前端学习--js.2

版权声明:yx全栈学习 https://blog.csdn.net/qq_43671996/article/details/84229369
  1. 写一个通用的事件侦听器函数
  1.  markyun.Event = {  
  2.       // 页面加载完成后  
  3.       readyEvent : function(fn) {  
  4.           if (fn==null) {  
  5.               fn=document;  
  6.           }  
  7.           var oldonload = window.onload;  
  8.           if (typeof window.onload != 'function') {  
  9.               window.onload = fn;  
  10.           } else {  
  11.               window.onload = function() {  
  12.                   oldonload();  
  13.                   fn();  
  14.               };  
  15.           }  
  16.       },  
  17.       // 视能力分别使用dom0||dom2||IE方式 来绑定事件  
  18.       // 参数: 操作的元素,事件名称 ,事件处理程序  
  19.       addEvent : function(element, type, handler) {  
  20.           if (element.addEventListener) {  
  21.               //事件类型、需要执行的函数、是否捕捉  
  22.               element.addEventListener(type, handler, false);  
  23.           } else if (element.attachEvent) {  
  24.               element.attachEvent('on' + type, function() {  
  25.                   handler.call(element);  
  26.               });  
  27.           } else {  
  28.               element['on' + type] = handler;  
  29.           }  
  30.       },  
  31.       // 移除事件  
  32.       removeEvent : function(element, type, handler) {  
  33.           if (element.removeEnentListener) {  
  34.               element.removeEnentListener(type, handler, false);  
  35.           } else if (element.datachEvent) {  
  36.               element.detachEvent('on' + type, handler);  
  37.           } else {  
  38.               element['on' + type] = null;  
  39.           }  
  40.       },   
  41.       // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)  
  42.       stopPropagation : function(ev) {  
  43.           if (ev.stopPropagation) {  
  44.               ev.stopPropagation();  
  45.           } else {  
  46.               ev.cancelBubble = true;  
  47.           }  
  48.       },  
  49.       // 取消事件的默认行为  
  50.       preventDefault : function(event) {  
  51.           if (event.preventDefault) {  
  52.               event.preventDefault();  
  53.           } else {  
  54.               event.returnValue = false;  
  55.           }  
  56.       },  
  57.       // 获取事件目标  
  58.       getTarget : function(event) {  
  59.           return event.target || event.srcElement;  
  60.       },  
  61.       // 获取event对象的引用,取到事件的所有信息,确保随时能使用event;  
  62.       getEvent : function(e) {  
  63.           var ev = e || window.event;  
  64.           if (!ev) {  
  65.               var c = this.getEvent.caller;  
  66.               while (c) {  
  67.                   ev = c.arguments[0];  
  68.                   if (ev && Event == ev.constructor) {  
  69.                       break;  
  70.                   }  
  71.                   c = c.caller;  
  72.               }  
  73.           }  
  74.           return ev;  
  75.       }  
  76.   };  

 

 

67、["1", "2", "3"].map(parseInt) 答案是多少?

[1,NaN,NaN]

 

68关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?

 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为。  
事件处理机制:IE是事件冒泡、火狐是 事件捕获;
ev.stopPropagation();

 

69什么是闭包(closure),为什么要用它?

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

闭包的特性:

(1)函数内再嵌套函数
(2)内部函数可以引用外层的参数和变量
(3)参数和变量不会被垃圾回收机制回收

 

HTML:

<!-- li节点的onclick事件都能正确的弹出当前被点击的li索引 -->
<ul id="testUL">

  <li> index = 0</li>

  <li> index = 1</li>

  <li> index = 2</li>

  <li> index = 3</li></ul>

 

JS:

<script type="text/javascript">

  var nodes = document.getElementsByTagName("li");

  for(i = 0;i<nodes.length;i+= 1){

    nodes[i].onclick = (function(i){

      return function() {

        console.log(i);

      } //不用闭包的话,值每次都是4    })(i);

  }</script>

 


然后我们看看下面的一段代码,这是对闭包作用的非常直白的描述:

function say667() {// Local variable that ends up within closure

  var num = 666;

  var sayAlert = function() {

    alert(num);

  }

  num++;

  return sayAlert;

}var sayAlert = say667();

sayAlert()//执行结果应该弹出的667

 

执行say667()后,say667()闭包内部变量会存在,而闭包内部函数的内部变量不会存在
使得Javascript的垃圾回收机制GC不会收回say667()所占用的资源
因为say667()的内部函数的执行需要依赖say667()中的变量

 

 

  1. javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?

除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。

为什么用严格模式

- 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

- 消除代码运行的一些不安全之处,保证代码运行的安全;

- 提高编译器效率,增加运行速度;

- 为未来新版本的Javascript做好铺垫。

"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。

另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员。

 

进入标志

"use strict";

 

如何调用

(1)针对单个脚本

 <script>
    "use strict";
    console.log("这是严格模式。");
  </script>

(2)针对单个函数

function strict(){
    "use strict";
    return "这是严格模式。";
  }
  function notStrict() {
    return "这是正常模式。";
  }

 

语法与行为改变

严格模式对Javascript的语法和行为,都做了一些改变。

5.1 全局变量显式声明

在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。

"use strict";
  v = 1; // 报错,v未声明
  for(i = 0; i < 2; i++) { // 报错,i未声明
  }

因此,严格模式下,变量都必须先用var命令声明,然后再使用。 禁止this关键字指向全局对象

function f(){
    return !this;
  } 
  // 返回false,因为"this"指向全局对象,"!this"就是false
  function f(){ 
    "use strict";
    return !this;
  } 
  // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。

function f(){
    "use strict";
    this.a = 1;
  };
  f();// 报错,this未定义

 

禁止删除变量

严格模式下无法删除变量。只有configurable设置为true的对象属性,才能被删除。

"use strict";
  var x;
  delete x; // 语法错误
  var o = Object.create(null, {'x': {
      value: 1,
      configurable: true
  }});
  delete o.x; // 删除成功

对象不能有重名的属性

正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。

"use strict";
  var o = {
    p: 1,
    p: 2
  }; // 语法错误

函数不能有重名的参数

正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。

 "use strict";
  function f(a, a, b) { // 语法错误
    return ;
}
 
 
 

71、如何判断一个对象是否属于某个类?

javascript中检测对象的类型的运算符有:typeof、constructor、instanceof。

typeof:typeof是一个一元运算符,返回结果是一个说明运算数类型的字符串。如:"number","string","boolean","object","function","undefined"(可用于判断变量是否存在)。 但 typeof 的能力有限,其对于Date、RegExp、Array类型返回的都是"object"。所以它只在区别对象和原始类型的时候才有用。要区一种对象类型和另一种对象类型,必须使用其他的方法。

instanceof 运算符:instanceof 运算符要求其左边的运算数是一个对象,右边的运算数是对象类的名字或构造函数。如果 object 是 class 或构造函数的实例,则 instanceof 运算符返回 true。如果 object 不是指定类或函数的实例,或者 object 为 null,则返回 false。instanceof方法可以判断变量是否是数组类型,但是只限同一全局环境之内,在一个页面有多个iframe的情况下,instanceof失效。


constructor 属性: JavaScript中,每个对象都有一个constructor属性,它引用了初始化该对象的构造函数,常用于判断未知对象的类型。如给定一个求知的值 通过typeof运算符来判断它是原始的值还是对象。如果是对象,就可以使用constructor属性来判断其类型。

 

Object.prototype.toString.call():该方法是目前为止发现的判断一个对象类型的最好的办法。

 

 

 

72Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?

hasOwnProperty

 

 

73[].forEach.call($$("*"),function(a){ a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16) }) 能解释一下这段代码的意思吗?

(1)call:call(thisObj,arg1,arg2,arg3)

1

[].forEach.call($$("*"),

  就是用$$('a')来替代[],

好 那么到了第二个问题$$('a')是什么意思

(2)$$('a')

你可以在自己的浏览器上面运行一下,就是页面上所有的a标签

然后再继续

(3)function(a){}

无疑就是$$('a')组成的数组要进行的回调函数了

好我们再看里面的东西

(4)~~

看在浏览器上面的运行

1

2

3

4

5

6

7

8

var a=12.233

~~a

12

 

 

var b=-123.455

~~b

-123

  所以~~的作用就相当于parseInt

 

  1. js延迟加载的方式有哪些?

js的延迟加载有助与提高页面的加载速度,以下是延迟加载的几种方法:

(1)使用setTimeout延迟方法的加载时间

延迟加载js代码,给网页加载留出更多时间

<script type="text/javascript" >
    function A(){
        $.post("/lord/login",{name:username,pwd:password},function(){
            alert("Hello");
        });
    }
    $(function (){
        setTimeout('A()', 1000); //延迟1秒
    })</script>

(2)让js最后加载

例如引入外部js脚本文件时,如果放入html的head中,则页面加载前该js脚本就会被加载入页面,而放入body中,则会按照页面从上倒下的加载顺序来运行javascript的代码~~~ 所以我们可以把js外部引入的文件放到页面底部,来让js最后引入,从而加快页面加载速度

(3)上述方法2也会偶尔让你收到Google页面速度测试工具的“延迟加载javascript”警告。所以这里的解决方案将是来自Google帮助页面的推荐方案。

//这些代码应被放置在</body>标签前(接近HTML文件底部)<script type="text/javascript">
    function downloadJSAtOnload() {
        var element = document.createElement("script");
        element.src = "defer.js";
        document.body.appendChild(element);
    }
    if (window.addEventListener)
        window.addEventListener("load", downloadJSAtOnload, false);
    else if (window.attachEvent)
        window.attachEvent("onload", downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;</script>

这段代码意思是等到整个文档加载完后,再加载外部文件“defer.js”。 
使用此段代码的步骤: 
1).复制上面代码

2).粘贴代码到HTML的标签前 (靠近HTML文件底部)

3).修改“defer.js”为你的外部JS文件名

4).确保你文件路径是正确的。例如:如果你仅输入“defer.js”,那么“defer.js”文件一定与HTML文件在同一文件夹下。

