1.document.querySelectorAll赋给其它变量时, 为什么要.bind(document)?

阮一峰的博客提到$的替代方法:

var $ = document.querySelectorAll.bind(document);

回答(1):我的理解是this的指向问题。querySelectorAll是document下的一个方法,附值给select后,select已经是window下的一个属性,此时,this已经不再是document,而window下没有querySelectorAll方法,所以会报错;var select = document.querySelectorAll.bind(document),能保证调用select()时this永远指向document。

回答(2):这个问题其实和querySelectorAll没什么关系。document是类的一个实例,而querySelectorAll是原型链上的方法。类比到普通的类和原型方法就很好理解了吧。

通过实例来运行原型链上的方法时,解释器会自动将this指向那个实例,但是直接这样var select = document.querySelectorAll;,你的变量仅仅是指向了原型链上的那个函数,而没有绑定this指针,所以你才需要在外面手动绑定一下指针。

回答(3):因为document.querySelectorAll是通过document这个对象去调用querySelectorAll的时候,函数的环境变量里this会指向document,假设querySelectorAll含有this的操作的话,那么this就会指代document。

而当你执行var select = document.querySelectorAll; 的时候,select所得到的是querySelector这个引用,但是此时如果直接通过select去调用的话,也就是select('span'); ,由于select(querySelectorAll)直接调用的话,this会自动指向window,所以就会出错。

bind的作用是,创建一个新函数,称为绑定函数。当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数。
而这句话var $ = document.querySelectorAll.bind(document);的效果相当于下面的代码

var $ = function(document) {
    return function() {
        return document.querySelectorAll.call(document, arguments);
    }
}

2.对Array.prototype.slice.call()方法的理解

在看别人代码时,发现有这么个写法:[].slice.call(arguments, 0),这到底是什么意思呢?

(1)slice() 方法可从已有的数组中返回选定的元素。

start:必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。

end:可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。该方法并不会修改数组,而是返回一个子数组。

(2)call()和apply()方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。apply和call方法的第一个参数都是特定的作用域第二个参数不同,apply第二个参数可以是Array的实例,也可以是arguments对象。call方法需要逐个列出需要传递的参数。

(3)arguments对象指数与数组类似(它并不是Array的实例),但是可以使用方括号语法访问每一个元素,使用length来确定传递进来多少个参数。

(4)Array.prototype.slice.call()可以理解为:改变数组的slice方法的作用域,在特定作用域中去调用slice方法,call()方法的第二个参数表示传递给slice的参数即截取数组的起始位置。

原理:

Array.prototype.slice.call(arguments)能将具有length属性的对象(key值为数字)转成数组。[]是Array的示例,所以可以直接使用[].slice()方法。

var obj = {0:'hello',1:'world',length:2};
console.log(Array.prototype.slice.call(obj,0));//["hello", "world"]

没有length属性的对象

var obj = {0:'hello',1:'world'};//没有length属性
console.log(Array.prototype.slice.call(obj,0));//[]

可以借用Array.prototype.slice方法的对象要满足一下两个条件:

  • 对象本身要可以存取属性
  • 对象的length属性可读写

3.在 JavaScript 中, true && expression 总是会评估为 expression ,而 false && expression 总是执行为 false 。

console.log(true && "expression") 
console.log(false && "expression")

输出:
expression
false

CodeMan
1.4k 声望58 粉丝

《伤害》