1 . 请解释事件代理 (event delegation)
javascript
当须要对不少元素添加事件的时,能够经过将事件添加到它们的父节点经过委托来触发处理函数。其中利用到了浏览器的事件冒泡机制。html
var delegate = function(client, clientMethod) { return function() { return clientMethod.apply(client, arguments); } } var agentMethod = delegate (client, clientMethod); agentMethod(); // 获取父节点,并为它添加一个click事件 document.getElementById("parent-list").addEventListener("click",function(e) { // 检查事件源e.targe是否为Li if(e.target && e.target.nodeName.toUpperCase == "LI") { // 真正的处理过程在这里 console.log("List item ",e.target.id.replace("post-")," was clicked!"); } });
2 . 谈谈浏览器的事件冒泡机制
java
对于事件的捕获和处理,不一样的浏览器厂商有不一样的处理机制,咱们以W3C对DOM2.0定义的标准事件为例
DOM2.0模型将事件处理流程分为三个阶段:1、事件捕获阶段,2、事件目标阶段,3、事件起泡阶段。node
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程当中,事件相应的监听函数是不会被触发的。git
事件目标:当到达目标元素以后,执行目标元素该事件相应的处理函数。若是没有绑定监听函数,那就不执行。github
事件起泡:从目标元素开始,往顶层元素传播。途中若是有节点绑定了相应的事件处理函数,这些函数都会被一次触发。若是想阻止事件起泡,可使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。ajax
3 . JavaScript 中 this 是如何工做的。
编程
4 . 谈谈CommonJs 、AMD 和CMD
数组
CommonJS规范,一个单独的文件就是一个模块。每个模块都是一个单独的做用域 CommonJS的使用表明:NodeJS浏览器
AMD 即Asynchronous Module Definition 异步模块定义 它是一个在浏览器端模块化开发的规范 AMD 是 RequireJS 在推广过程当中对模块定义的规范化的产出
CMD 即Common Module Definition 通用模块定义 其表明为SeaJS
requireJS主要解决两个问题
CMD和AMD的区别
5 . 谈谈对IIFE的理解
IIFE即Immediately-Invoked Function Expression 当即执行函数表达式
不推荐
(function(){})();
推荐
(function(){}());
在javascript里,括号内部不能包含语句,当解析器对代码进行解释的时候,先碰到了(),而后碰到function关键字就会自动将()里面的代码识别为函数表达式而不是函数声明。
知识拓展:
function(){ /* code */ }(); 解释下该代码能正确执行吗?
不行,在javascript代码解释时,当遇到function关键字时,会默认把它当作是一个函数声明,而不是函数表达式,若是没有把它显视地表达成函数表达式,就报错了,由于函数声明须要一个函数名,而上面的代码中函数没有函数名。(以上代码,也正是在执行到第一个左括号(时报错,由于(前理论上是应该有个函数名的。)
function foo(){ /* code */ }(); 解释下该代码能正确执行吗?
在一个表达式后面加上括号,表示该表达式当即执行;而若是是在一个语句后面加上括号,该括号彻底和以前的语句没法匹配,而只是一个分组操做符,用来控制运算中的优先级(小括号里的先运算)至关于先声明了一个叫foo的函数,以后进行()内的表达式运算,可是()(分组操做符)内的表达式不能为空,因此报错。(以上代码,也就是执行到右括号时,发现表达式为空,因此报错)。
6 . .call 和 .apply 的区别是什么?
foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)
call, apply方法区别是,从第二个参数起, call方法参数将依次传递给借用的方法做参数, 而apply直接将这些参数放到一个数组中再传递, 最后借用方法的参数列表是同样的.
7 . 请解释 Function.prototype.bind?
bind() 方法的主要做用就是将函数绑定至某个对象,bind() 方法会建立一个函数,函数体内this对象的值会被绑定到传入bind() 函数的值。
原理
Function.prototype.bind = function(context) { var self = this; // 保存原函数 return function() { // 返回一个新函数 return self.apply(context, arguments); // 执行新函数时,将传入的上下文context做为新函数的this } }
用法:
var paint = { color: "red", count: 0, updateCount: function() { this.count++; console.log(this.count); } }; // 事件处理函数绑定的错误方法: document.querySelector('button') .addEventListener('click', paint.updateCount); // paint.updateCount函数的this指向变成了该DOM对象 // 事件处理函数绑定的正确方法: document.querySelector('button') .addEventListener('click', paint.updateCount.bind(paint)); // paint.updateCount函数的this指向变成了paint
8 . 请解释原型继承 (prototypal inheritance) 的原理。
当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止。——出自JavaScript秘密花园
JavaScript中的每一个对象,都有一个内置的 proto 属性。这个属性是编程不可见的(虽然ES6标准中开放了这个属性,然而浏览器对这个属性的可见性的支持不一样),它其实是对另外一个对象或者 null 的引用。
当一个对象须要引用一个属性时,JavaScript引擎首先会从这个对象自身的属性表中寻找这个属性标识,若是找到则进行相应读写操做,若没有在自身的属性表中找到,则在 proto 属性引用的对象的属性表中查找,如此往复,直到找到这个属性或者 proto 属性指向 null 为止。
如下代码展现了JS引擎如何查找属性:
//__proto__ 是一个不该在你代码中出现的非正规的用法,这里仅仅用它来解释JavaScript原型继承的工做原理。 function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) return obj[prop] else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop) else return undefined }
JS的ECMA规范只容许咱们采用 new 运算符来进行原型继承
原型继承
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { print: function () { console.log(this.x, this.y); } }; var p = new Point(10, 20); p.print(); // 10 20
顺便阐述下new 运算符是如何工做的?
function New (f) { var n = { '__proto__': f.prototype }; /*第一步*/ return function () { f.apply(n, arguments); /*第二步*/ return n; /*第三步*/ }; }
JavaScript中真正的原型继承
Object.create = function (parent) { function F() {} F.prototype = parent; return new F(); };
使用真正的原型继承(如 Object.create 以及 proto)仍是存在如下缺点:
ES6 内部实现类和类的继承
class Parent { constructor(name) { //构造函数 this.name = name; } say() { console.log("Hello, " + this.name + "!"); } } class Children extends Parent { constructor(name) { //构造函数 super(name); //调用父类构造函数 // ... } say() { console.log("Hello, " + this.name + "! hoo~~"); } }
参考:
9 . 请尽量详尽的解释 AJAX 的工做原理
Ajax 的原理简单来讲经过 XmlHttpRequest 对象来向服务器发异步请求,从服务器得到数据,而后用 JavaScript来操做 DOM 而更新页面。 这其中最关键的一步就是从服务器得到请求数据。
不使用ajax工做原理
使用ajax工做原理
10 . javascript中"attribute" 和 "property" 的区别是什么?
property 和 attribute很是容易混淆,两个单词的中文翻译也都很是相近(property:属性,attribute:特性),但实际上,两者是不一样的东西,属于不一样的范畴。每个DOM对象都会有它默认的基本属性,而在建立的时候,它只会建立这些基本属性,咱们在TAG标签中自定义的属性是不会直接放到DOM中的。