注意:这段代码直到文档加载完才会加载指定的外部js文件。因此,不应该把那些页面正常加载需要依赖的javascript代码放在这里。而应该将JavaScript代码分成两组。一组是因页面需要而立即加载的javascript代码,另外一组是在页面加载后进行操作的javascript代码(例如添加click事件或其他东西)。这些需等到页面加载后再执行的JavaScript代码,应放在一个外部文件,然后再引进来。

 

 

75、同步和异步的区别?

同步:

同步的思想是:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的感觉)。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。

 

异步:

将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。但是用户没有卡死的感觉,会告诉你,你的请求系统已经响应了。你可以关闭界面了。

 

同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,在相应用户,用户体验不好。

异步,不用等所有操作等做完,就相应用户请求。即先相应用户请求,然后慢慢去写数据库,用户体验较好。

 

异步操作例子:

为了避免短时间大量的数据库操作,就使用缓存机制,也就是消息队列。先将数据放入消息队列,然后再慢慢写入数据库。

引入消息队列机制,虽然可以保证用户请求的快速响应,但是并没有使得我数据迁移的时间变短(即80万条数据写入mysql需要1个小时,用了redis之后,还是需要1个小时,只是保证用户的请求的快速响应。用户输入完http url请求之后,就可以把浏览器关闭了,干别的去了。如果不用redis,浏览器不能关闭)。

 

同步就没有任何价值了吗?

银行的转账功能。

 

 

76、页面编码和被请求的资源编码如果不一致如何处理?

s编码和页面编码不一致,导致提示变量未定义的解决方法 (2011-06-30 10:27:02)转载▼
标签: js跨域 变量未定义 js编码 it 分类: JS
今天在测试项目的时候,由于是和其他站合作的,引用合作方的js文件,
有个js函数调用,调用时会使用包含合作方js里的变量,
可是竟然不兼容ie6、ie7、360等主流浏览器。那必须得解决是吧。
原本以为是跨域问题,如果是跨域问题,也应该提示没权限,可是没提示。

提示的是某某变量未定义,我就百度了。 没找到我想要的答案,
灵机一动想到是不是编码问题 。于是在js后加了 charset="utf-8" 这个 。

发现还真好了。 。 绕了好些圈子 。 这次记下了。避免下次再遇到类似的状况。

比如:http://www.yyy.com/a.html 中嵌入了一个http://www.xxx.com/test.js

a.html 的编码是gbk或gb2312的。 而引入的js编码为utf-8的 ,那就需要在引入的时候

<script src="http://www.xxx.com/test.js" charset="utf-8"></script>
同理,如果你的页面是utf-8的,引入的js是gbk的,那么就需要加上charset="gbk".

 

 

77、AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?

AMD

AMD规范其实只有一个主要接口 define(id,dependencies,factory),它要在声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行,依赖前置

[javascript] view plain copy  

  1. define("module", ["dep1""dep2"], function(d1, d2) {  
  2.   return someExportedValue;  
  3. });  
  4. require(["module""../file"], function(module, file) { /* ... */ });  

优点:

适合在浏览器环境异步加载

并行加载多个模块

缺点:

提高开发成本,代码阅读和书写比较困难

不符合通用的模块思维方式,是一种妥协的实现

CMD

CMD规范和AMD相似,尽量保持简单,并且与CommonJS和NodeJS的Modules规范保持了很大的兼容性。

[javascript] view plain copy  

  1. define(function(require, exports, module) {  
  2.   var $ = require('jquery');  
  3.   var Spinning = require('./spinning');  
  4.   exports.doSomething = ...  
  5.   module.exports = ...  
  6. })  

优点:

依赖就近,延迟执行

很容易在node中运行

缺点:

依赖SPM打包,模块的加载逻辑偏重

 

 

 

78、谈一谈你对ECMAScript6的了解?

ES6 包含了很多新的语言功能,且这些语言功能使得 JS 更加强大更富有表现力。

ECMAScript 的范围是什么?

JavaScript 编程语言是由 ECMAScript 名下的 ECMA 进行标准化制定的( ECMA 是和 W3C 一样的标准化组织 )。除此之外,ECMAScript 可如下定义:

语法-解析规则,关键字,语句,声明,操作等等。

类型-布尔型,数字,字符串,对象等等。

原型和继承。

内置对象和函数的标准库 - JSON ,数学( Math ), 数组方法( Array methods ),对象内省的方法( Object introspection methods )等等。

其没有定义与 HTML 、CSS 或者 Web API 交互的内容,比如 DOM ( 文档对象模型 )。那些都是在单独的标准中定义的。 ECMAScript 不仅在浏览器环境中的涵盖了 JS 的所有方面,其在非浏览器环境中也涵盖了 JS ,例如 node.js 。

新的标准

上周, ECMAScript 语言规范的最终草案,第 6 版,被提交给 ECMA 大会进行审查。这意味着什么呢?

这意味着这个夏天,对于核心的 JavaScript 编程语言,我们将有一个新的标准。

这是一个大新闻。新的 JS 语言不是每天都可能出现的。 上一个版本,ES5,可以追溯到 2009 年。从那时起,ES 标准委员会就一直致力于 ES6 的制定直至今日。

ES6 是语言的一次重大的升级。同时,你的 JS 代码也可以继续工作。ES6 被设计为可以最大程度兼容现有的代码。事实上,很多浏览器已经支持丰富的 ES6 的功能,同时实现工作也正在进行中。这就意味着你所有的 JS 代码已经可以在那些实现一些 ES6 功能的浏览器里面运行!如果你到现在还没有看到任何兼容性问题,你可能永远也不会碰到这些问题了。

计数到 6

ECMAScript 标准的先前的版本分别编号为 1,2,3 和 5。

第四版本发生了什么?第 4 版的 ECMAScript 曾是在计划之中的,并且事实上大量的工作也已经完成了。但由于它过于的繁琐,其最终被废弃了。 ( 例如,它在静态类型系统中对泛型和类型推断有一个复杂的选择。)

ES4 是有争议的。当标准委员会最终停止继续制定时,该委员会成员同意出版一个相对温和的 ES5 ,然后继续工作以制定更多的有较大幅度改进的新功能。这个直接通过谈判达成的协议被称为“和谐(Harmony)”,这也是为什么 ES5 规范包含这两句话:

ECMAScript 是一个充满活力的语言且其语言的演化还不完整。在未来的 ECMAScript 的版本中将有较大提升的技术的声明。

这种说法也可以被看作是委员会给出的一个承诺。

兑现承诺

ES5 在 2009 年对语言进行了更新,其介绍了 Object.create( ), Object.defineProperty( ), getter 和 setter 方法​​,strict 模式和 JSON 对象。我已经使用了所有的这些功能,而且我喜欢 ES5 对语言做出的贡献。但是, 这些功能中的任何一种都没有对我写 JS 代码的方式产生巨大的影响。对我来说其最重要的创新,很可能是新的数组方法:.MAP,filter 等等。

然而,ES6 是决然不同的。它是多年和谐工作的产物。 同时,它是新的语言和库功能的宝库,其是迄今为止 JS 的最实质性的升级。 其新功能涵盖面很广,从那些很受欢迎的能带来便利的功能(如箭头的功能和简单的字符串插值),到能带来头脑风暴的概念(如代理和生成器)。

ES6 将改变你写 JS 代码的方式。

本系列旨在向你展示 ES6 如何通过检查其新功能来给JavaScript程序员提供新的写代码体验。

我们将以一个典型的“功能缺失”作为开始。“功能缺失”是我在过去的十年的时间内一直渴望能从 JavaScript 那看到的。所以,让我们一起去探索 ES6 迭代器和新的 for-of 循环。

 

79、ECMAScript6 怎么写class么,为什么会出现class这种东西?

ES6 的 class 有优点也有缺点,整体说来,是利大于弊的,推荐使用。

缺点主要有:
(1)语法和语义难对上了,也就是说从书写出来的代码是看不出来内部是通过原型实现相关功能点的。
(2)类的写法有一定的限制性,不再像原型那么灵活了。

优点主要有:

(1)语法更加紧凑,更加符合传统面相对象的写法了。
(2)使 IDE 、类型检查器、代码风格检查器等工具更方便地检测代码语法,做静态分析。
(3) ES6 的类可以继承内置类,并使某些属性和内置类有一样的行为。比如可以继承 Array ,并且子类的 length 属性和 Array 的 length 属性一样会随着元素个数的变化而自动变化。
(4)兼容以前的代码。
(5)使初学者入门更快。
(6)不再需要第三方的继承库。

最后, ES6 的类只是一个基础形式,后续 ECMAScript 版本还会继续添加一些内容进去,比如 trait 、不可变实例等。

其实,从多人开发的大型项目来看,其中使用的大多数语言都包含了类这个元素,并且类在这些项目中还被广泛使用。这就说明类有利于多人大型项目的开发。而 ES6 引入类,也表明了现在的 js 项目越来越复杂了,同时也为 js 在服务器端舞台上大放异彩奠定基础。

 

 

80、documen.write和 innerHTML的区别?

(1).write是DOM方法,向文档写入HTML表达式或JavaScript代码,可列出多个参数,参数被顺序添加到文档中 ;innerHTML是DOM属性,设置或返回调用元素开始结束标签之间的HTML元素。

(2)两者都可向页面输出内容,innerHTML比document.write更灵活。

当文档加载时调用document.write直接向页面输出内容,文档加载结束后调用document.write输出内容会重写整个页面。通常按照两种的方式使用 write() 方法:一是在使用该方在文档中输出 HTML,二是在调用该方法的的窗口之外的窗口、框架中产生新文档(务必使用close关闭文档)。

在读模式下,innerHTML属性返回与调用元素的所有子节点对应的HTML标记,在写模式下,innerHTML会根据指定的值创建新的DOM树替换调用元素原先的所有子节点。

(3)两者都可动态包含外部资源如JavaScript文件

通过document.write插入<script>元素会自动执行其中的脚本;

大多数浏览器中,通过innerHTML插入<script>元素并不会执行其中的脚本。

 

 

81、JS 怎么实现一个类。怎么实例化这个类

严格的说,JavaScript 是基于对象的编程语言,而不是面向对象的编程语言。

在面向对象的编程语言中(如Java、C++、C#、PHP等),声明一个类使用 class 关键字。

例如:

  1. public class Person{}


但是在JavaScript中,没有声明类的关键字,也没有办法对类的访问权限进行控制。

JavaScript 使用函数来定义类。


语法:
function className(){
    // 具体操作
}


例如,定义一个Person类:

function Person() {

    this.name=" 张三 ";  // 定义一个属性 name

    this.sex=" 男 ";  // 定义一个属性 sex

    this.say=function(){  // 定义一个方法 say()

        document.write("嗨!大家好,我的名字是 " + this.name + " ,性别是 " + this.sex + "。");

    }

}

说明:this 关键字是指当前的对象。

创建对象(类的实例化)

创建对象的过程也是类实例化的过程。
在JavaScript中,创建对象(即类的实例化)使用 new 关键字。

语法:
new className();
将上面的 Person 类实例化:

var zhangsan=new Person();

zhangsan.say();

运行代码,输出如下内容:
    嗨!大家好,我的名字是 张三 ,性别是 男 。

定义类时可以设置参数,创建对象时也可以传递相应的参数。

下面,我们将Person类重新定义:

function Person(name,sex) {

    this.name=name;  // 定义一个属性 name

    this.sex=sex;  // 定义一个属性 sex

    this.say=function(){  // 定义一个方法 say()

        document.write("嗨!大家好,我的名字是 " + this.name + " ,性别是 " + this.sex);

    }

}

var zhangsan=new Person("小丽","女");

zhangsan.say();

运行代码,输出如下内容:
    嗨!大家好,我的名字是 小丽 ,性别是 女 。

 

 

 

  1. jquery中如何将数组转化为json字符串,然后再转化回来?
    现代浏览器中提供了JSON.stringify()方法 将数组,对象转成json。
    JSON.stringify 把一个对象转换成json字符串, 
    JSON.parse 把一个json字符串解析成对象。
    不支持的可以引入json2.js

$.fn.stringifyArray = function(array) {

  return JSON.stringify(array)

}

 

$.fn.parseArray = function(array) {

  return JSON.parse(array)

}

 

然后调用:

$("").stringifyArray(array)

 

 

83、jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?

语法:jQuery.extend( [deep ], target, object1 [, objectN ] )

描述: 将两个或更多对象的内容合并到第一个对象。

关于$.extend()的用法网上有很多文章,在这里指向写写对深浅拷贝的理解

深浅拷贝对应的参数就是[deep],是可选的,为true或false。默认情况是false(浅拷贝),并且false是不能够显示的写出来的。如果想写,只能写true(深拷贝)~~

什么是深、浅拷贝呢?先讲定义,再举例子

在默认情况下,通过$.extend()合并操作不是递归的(浅拷贝);如果第一个对象的属性本身是一个对象或数组,那么它将完全用第二个对象相同的key重写一个属性。这些值不会被合并。然而,如果将 true 作为该函数的第一个参数,那么会在对象上进行递归的合并(深拷贝)。

浅拷贝(false 默认):如果第二个参数对象有的属性第一个参数对象也有,那么不会进行相同参数内部的比较,直接将第一个对象的相同参数覆盖。

深拷贝(true):如果第二个参数对象有的属性第一个参数对象也有,还要继续在这个相同的参数向下一层找,比较相同参数的对象中是否还有不一样的属性,如果有,将其继承到第一个对象,如果没有,则覆盖。

 

var object1 = {
    apple: 0,
    banana: {
        weight: 52,
        price: 100
    },
    cherry: 97
};var object2 = {
    banana: {
        price: 200
    },
    durian: 100
};
//默认情况浅拷贝
//object1--->{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
//object2的banner覆盖了object1的banner,但是weight属性未被继承
//$.extend(object1, object2);
//深拷贝
//object1--->{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}
//object2的banner覆盖了object1的banner,但是weight属性也被继承了呦
$.extend(true,object1, object2);
 
console.log('object1--->'+JSON.stringify(object1));

 

 

84、jquery.extend 与 jquery.fn.extend的区别?

(1). jQuery.extend(object); 

它是为jQuery类添加类方法,可以理解为添加静态方法。如:

a.jQuery.extend({

  min: function(a, b) { return a < b ? a : b; },

  max: function(a, b) { return a > b ? a : b; }

});

jQuery.min(2,3); //  2 
jQuery.max(4,5); //  5


b. jQuery.extend(target, object1, [objectN])用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
var settings = { validate: false, limit: 5, name: "foo" }; 
var options = { validate: true, name: "bar" }; 
jQuery.extend(settings, options);


结果:settings == { validate: true, limit: 5, name: "bar" }

 

(2). jQuery.fn.extend(object);

$.fn是什么?

$.fn是指jQuery的命名空间,fn上的成员(方法function及属性property),会对jQuery实例每一个有效。 

查看jQuery代码,就不难发现。

jQuery.fn = jQuery.prototype = {

   init: function( selector, context ) {//.... 

};

原来 jQuery.fn = jQuery.prototype.

所以,它是对jQuery.prototype进得扩展,就是为jQuery类添加“成员函数”。jQuery类的实例可以使用这个“成员函数”。

比如我们要开发一个插件,做一个特殊的编辑框,当它被点击时,便alert 当前编辑框里的内容。可以这么做:

$.fn.extend({          
     doAlertWhileClick:function() {            
           $(this).click(function(){                 
                  alert($(this).val());           
            });           
      }       
});       
$("#input1").doAlertWhileClick(); //
页面上为:    

$("#input1") 为一个jQuery实例,当它调用成员方法 doAlertWhileClick后,便实现了扩展,每次被点击时它会先弹出目前编辑里的内容。

 

 

85、谈一下Jquery中的bind(),live(),delegate(),on()的区别?

bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数

$("a").bind("click",function(){alert("ok");});

live(type,[data],fn) 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的

$("a").live("click",function(){alert("ok");});

delegate(selector,[type],[data],fn) 指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数

$("#container").delegate("a","click",function(){alert("ok");})

on(events,[selector],[data],fn) 在选择元素上绑定一个或多个事件的事件处理函数

差别:

.bind()是直接绑定在元素上

.live()则是通过冒泡的方式来绑定到元素上的。更适合列表类型的,绑定到document DOM节点上。和.bind()的优势是支持动态数据。

.delegate()则是更精确的小范围使用事件代理,性能优于.live()

.on()则是最新的1.9版本整合了之前的三种方式的新事件绑定机制

 

 

86、JQuery一个对象可以同时绑定多个事件,这是如何实现的?

  • jQuery("#id").click(func1).mouseover(func2)//方法连写,func为方法的名字
  • jQuery("#id").click(function(){//你的具体方法实现}),mouser(function(){//你的具体方法实现});
  • jQuery("#id").bind("click mouseover",func)//两个事件中间有空格 ,func为方法的名字
  • jQuery("#id").bind("load scroll",function(){//你的具体方法实现});

 

 

87、是否知道自定义事件。jQuery里的fire函数是什么意思,什么时候用?

1种是把那个函数放到ready函数外面。 第2种是在ready函数里面加上window.deleteStu = deleteStu; 即: $(function(){ function deleteStu(id){ alert(id); } window.deleteStu = deleteStu; }
 
  1. jQuery 是通过哪个方法和 Sizzle 选择器结合的?

什么是jQuery选择器?

jQuery选择器通俗来讲就是一个获取html元素的工具。比如,$("p") 选取 <p> 元素,$("p")是jQuery的选择器的写法,这么写就可以获取(选取)html里的<p>元素。

jQuery选择器包括元素选择器、属性选择器、CSS选择器。(个人感觉这个分类比较扯淡)

注意:属性选择器的意思并不是选择属性,而是根据属性选择元素。

 

什么叫html元素?什么是属性?

html代码里的开始标签+内容+结束标签就构成一个元素,英文是element。

<p>这是一个标签,</p>这也是一个标签,英文是tag。

<p>XXX</p>这就是一个元素。

特殊的<br/>这也是一个标签。

属性估计大家都清楚,比如标签<body bgcolor="red">中,bgcolor="red"就是属性。

也就是说,属性是在标签中的;而在不混淆的情况下,我们经常把元素称作为标签(部分人包括我经常这样),也不是一个很大的问题。

 

不用jQuery选择器的话是如何实现该功能的?

如果不用jQeury,简单的元素选择器的一般原生js写法是:getElementById()、getElementByClassName()等函数获取元素。在这种情况下,$的作用仅仅是简化了代码的书写方法。

当然,这只是最简单的情况下。$写法的在这种情况下其实也是调用getElementById(),但复杂情况则通过jQuery选择器的复杂实现。

 

jQuery选择器是如何实现的?

w3c上说:jQuery 使用 CSS 选择器来选取 HTML 元素。。

 

什么是sizzle?

sizzle是一个纯js的CSS选择器引擎(A pure-JavaScript CSS selector engine)。最新版本是2.1.1(jquery-sizzle-2.1.1-jquery.2.1.2-11-gf8ef711.zip)。

它是jQuery官网的一部分。(jQuery官网一共有5部分:jQuery、jQueryUI、jQueryMobile、Sizzle、QUnit)但它是独立的,虽然jQuery本身使用sizzle,但是你完全可以在不使用jQuery的情况下使用sizzle。

 

 

89、针对 jQuery性能的优化方法?

(1)总是使用#id去寻找element.

在jQuery中最快的选择器是ID选择器 ($('#someid')). 这是因为它直接映射为JavaScript的getElementById()方法。
选择单个元素

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<div id="content">

 

 <form method="post" action="/">

 

  <h2>Traffic Light</h2>

 

  <ul id="traffic_light">

 

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

 

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

 

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

 

  </ul>

 

  <input class="button" id="traffic_button" type="submit" value="Go" />

 

 </form>

 

</div>

选择button的性能不好的一种方式:

 

1

var traffic_button = $('#content .button');

取而代之的是直接选择button:

 

1

var traffic_button = $('#traffic_button');

选择多个元素

在我们讨论选择多个元素的时候,我们真正需要知道的是DOM的遍历和循环才是性能低下的原因。为了尽量减少性能损失, 总是使用最近的父ID去寻找。

 

1

var traffic_lights = $('#traffic_light input');

 

 

(2)在Classes前面使用Tags

在jQuery中第二快的选择器就是Tag选择器 ($('head')). 而这是因为它直接映射到JavaScript的getElementsByTagName()方法。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<div id="content">

 

 <form method="post" action="/">

 

  <h2>Traffic Light</h2>

 

  <ul id="traffic_light">

 

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

 

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

 

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

 

  </ul>

 

  <input class="button" id="traffic_button" type="submit" value="Go" />

 

 </form>

 

</div>

总是在一个Class前面加上一个tag名字(记得从一个ID传下来)

 

1

var active_light = $('#traffic_light input.on');

注意:在jQuery里Class选择器是最慢的一个选择器;在IE中它循环整个DOM。可能的话尽量避免使用它。不要在ID前面 加Tags。例如,它会因为去循环所有的<div>元素去寻找ID为content的<div>,而导致很慢。

 

1

var content = $('div#content');

按照同样的思路,从多个ID传下来是冗余的。

 

1

var traffic_light = $('#content #traffic_light');

 

 

 

(3)缓存jQuery对象

养成保存jQuery对象到一个变量上(就像上面的例子)的习惯。例如,不要这样做:

?

1

2

3

4

5

6

7

$('#traffic_light input.on).bind('click', function(){...});

 

$('#traffic_light input.on).css('border', '3px dashed yellow');

 

$('#traffic_light input.on).css('background-color', 'orange');

 

$('#traffic_light input.on).fadeIn('slow');

取而代之,首现保存jQuery变量到一个本地变量后,再继续你的操作。

 

1

2

3

4

5

6

7

8

9

var $active_light = $('#traffic_light input.on');

  

$active_light.bind('click', function(){...});

  

$active_light.css('border', '3px dashed yellow');

  

$active_light.css('background-color', 'orange');

  

$active_light.fadeIn('slow');

提示:使用$前辍表示我们的本地变量是一个jQuery包集。记住,不要在你的应该程序里出现一次以上的jQuery重复的选择操作。 额外提示:延迟存储jQuery对象结果。

如果你想在你的程序的其它地方使用jQuery结果对象(result object(s)),或者你的函数要执行多次,要把它缓存在一个全局范围的对象里。通过定义一个全局容器保存jQuery结果对象,就可以在其它的函数里引用它。

 

// Define an object in the global scope (i.e. the window object)

 

window.$my ={

 

 // Initialize all the queries you want to use more than once

 

 head : $('head'),

 

 traffic_light : $('#traffic_light'),

 

 traffic_button : $('#traffic_button')};

 

function do_something(){

 

 // Now you can reference the stored results and manipulate them

 

 var script = document.createElement('script');

 

 $my.head.append(script);

 

 // When working inside functions, continue to save jQuery results

 

 // to your global container.

 

 $my.cool_results = $('#some_ul li');

 

 $my.other_results = $('#some_table td');

 

 // Use the global functions as you would a normal jQuery result

 

 $my.other_results.css('border-color', 'red');

 

 $my.traffic_light.css('border-color', 'green');

 

}

 

 

(4)更好的利用链

前面的例子也可以这样写:

 

1

2

3

4

5

6

7

8

9

var $active_light = $('#traffic_light input.on');

 

$active_light.bind('click', function(){...})

 

 .css('border', '3px dashed yellow')

 

 .css('background-color', 'orange')

 

 .fadeIn('slow');

这样可以让我们写更少的代码,使JavaScript更轻量。

 

 

(5)使用子查询

jQuery允许我们在一个包集上附加其它的选择器。因为我们已经在本地变量里保存了父对象这样会减少以后在选择器上的性能开销。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<div id="content">

 

 <form method="post" action="/">

 

  <h2>Traffic Light</h2>

 

  <ul id="traffic_light">

 

   <li><input type="radio" class="on" name="light" value="red" /> Red</li>

 

   <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

 

   <li><input type="radio" class="off" name="light" value="green" /> Green</li>

 

  </ul>

 

  <input class="button" id="traffic_button" type="submit" value="Go" />

 

 </form>

 

</div>

例如,我们可以利用子查询缓存active和inactive lights以便后面的操作。

?

1

2

3

4

5

var $traffic_light = $('#traffic_light'),

 

$active_light = $traffic_light.find('input.on'),

 

$inactive_lights = $traffic_light.find('input.off');

提示:可以用逗号隔开一次定义多个本地变量,这样可以节省一些字节。

 

 

(6)限制直接对DOM操作

DOM操作的基本做法是在内存中创建DOM结构,然后再更新DOM结构。这不是jQuery最好的做法,但对JavaScript来讲是高效的。直接操作DOM结构性能是低下的。 例如,如果你需要动态创建一列元素,不要这样做:

?

1

2

3

4

5

6

7

8

9

var top_100_list = [...], // assume this has 100 unique strings

 

$mylist = $('#mylist'); // jQuery selects our <ul> element

 

for (var i=0, l=top_100_list.length; i<l; i++){

 

 $mylist.append('<li>' + top_100_list[i] + '</li>');

 

}

取而代之,我们希望在插入DOM结构之前先在一个字符串里创建一套元素。
代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

var top_100_list = [...], // assume this has 100 unique strings

 

$mylist = $('#mylist'), // jQuery selects our <ul> element

 

top_100_li = ""; // This will store our list items

 

for (var i=0, l=top_100_list.length; i<l; i++){

 

 top_100_li += '<li>' + top_100_list[i] + '</li>';

 

}

 

$mylist.html(top_100_li);

更快的做法,在插入DOM结构之前我们应该总是在一个父节点里包含许多元素

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

var top_100_list = [...], // assume this has 100 unique strings

 

$mylist = $('#mylist'), // jQuery selects our <ul> element

 

top_100_ul = '<ul id="#mylist">'; // This will store our entire unordered list

 

for (var i=0, l=top_100_list.length; i<l; i++){

 

 top_100_ul += '<li>' + top_100_list[i] + '</li>';

 

}

 

top_100_ul += '</ul>'; // Close our unordered list

 

$mylist.replaceWith(top_100_ul);

如是你照着上面的做了还是对性能有些迷惑的话,可以参考以下内容:

* 试一下jQuery提供的Clone()方法。Clone()方法创建节点数的拷贝,随后你可以在这个副本中进行操作。

* 使用DOM DocumentFragments. As the creator of jQuery points out, 比直接操作DOM性能上更好. 先创建你需要的结构(就像我们上面用一个字符串做的一样), 然后使用jQuery的 insert or replace methods.

 

 

(7)事件委托(又名:冒泡事件)

除非特别说明,每一个JavaScript事件(如click, mouseover 等)在DOM结构树上都会冒泡到它的父元素上。如果我们想让很多elements(nodes)调用同一个function这是非常有用的。取而代之的是 你可以只对它们的父级绑定一次,而且可以计算出是哪一个节点触发了事件,而不是绑定一个事件监听器到很多节点上这种效率低下的方式。例如,假如我们要开发 一个包含很多input的大型form,当input被选择的时候我们想绑定一个class name。像这样的帮定是效率低下的:

 

1

2

3

4

5

$('#myList li).bind('click', function(){

 

 $(this).addClass('clicked'); // do stuff

 

});

反而,我们应该在父级侦听click事件。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

$('#myList).bind('click', function(e){

 

 var target = e.target, // e.target grabs the node that triggered the event.

 

  $target = $(target); // wraps the node in a jQuery object

 

 if (target.nodeName === 'LI') {

 

  $target.addClass('clicked');  // do stuff

 

 }

 

});

父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。

 

 

 

(8)消除查询浪费

虽然jQuery对没有找到任何匹配的elements处理的很好,但是它还是需要花费时间去查找的。如果你的站点有一个全局的JavaScript,你可能会把每个jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要这样做。只去放一些页面上适合用到的function。这样做最有效的方式是你的模板可以完全控制任何时候或者地方执行JavaScript以内联脚 本的方式初始化function。例如,在你的“article”页面模板里,你可能在body标签关闭之前包含以下代码

<script type="text/javascript>mylib.article.init();</script></body& gt;如果你的页面模板包含多种有可能在页面或者不在页面上的模块,或者为了可视化效果你需要它们稍后再初如化,你应该在这些模块之后立即放置初如化函数。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

<ul id="traffic_light">

 

 <li><input type="radio" class="on" name="light" value="red" /> Red</li>

 

 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>

 

 <li><input type="radio" class="off" name="light" value="green" /> Green</li>

 

</ul>

 

 

 

<script type="text/javascript>mylib.traffic_light.init();</script>

你的全局JavaScript库看起来应该是这样的:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

var mylib ={

 

 article_page : {

 

  init : function()  {

 

   // Article page specific jQuery functions.

 

  }

 

 },

 

 traffic_light : {

 

  init : function()  {

 

   // Traffic light specific jQuery functions.

 

  }

 

 }

 

}

 

 

(9)遵从$(windows).load

有 一种诱惑会使jQuery开发者hook所有事情到 $(document).ready 这个虚伪的事件里。毕竟在大多数例子里都可以看到这样使用。虽然$(document).ready 非常有用,它在页面呈现时发生,虽然其它对象还在下载中。如果你发现你的页面在下载中停顿,就有可能是$(document).ready 引起的。你可以通过把jQuery functions帮定到$(window).load事件来减少下面下载时的CPU使用率,它是在所有HTML(包括iframe内容)都下载完以后才 去调用所有对象的。

 

1

2

3

4

5

$(window).load(function(){

 

 // jQuery functions to initialize after the page has loaded.

 

});

多余的功能,如拖拽、帮定可视化效果和动画、预读取图片等,使用这种方法比较好。

 

 

(10)压缩JS

虽然和jQuery无关,但在这里也要提一下。使JavaScript函数和变量变得可读是一个趋势,这对开发者来讲是必不可少的,但对普通用户来 讲没有任何关系。不用什么借口,是时候把JS压缩纳入我们的工作流程中来了。注释你的代码,在投放到生产环境之前找一个压缩工具进行压缩。使用 YUICompressor 压缩你代码中多余的浪费的字节。根据我们的经验,它可以安全的把JavaScript压缩的尽可能小,而不会多占用CPU。小提示:为了在 YUICompressor里最大化压缩,应该这样这样定义变量(例如:var my_long_variable_name;)

学习和最有效的使用jQuery,最好的方法就是去查jQuery的文档和手册了。

以上就是本文的全部内容,了解更多jQuery的语法,大家可以查看:《jQuery 1.10.3 在线手册》,也希望大家多多支持脚本之家。

 

 

90、Jquery与jQuery UI有啥区别?

jqueryui是jquery的一个插件,jquery是对javascript的封装,而jqueryui是一个基于jquery的一个UI方面的框架。

网上主流的说法是(1) jQuery是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等。  
 (2) jQueryUI则是在jQuery的基础上,利用jQuery的扩展性,设计的插件。提供了一些常用的界面元素,诸如对话框、拖动行为、改变大小行为等等。 
 (3) jQuery本身注重于
后台,没有漂亮的界面,而jQueryUI则补充了前者的不足,他提供了华丽的展示界面,使人更容易接受。既有强大的后台,又有华丽的前台。

个人觉得完全可以解释了。

在就是easyui了,也是最近刚刚接触到的,这么earyui和jquery有什么区别了?

jquery ui 是jquery开发团队 开发,适用于网站式的页面。jquery easyui 是第三方基于jquery开发,适用于应用程序式的页面。

jQueryUI: http://jqueryui.com/demos/tabs/#manipulation

jQuery自带的一个可选UI库,但是非常可惜,一些关键的组件没有包含进去,如TreeView, DataGrid,还需要寻找第三方的插件。

EasyUI:

是某公司开发的一套对私免费,对公收费的UI库,基于GNU开源协议,不过只有付费了才能买到他们的源代码。是目前枯人接触过最优秀的一款基于jQuery的UI库,整体打包后不到300k, 几乎包含所有的常用组件。

jQuery UI vs EasyUI: 二者冲突怎么办?

很不幸,jQueryUI和EasyUI的某些组件是命名冲突的,如 Dialog, Tabs等,我们之前的项目主要是基于jQueryUI, 如果使用EasyUI将重写以前的代码,后来我们采取了一种折中的方案:
进入http://jqueryui.com/download 定制jQuery组件,只保留jQueryUI中的Tabs, Dialog. (其他的如DatatimePicker等使用EasyUI重写);这样我们会得到一个只有40K的jQueryUI文件,我们认为还是可以接受的。
将精简后的jQueryUI加载到EasyUI引用之后,这样EasyUI的Tabs和Dialog就会被复写。

 

 

 

91、jQuery和Zepto的区别?各自的使用场景?

(1) Zepto 对象 不能自定义事件

  例如执行: $({}).bind('cust', function(){});
 结果:  TypeError: Object has no method 'addEventListener'
  解决办法是创建一个脱离文档流的节点作为事件对象:

  例如: $('').bind('cust', function(){});

 

(2)Zepto 的选择器表达式: [name=value]  中value 必须用 双引号 "  or 单引号 ' 括起来

  例如执行:$('[data-userid=123123123]')
         结果:Error: SyntaxError: DOM Exception 12

  解决办法: $('[data-userid="123123123]"') or $("[data-userid='123123123']")

 

2-1.zepto的选择器没有办法选出 $("div[name!='abc']") 的元素

 

 

 

2-2.zepto获取select元素的选中option不能用类似jq的方法$('option[selected]'),因为selected属性不是css的标准属性

    应该使用$('option').not(function(){ return !this.selected })
    比如:jq:$this.find('option[selected]').attr('data-v') * 1
 zepto:$this.find('option').not(function() {return !this.selected}).attr('data-v') * 1
   但是获取有select中含有disabled属性的元素可以用 $this.find("option:not(:disabled)") 因为disabled是标准属性

   参考网址:https://github.com/madrobby/zepto/issues/503

 

2-3、zepto在操作dom的selected和checked属性时尽量使用prop方法,以下是官方说明:


 

(3)Zepto 是根据标准浏览器写的,所以对于节点尺寸的方法只提供 width() 和 height(),省去了 innerWidth(), innerHeight(),outerWidth(),outerHeight()

Zepto.js: 由盒模型( box-sizing )决定
jQery: 忽略盒模型,始终返回内容区域的宽/高(不包含 padding 、 border )解决方式就是使用 .css('width') 而不是 .width() 。

 

3-1.边框三角形宽高的获取

假设用下面的 HTML 和 CSS 画了一个小三角形:

[html] view plain copy

  1. <div class="caret"></div>   
  2. .caret {  
  3.   width: 0;  
  4.   height: 0;  
  5.   border-width: 0 20px 20px;  
  6.   border-color: transparent transparent blue;   
  7.   border-style: none dotted solid;  
  8. }  

jQuery 使用 .width() 和 .css('width') 都返回 ,高度也一样;
Zepto 使用 .width() 返回 ,使用 .css('width') 返回 0px 。
所以,这种场景,jQuery 使用 .outerWidth() / .outerHeight() ;Zepto 使用 .width() / .height() 。

3-2.offset()

Zepto.js: 返回 top 、 left 、 width 、 height
jQuery: 返回 width 、 height

 

3-3.隐藏元素

Zepto.js: 无法获取宽高;
jQuery: 可以获取。

 

(4)Zepto 的each 方法只能遍历 数组,不能遍历JSON对象

 

(5)Zepto 的animate 方法参数说明 :详情点击-> 

zepto中animate的用法

 

(6)zepto的jsonp callback函数名无法自定义

 

(7)DOM 操作区别

jq代码:

[html] view plain copy

  1. (function($) {  
  2.   $(function() {  
  3.     var $list = $('<ul><li>jQuery 插入</li></ul>', {  
  4.       id: 'insert-by-jquery'  
  5.     });  
  6.     $list.appendTo($('body'));  
  7.   });  
  8. })(window.jQuery);  

jQuery 操作 ul 上的 id 不会被添加。

zepto代码:

[html] view plain copy

  1. Zepto(function($) {    
  2.   var $list = $('<ul><li>Zepto 插入</li></ul>', {  
  3.     id: 'insert-by-zepto'  
  4.   });  
  5.   $list.appendTo($('body'));  
  6. });  

Zepto 可以在 ul 上添加 id 。

 

(8)事件触发区别

jq代码:

[html] view plain copy

  1. (function($) {  
  2.   $(function() {      
  3.     $script = $('<script />', {  
  4.       src: 'http://cdn.amazeui.org/amazeui/1.0.1/js/amazeui.min.js',  
  5.       id: 'ui-jquery'  
  6.     });  
  7.   
  8.     $script.appendTo($('body'));  
  9.   
  10.     $script.on('load', function() {  
  11.       console.log('jQ script loaded');  
  12.     });  
  13.   });  
  14. })(window.jQuery);  

使用 jQuery 时 load 事件的处理函数 不会 执行

zepto代码:

[html] view plain copy

  1. Zepto(function($) {    
  2.   $script = $('<script />', {  
  3.     src: 'http://cdn.amazeui.org/amazeui/1.0.1/js/amazeui.js',  
  4.     id: 'ui-zepto'  
  5.   });  
  6.   
  7.   $script.appendTo($('body'));  
  8.   
  9.   $script.on('load', function() {  
  10.     console.log('zepto script loaded');  
  11.   });  
  12. });  

使用 Zepto 时 load 事件的处理函数 会 执行。

 

(9)zepto阻止事件冒泡

link传送门

10、zepto的slideUP和slidedown事件到底部才能触发

[html] view plain copy

  1. document.addEventListener('touchmove', function (event) {  
  2. event.preventDefault();  
  3. }, false);  

 

 

 

 

 

92、Zepto的点透问题如何解决?

(1)“点透”是什么

你可能碰到过在列表页面上创建一个弹出层,弹出层有个关闭的按钮,你点了这个按钮关闭弹出层后后,这个按钮正下方的内容也会执行点击事件(或打开链接)。这个被定义为这是一个“点透”现象。

在前面的项目中遇到了如下图的问题:在点击弹出来的选择组件的右上角完成后会让完成后面的input输入框聚焦,弹出输入键盘,也就是点透了

(2)为什么会出现点透呢?
这个需要从zepto(或者jqm)源码里面看关于tap的实现方法:

 View Code

可以看出zepto的tap通过兼听绑定在document上的touch事件来完成tap事件的模拟的,及tap事件是冒泡到document上触发的

再点击完成时的tap事件(touchstart\touchend)需要冒泡到document上才会触发,而在冒泡到document之前,用户手的接触屏幕(touchstart)和离开屏幕(touchend)是会触发click事件的,因为click事件有延迟触发(这就是为什么移动端不用click而用tap的原因)(大概是300ms,为了实现safari的双击事件的设计),所以在执行完tap事件之后,弹出来的选择组件马上就隐藏了,此时click事件还在延迟的300ms之中,当300ms到来的时候,click到的其实不是完成而是隐藏之后的下方的元素,如果正下方的元素绑定的有click事件此时便会触发,如果没有绑定click事件的话就当没click,但是正下方的是input输入框(或者select选择框或者单选复选框),点击默认聚焦而弹出输入键盘,也就出现了上面的点透现象。

(3)点透的解决方法:

方案一:来得很直接github上有个fastclick可以完美解决https://github.com/ftlabs/fastclick

引入fastclick.js,因为fastclick源码不依赖其他库所以你可以在原生的js前直接加上

1 window.addEventListener( "load", function() {2     FastClick.attach( document.body );3 }, false );

或者有zepto或者jqm的js里面加上

1 $(function() {2     FastClick.attach(document.body);3 });

当然require的话就这样:

1 var FastClick = require('fastclick');2 FastClick.attach(document.body, options);

方案二:用touchend代替tap事件并阻止掉touchend的默认行为preventDefault()

1 $("#cbFinish").on("touchend", function (event) {2     //很多处理比如隐藏什么的3     event.preventDefault();4 });

方案三:延迟一定的时间(300ms+)来处理事件

1 $("#cbFinish").on("tap", function (event) {2     setTimeout(function(){3     //很多处理比如隐藏什么的4     },320);5 });    

这种方法其实很好,可以和fadeInIn/fadeOut等动画结合使用,可以做出过度效果

理论上上面的方法可以完美的解决tap的点透问题,如果真的倔强到不行,用click

 

 

93、jQueryUI如何自定义组件?

如何开始使用

首先用$.widget()方法开始定义你的组件,它只接收三个参数:第一个是组件名称,第二个是可选的基类组件(默认的基类是$.Widget),第三个是组件的原型。

组件名称必须包含命名空间,要注意的是,官方组件的命名空间是以‘ui’开头的,比如:‘ui.tabs’。我在下面的用‘我’的拼音(‘wo’)。

 
         $.widget("yourNamespace.yourWidgetName",[yourBaseWidget],yourWidgetPrototype)

$.Widget基类含有一个重要的属性‘options’,它用来定义公有参数,组件初始化时外部调用的参数会覆盖内部定义的参数;以及三个重要的私有的方法‘_create’、‘_init’、‘’,前两个相当于构造函数的作用,按顺序执行,_create()方法执行之后会触发'create'事件。 _trigger()方法会将参数中的指定函数标准化为W3C事件,并且触发这个自定义事件。
另外还有三个公有方法‘enable’,‘disable’,‘destroy’,分别表示启用、禁用和销毁组件。

这里很有意思的,是私有方法和公有方法的实现。jQuerUI Widget暴露的方法都是不以‘_’开头的:

 
         // prevent calls to internal methods
         if ( isMethodCall && options.charAt( 0 ) === "_" ) {
                 return returnValue;
         }

实际上,jQueryUI Widget还是保留了原始的API,比如这样使用:

 
         var $div = $('.demo:first');
         var api = $div.data('divZoom');
         // console.dir(api);
         api.zoomIn();
         // 对比
         $div.divZoom('zoomIn');

一个实现完全私有变量的小技巧:

 
(function($) {
         var privateVar = '';
         $.widget(&quot;wo.divZoom&quot;,{});
})(jQuery)

所有代码

 
/*
* @by   ambar
* @create 2010-10-20
* @update 2010-10-25
*/
 
(function ($) {
  var html = '<div class="icon-zoom">\
          <span title="zoom in" class="zoom-in">zoom in</span>\
          <span title="zoom out" class="zoom-out">zoom out</span>\
        </div>';
  $.widget("wo.divZoom", {
    _init: function () {
      var self = this,
          opt = self.options,
          tgt = opt.target,
          $el = self.element;
      // 初始一次
      if ($('div.icon-zoom', $el).length) return;
      $el.append(html);
 
      self.target = (tgt == '' ? $el : $el.find(tgt));
      // 检测初始值
      var level   = self.target.attr(opt.dataPrefix);
      self.target.attr(opt.dataPrefix, level || opt.level[0]);
 
      self.btnZoomIn  = $el.find('span.zoom-in').click($.proxy(self.zoomIn, self));
      self.btnZoomOut = $el.find('span.zoom-out').click($.proxy(self.zoomOut, self));
    },
    destroy: function () {
      this.element.find('div.icon-zoom').remove();
    },
    options: {
      level     : [120, 160, 200],
      target    : '',
      speed     : 'normal',
      dataPrefix: 'data-zoom-level',
      zooming   : null,
      select    : null,
      show      : null
    },
    currentLevel: function () {
      var self = this, opt = self.options, lvl = Number(self.target.attr(opt.dataPrefix));
      return $.inArray(lvl, opt.level);
    },
    zoomIn: function () {
      this.zoom(this.currentLevel() + 1);
    },
    zoomOut: function () {
      this.zoom(this.currentLevel() - 1);
    },
    zoom: function (i) {
      var self = this, opt  = self.options, lvls = opt.level, $tgt = self.target;
 
      if (i <= -1 || i >= lvls.length) return;
 
      var value = lvls[i], originalValue = lvls[self.currentLevel()], style = { width : value, height: value };
      var data = { target: $tgt, css: style, originalCss: { width : originalValue,height: originalValue } };
 
      var goon = self._trigger('start', null, data);
      if (!goon) return;
 
      $tgt.animate(style, {
        duration: opt.speed,
        step: function (val) {
          var css = { width: val, height: val };
          self._trigger('zooming', null, $.extend({}, data, { css: css }));
        },
        complete: function () {
          $tgt.attr(opt.dataPrefix, value);
          self._trigger('stop', null, data);
        }
      });
    }
  });
})(jQuery)

在页面上调用

 
         <script src="js/jquery-1.4.4.min.js"></script>
         <script src="js/jquery.ui.widget.js"></script>
         <!-- 自定义的 -->
         <script src="js/jquery.ui.wo.divZoom.js"></script>
 
         <script type="text/javascript">
  $(function () {
    $('div.demo').divZoom({
      target: '>a',
      level: [80, 120, 160, 200],
      zooming: function (e, ui) {
        // console.log(e,ui.css);
      },
      start: function (e, ui) {
        console.log('开始', this, e.type, ui);
      },
      stop: function (e, ui) {
        console.log('结束', ui.css);
      }
    });
  });
         </script>

 

 

 

94、如何判断当前脚本运行在浏览器还是node环境中?(阿里)

node环境是一个服务器端js的解释器。

看this指向global还是指向window。

前者是node环境,后者是浏览器。即node全局变量是global,浏览器全局变量是window。

typeof  window=="undefined"?global:window;

 

 

95、把 Script 标签 放在页面的最底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?

(1)拉取 HTML 页面 (e.g. index.html)

(2)开始解析 HTML

(3)解析到 <script> 标签之后准备获取 script 文件.

(4)浏览器获取script文件。同时,html 解析中断并且阻断页面上其他html的解析。

(5)一段时间后,script下载完成并且执行

(6)继续解析HTML文档的其他部分(解析script之后的html代码)

第4步导致了不好的用户体验,直到script文件全部下载完成之前HTML都不能得到解析。


 

  1. 移动端的点击事件的有延迟,为什么会有?

  Google开发者文档中有提到:

mobile browsers will wait approximately 300ms from the time that you tap the button to fire the click event. The reason for this is that the browser is waiting to see if you are actually performing a double tap.

      移动浏览器为什么会设置300毫秒的等待时间呢?这与双击缩放的方案有关。平时我们有可能已经注意到了,双击缩放,即用手指在屏幕上快速点击两次,可以看到内容或者图片放大,再次双击,浏览器会将网页缩放至原始比例。

      浏览器捕获第一次单击后,会先等待一段时间,如果在这段时间区间里用户未进行下一次点击,则浏览器会做单击事件的处理。如果这段时间里用户进行了第二次单击操作,则浏览器会做双击事件处理。这段时间就是上面提到的300毫秒延迟。

 

如何避免延迟

      在特定场景如一些游戏页面,我们需要取消300毫毛的延迟。目前有以下方法:

 

方法一:静止缩放

[html] view plain copy

  1. <meta name="viewport" content="width=device-width user-scalable= 'no'">  


      使用这个方法必须完全禁用缩放来达到目的,虽然大部分移动端能解决这个延迟问题,但是部分苹果手机还是不行。

方法二:fastclick.js

      FastClick 是 FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。简而言之,FastClick 在检测到touchend事件的时候,会通过 DOM 自定义事件立即触发一个模拟click事件,并把浏览器在 300 毫秒之后真正触发的click事件阻止掉。使用方法如下。

      第一步:在页面中引入fastclick.js文件。
      第二步:在js文件中添加以下代码
      在 window load 事件之后,在body上调用FastClick.attach()即可。

[javascript] view plain copy

  1. window.addEventListener(function(){   
  2.     FastClick.attach( document.body );  
  3. },false );  


      如果你项目使用了JQuery,就将上面的代码改写成:

[javascript] view plain copy

  1. $(function() {    
  2.     FastClick.attach(document.body);    
  3. });  

 

方法三:指针事件


      指针事件最初由微软提出,现已进入 W3C 规范的候选推荐标准阶段 (Candidate Recommendation)。指针事件是一个新的 web 事件系列,相应的规范旨在使用一个单独的事件模型,对所有输入类型,包括鼠标 (mouse)、触摸 (touch)、触控 (stylus) 等,进行统一的处理。

      指针事件 (Pointer Events) 目前兼容性不太好,不知道在以后会不会更加支持。

 

 

 

  1. 知道各种JS框架(Angular, Backbone, Ember, React, Meteor, Knockout...)么? 能讲出他们各自的优点和缺点么?

angular、backbone、knockout都是完整的MV*框架

angular是双向数据绑定的,backbone、knockout是单向数据绑定的

React只是单纯地View层

 

 

98、解释JavaScript中的作用域与变量声明提升?

javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。

先看一段代码

1

2

3

4

5

var v = "hello";

(function(){

  console.log(v);

  var v = "world";

})();

这段代码运行的结果是什么呢?
答案是:undefined
这段代码说明了两个问题,
第一,function作用域里的变量v遮盖了上层作用域变量v。代码做少些变动

1

2

3

4

5

var v = "hello";

if(true){

  console.log(v);

  var v = "world";

}

输出结果为”hello”,说明javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构。

第二,在function作用域内,变量v的声明被提升了。所以最初的代码相当于:

1

2

3

4

5

6

var v = "hello";

(function(){

  var v; //declaration hoisting

  console.log(v);

  v = "world";

})();

声明、定义与初始化

声明宣称一个名字的存在,定义则为这个名字分配存储空间,而初始化则是为名字分配的存储空间赋初值。
用C++来表述这三个概念

1

2

3

extern int i;//这是声明,表明名字i在某处已经存在了

int i;//这是声明并定义名字i,为i分配存储空间

i = 0;//这是初始化名字i,为其赋初值为0

javascript中则是这样

1

2

var v;//声明变量v

v = "hello";//(定义并)初始化变量v

因为javascript为动态语言,其变量并没有固定的类型,其存储空间大小会随初始化与赋值而变化,所以其变量的“定义”就不像传统的静态语言一样了,其定义显得无关紧要。

声明提升

当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明

1

2

3

4

5

6

(function(){

  var a = "1";

  var f = function(){};

  var b = "2";

  var c = "3";

})();

变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:

1

2

3

4

5

6

7

(function(){

  var a,f,b,c;

  a = "1";

  f = function(){};

  b = "2";

  c = "3";

})();

请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:

1

2

3

4

5

6

7

8

9

(function(){

  //var f1,function f2(){}; //hoisting,被隐式提升的声明

 

  f1(); //ReferenceError: f1 is not defined

  f2();

 

  var f1 = function(){};

  function f2(){}

})();

上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。

名字解析顺序

javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
语言内置:所有的作用域中都有 this 和 arguments 关键字
形式参数:函数的参数在函数作用域中都是有效的
函数声明:形如function foo() {}
变量声明:形如var bar;

名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:

1

2

3

4

5

6

7

8

9

(function(){

    var foo;

    console.log(typeof foo); //function

     

    function foo(){}

 

    foo = "foo";

    console.log(typeof foo); //string

})();

如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。

以上的名字解析优先级存在例外,比如可以覆盖语言内置的名字arguments。

命名函数表达式

可以像函数声明一样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提升。

1

2

3

4

5

f();//TypeError: f is not a function

foo();//ReferenceError: foo is not defined

var f = function foo(){console.log(typeof foo);};

f();//function

foo();//ReferenceError: foo is not defined

命名函数表达式的名字只在该函数的作用域内部有效。
===
在认识一切事物之后,人才能认识自己,因为事物仅仅是人的界限。 —— 尼采

 

Js作用域与作用域链详解

http://blog.csdn.net/yueguanghaidao/article/details/9568071

  一直对Js的作用域有点迷糊,今天偶然读到Javascript权威指南,立马被吸引住了,写的真不错。我看的是第六版本,相当的厚,大概1000多页,Js博大精深,要熟悉精通需要大毅力大功夫。

一:函数作用域

   先看一小段代码:

[javascript] view plaincopy

var scope="global";  

function t(){  

    console.log(scope);  

    var scope="local"  

    console.log(scope);  

}  

t();  

(PS: console.log()是firebug提供的调试工具,很好用,有兴趣的童鞋可以用下,比浏览器+alert好用多了)

第一句输出的是: "undefined",而不是 "global"

第二讲输出的是:"local"

  你可能会认为第一句会输出:"global",因为代码还没执行var scope="local",所以肯定会输出“global"。

  我说这想法完全没错,只不过用错了对象。我们首先要区分Javascript的函数作用域与我们熟知的C/C++等的块级作用域。

  在C/C++中,花括号内中的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的。而Javascript压根没有块级作用域,而是函数作用域.

所谓函数作用域就是说:-》变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

所以根据函数作用域的意思,可以将上述代码重写如下:

[javascript] view plaincopy

var scope="global";  

function t(){  

    var scope;  

    console.log(scope);  

    scope="local"  

    console.log(scope);  

}  

t();  

    我们可以看到,由于函数作用域的特性,局部变量在整个函数体始终是由定义的,我们可以将变量声明”提前“到函数体顶部,同时变量初始化还在原来位置。

为什么说Js没有块级作用域呢,有以下代码为证:

[javascript] view plaincopy

var name="global";  

if(true){  

    var name="local";  

    console.log(name)  

}  

console.log(name);  

都输出是“local",如果有块级作用域,明显if语句将创建局部变量name,并不会修改全局name,可是没有这样,所以Js没有块级作用域。

现在很好理解为什么会得出那样的结果了。scope声明覆盖了全局的scope,但是还没有赋值,所以输出:”undefined“。

所以下面的代码也就很好理解了。

[javascript] view plaincopy

function t(flag){  

    if(flag){  

        var s="ifscope";  

        for(var i=0;i<2;i++)   

            ;  

    }  

    console.log(i);  

    console.log(s);  

}  

t(true);  

输出:2  ”ifscope"
 

二:变量作用域

还是首先看一段代码:

[javascript] view plaincopy

function t(flag){  

    if(flag){  

        s="ifscope";  

        for(var i=0;i<2;i++)   

            ;  

    }  

    console.log(i);  

}  

t(true);  

console.log(s);  


就是上面的翻版,知识将声明s中的var去掉。

程序会报错还是输出“ifscope"呢?

让我揭开谜底吧,会输出:”ifscope"

这主要是Js中没有用var声明的变量都是全局变量,而且是顶层对象的属性。

所以你用console.log(window.s)也是会输出“ifconfig"

 

当使用var声明一个变量时,创建的这个属性是不可配置的,也就是说无法通过delete运算符删除

var name=1    ->不可删除

sex=”girl“         ->可删除

this.age=22    ->可删除

 

三:作用域链

先来看一段代码:

[javascript] view plaincopy

name="lwy";  

function t(){  

    var name="tlwy";  

    function s(){  

        var name="slwy";  

        console.log(name);  

    }  

    function ss(){  

        console.log(name);  

    }  

    s();  

    ss();  

}  

t();  


当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显

name是"slwy"。

但执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy"

下面看一个很容易犯错的例子:

[html] view plaincopy

<html>  

<head>  

<script type="text/javascript">  

function buttonInit(){  

    for(var i=1;i<4;i++){  

        var b=document.getElementById("button"+i);  

        b.addEventListener("click",function(){ alert("Button"+i);},false);  

    }  

}  

window.onload=buttonInit;  

</script>  

</head>  

<body>  

<button id="button1">Button1</button>  

<button id="button2">Button2</button>  

<button id="button3">Button3</button>  

</body>  

</html>  

当文档加载完毕,给几个按钮注册点击事件,当我们点击按钮时,会弹出什么提示框呢?

很容易犯错,对是的,三个按钮都是弹出:"Button4",你答对了吗?

当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,

所以弹出”button4“。

 

四:with语句

说到作用域链,不得不说with语句。with语句主要用来临时扩展作用域链,将语句中的对象添加到作用域的头部。

看下面代码

[javascript] view plaincopy

person={name:"yhb",age:22,height:175,wife:{name:"lwy",age:21}};  

with(person.wife){  

    console.log(name);  

}  

with语句将person.wife添加到当前作用域链的头部,所以输出的就是:“lwy".

with语句结束后,作用域链恢复正常。

 

 

99、哪些操作会造成内存泄漏?

Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的可能是24M,当我们的内存占用超过了一定的程度后,就会出现OutOfMemory的错误。

下面说明几点可能导致内存泄露的原因,供大家参考。

(1)对象内存过大

保存了多个好用内存过大的对象,造成内存超出限制。

(2)资源释放

程序代码的问题,长期保持某些资源,如Context,Cursor,IO流的引用,资源得不到释放造成内存泄露。

(3)static关键字的使用

static 是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所以用static修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例,就可能会造成内存的泄露。

针对static的解决方案:

应该尽量避免static成员变量引用资源耗费过多的实例,比如Context.

Context尽量使用ApplicationContext的生命周期比较长,引用它不会出现内存泄露。

使用WeakReference代替强引用。比如可以使用WeakReference<Context> mContext;

(4).线程导致内存溢出

线程产生内存泄露的主要原因在于线程生命周期的不可控。如当我们切换横竖屏的时候,一般会重新创建Activity,老的Activity应该被销毁。但是此时我们在子线程中正在进行耗时的操作,老的Activity不会被销毁,这个时候就会出现内存泄露。

解决方案:

将线程的内部类,改为静态内部类。

在线程内部采用弱引用保存Context引用。

 

 

100Node.js的适用场景?

NodeJS是近年来比较火的服务端JS平台,这一方面得益于其在后端处理高并发的卓越性能,另一方面在nodeJS平台上的npm、grunt、express等强大的代码与项目管理应用崛起,几乎重新定义了前端的工作方式和流程。

NodeJS的成功标志着它的强大,但是不是所有情况都适合应用NodeJS作为服务器端平台呢?

答案当然是否定的,而网上也是众说纷纭。那我们从原理出发了解一下NodeJS的适用情况。

在讲NodeJS之前我们不仿先看一下传统(以Apache为代表)的服务器端处理平台处理并发的方式。

 (1) Apache的多线程高并发模式

Apache是当前世界排名第一的Web服务端软件,它由于支持多线程并发而受到广大服务器技术选型者的欢迎。但发展到后来,Apache在一些WEB的大型应用中也渐渐暴露出它的缺点:阻塞。

那有的同学会奇怪,Apache不是多线程处理并发吗,为什么还会出现阻塞呢?

要明白这一点我们首先需要了解线程这个概念

1.1 什么是线程?

我们引用官方的解释:线程可以独立运行的最小的CPU单位,可以在同一个进程里并发运行,共享该进程下的内存地址空间(注意这个特点)

我们可以看到同一个进程下的线程是会共享相同的文件和内存的(内存地址空间),所以大家可以想象,当不同的线程需要占用同一个变量时,根据先到先得的原则,先到的线程在运作时,后来的线程只能在旁边等待,也就是加入到了阻塞排队序列。所以这就是造成线程阻塞的原因。

因此,虽说进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,因为程序设计者必须小心,确保它们不会妨碍同一进程里的其它线程。

了解了多线程并行的缺陷后,我们就可以更好地理解NodeJS的强大所在了。因为NodeJS是异步单线程的!

 

(2) NodeJS的异步I/O原理

我们先来看一段Apache请求数据库的代码:

代码执行到第一行的时候线程会阻塞,等待query返回结果,然后继续处理。由于数据库查询、磁盘读写、网络通信等原因(所谓的I/O)阻塞时间会非常大(相对于CPU始终频率)。对于高并发的访问,一方面线程长期阻塞等待,另一方面为了应付新情求而不断添加新线程,会浪费大量系统资源,同时线程的增加也会也会占用大量的CPU时间来处理内存上下文切换。看看node.js怎么处理。

看到没,就四个字:异步回调。query的第二个参数是一个回调函数,进程执行到db.query的时候不会等待结果返回,而是直接继续执行下面的语句,直到进入事件循环。当数据库执行结果返回的时候会将事件发送到事件队列,等到线程进入事件循环后才会调用之前的回调函数。更专业的说法是异步I/O。只要单线程就可以。

 

那为什么NodeJS做到单线程,却可以实现异步呢?在这里我们先上一幅图,直戳图中的Event queue

看到没,NodeJS的工作原理其实就是事件循环。可以说每一条NodeJS的逻辑都是写在回调函数里面的,而回调函数都是有返回之后才异步执行的!

 

看到这里,你不禁会惊叹,NodeJS如果所有处理都异步,岂不是晓得飞了?错错错!当然不是,不要忘记,NodeJS实现这些的基础是单线程。没错,单线程!一条线程扛起所有操作!

你可以想象一下,NodeJS在寒风中面对着10万并发大军,OK,没问题,上来敌人一个扔到城里,上来一个又扔到城里。城里全民皆兵,可以很好地消化这些敌人。但如果上来一个类似于张飞赵云这样的人物,老Node心里一惨,和张飞大战300回合,把他打残了,再扔到城里。那后面的10万大军就得等这300回合。。。

所以这说明什么?说明NodeJS不是没有阻塞,而是阻塞不发生在后续回调的流程,而会发生在NodeJS本身对逻辑的计算和处理。我们已经知道,NodeJS的分发能力无比强大,可以循环事件进行异步回调。但如果在循环事件时遇到复杂的逻辑运算,那么单薄的单线程怎么支撑得起上百万的逻辑+并发呢?NodeJS它的所有I/O、网络通信等比较耗时的操作,都可以交给worker threads执行再回调,所以很快。但CPU的正常操作,它就只能自己抗了。 

说到这里,各位对NodeJS的特性估计也大概有个谱了。所以说适用的场景基本是呼之欲出了~!

 

(3) NodeJS的应用场景

既然NodeJS处理并发的能力强,但处理计算和逻辑的能力反而很弱,因此,如果我们把复杂的逻辑运算都搬到前端(客户端)完成,而NodeJS只需要提供异步I/O,这样就可以实现对高并发的高性能处理。情况就很多啦,比如:RESTFUL API、实时聊天、客户端逻辑强大的单页APP,具体的例子比如说:本地化的在线音乐应用,本地化的在线搜索应用,本地化的在线APP等。

顺便提一下Apache,打压了这么多,给颗甜枣。Apache由于其多线程高并发共享内存地址空间的特性,那就意味着如果服务器足够强大,处理器足够高核,Apache的运作将会非常良好,所以适用于(并发)异步处理相对较少,后台计算量大,后台业务逻辑复杂的应用程序。

 

 

 

  1. 简述一下 Handlebars 的基本用法?

Handlebars的安装是比较简单和方便的;handlebars是一个纯JS库,因此你可以像使用其他JS脚本一样用script标签来包含handlebars.js

<script src="jquery.min.js"></script><script type="text/javascript" src=".js/handlebars.js"></script>  

基本

html

<-- 模板 -->

<script type="text/x-handlebars-template" id="tpl">

  {{#each}}

    ...

  {{/each}}

</script>

js:

//获取到模板

var tpl = $("#tpl").html();

//预编译模板

var template = Handlebars.compile(tpl);

//模拟数据(也可以是获取的json数据)

var context = {};

//匹配数据

var html = template(context);

//输入模板

$('body').html(html);

  : 这是handlebars最常用的一中创建使用模式。

 

  1. 用js实现千位分隔符?

输入:数字(考虑数字是否合法、正负号、小数点)、字符串
输出:考虑到使用场景,最好是字符串

测试用例:-1234567.9012
期待输出:-1,234,567.9012

千位分隔符貌似在《精通正则表达式》中讲环视的时候作为经典范例,然而写出来发现js不支持逆序环视,也就是 (?<=expression) (?<!expression) 这两种是不支持的。

// 正则function thousandBitSeparator(num) {

    return num && num

        .toString()

        .replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {

            return $1 + ",";

        });}console.log(thousandBitSeparator(-1234567.9012));// -1,234,567.9012

todo

当测试用例是1000的时候,此正则不能正确标注千位分隔符,现修改如下:

function thousandBitSeparator(num) {

  return num && (num

    .toString().indexOf('.') != -1 ? num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {

      return $1 + ",";

    }) : num.toString().replace(/(\d)(?=(\d{3}))/g, function($0, $1) {

      return $1 + ",";

    }));}console.log(thousandBitSeparator(1000));//1,000

 

 

 

103、检测浏览器版本版本有哪些方式?

如何判断浏览器的类型和版本? -- 使用JavaScript的内置对象 navigator 的属性userAgent的值来判断(navigator.userAgent)。
navigator是javascript的内置对象,通常用于检测浏览器与操作系统的版本。 常用的属性有

  • appCodeName -- 浏览器代码名的字符串表示
  • appName -- 官方浏览器名的字符串表示
  • appVersion -- 浏览器版本信息的字符串表示
  • cookieEnabled -- 如果启用cookie返回true,否则返回false
  • javaEnabled -- 如果启用java返回true,否则返回false
  • platform -- 浏览器所在计算机平台的字符串表示
  • plugins -- 安装在浏览器中的插件数组
  • taintEnabled -- 如果启用了数据污点返回true,否则返回false
  • userAgent -- 用户代理头的字符串表示(就是包含浏览器版本信息等的字符串)

 

 

 

104、我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡,你来说下会执行几次事件,然后会先执行冒泡还是捕获

事件的执行顺序绝对是让人头疼的问题。当父元素与子元素都绑定了多个事件,且有的绑定在冒泡阶段、有的绑定在捕获阶段时,事件的触发顺序如何?如果你只关心这个问题,请直接下滑到3. 绑定多个事件,且由用户行为触发。如果你想细致了解JavaScript中的事件发生,请慢慢阅读。

(1) 原生事件的发生顺序

一般来讲,当为一个a标签添加click事件以后,点击这个标签,会先执行绑定的事件、后跳转页面。一个input绑定blur事件以后,你在input里输入完内容,点击提交按钮,会先发生blur事件,后发生click事件。当然,这是一般来讲。我在一个React项目中曾经发生表单提交时,先发生click事件,blur事件没有来得及发生,造成表单内容没有检验就提交到后台,原因我至今没有找到,解决办法是在click事件上加一个50ms的延迟。

(2)自定义事件

JavaScript中也支持手动触发事件,请看下面代码。

         a.addEventListener('click', function(){
            console.log(input.value);
            console.log(this.getAttribute('href'));
            console.log(location.href);
        }, false); //a是我已经通过id获得好的一个a标签
 
         var event = document.createEvent('HTMLEvents'); // initEvent接受3个参数: 事件类型,是否冒泡,是否阻止浏览器的默认行为
        event.initEvent('click', true, true);    
        event.eventType = 'click'; 
        //触发a上绑定的自定义事件   
        a.dispatchEvent(event);   //注:jQuery中有更简单的trigger()方法实现自定义事件功能

 

JavaScript中自定义事件的类型有(即document.createEvent('HTMLEvents')中的参数): 
UIEvents:一般化的UI事件。 
MouseEvents:一般化的鼠标事件。 
MutationEvents:一般化的DOM变动事件。 
HTMLEvents:一般化的HTML事件。 
自定义事件的发生比较容易控制,你什么时候触发(dispatchEvent/fireEvent)它,它就什么时候发生。

(3)绑定多个事件,且由用户行为触发

这个情况最复杂,也是标题中的情况:父元素与子元素都绑定多个事件,且有的事件在捕获阶段、有的事件在冒泡阶段。

下面这个例子,父元素div绑定两个事件(一个冒泡阶段、一个捕获阶段),子元素也是这种情况。事件触发顺序如何。

        var btn = document.querySelector('button');
        var div = document.querySelector('div');
 
        btn.addEventListener('click', function(){
            console.log('bubble','btn');
        },false);
        btn.addEventListener('click', function(){
            console.log('capture','btn');
        },true);
 
        div.addEventListener('click', function(){
            console.log('bubble','div');
        },false);
        div.addEventListener('click', function(){
            console.log('capture','div');
        },true);

执行结果: 
 
乍一看这个结果有些乱,但仔细分析可以得出结论: 
绑定在被点击元素的事件是按照代码顺序发生,其他元素通过冒泡或者捕获“感知”的事件,按照W3C的标准,先发生捕获事件,后发生冒泡事件。所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件 。

 

 

105设计模式 知道什么是singleton, factory, strategy, decrator么?

设计模式主要分三个类型:创建型、结构型和行为型。 

其中创建型有: 

    一、Singleton,单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点 

    二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。 

    三、Factory Method,工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。 

    四、Builder,建造模式:将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。 

    五、Prototype,原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。 

行为型有: 

    六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。 

    七、Observer,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。 

    八、Template Method,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。 

    九、Command,命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。 

    十、State,状态模式:允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。 

    十一、Strategy,策略模式:定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。 

    十二、China of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系 

    十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。 

    十四、Visitor,访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。 

    十五、Interpreter,解释器模式:给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 

    十六、Memento,备忘录模式:在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 

结构型有: 

    十七、Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。 

    十八、Facade,外观模式:为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。 

    十九、Proxy,代理模式:为其他对象提供一种代理以控制对这个对象的访问 

    二十、Adapter,适配器模式:将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。 

    二十一、Decrator,装饰模式:动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。 

    二十二、Bridge,桥模式:将抽象部分与它的实现部分相分离,使他们可以独立的变化。 

    二十三、Flyweight,享元模式

 

 

106、常使用的库有哪些?

使用率较高的框架有jQuery、YUI、Prototype、Dojo、Ext.js、Mootools等。

 

  1. 列举IE与其他浏览器不一样的特性?
事件不同之处:
    触发事件的元素被认为是目标(target)。而在 IE 中,目标包含在 event 对象的 srcElement 属性;
 
    获取字符代码、如果按键代表一个字符(shift、ctrl、alt除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是分离的,要获取字符代码,需要使用 charCode 属性;
 
    阻止某个事件的默认行为,IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,需要调用 preventDefault() 方法;
 
停止事件冒泡,IE 中阻止事件进一步冒泡,需要设置 cancelBubble 为 true,Mozzilla 中,需要调用 stopPropagation();
 
  1. WEB应用从服务器主动推送Data到客户端有那些方式?
html5提供的Websocket
不可见的iframe
WebSocket通过Flash
XHR长时间连接
XHR Multipart Streaming
<script>标签的长时间连接(可跨域)
 
 
  1. 你有用过哪些前端性能优化的方法?
(1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
(4) 当需要设置的样式很多时设置className而不是直接操作style。  (5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作
(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
(7) 图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。

 
对普通的网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的

110new操作符具体干了什么呢

  1. 先创建了一个新的空对象
    (2)然后让这个空对象的__proto__指向函数的原型prototype
    (3)将对象作为函数的this传进去,如果return 出来东西是对象的话就直接返回 return 的内容,没有的话就返回创建的这个对象

 

 

猜你喜欢

转载自blog.csdn.net/qq_43671996/article/details/84229369