今天前Leader在下班前发给我一道JavaScript的题目,看到感受很不错,并且我开始的时候确实也理解错了,以为有必要拿出来说讲,而且为此我也作错了地铁,哈哈哈~
题目是这样的:javascript
var length = 10; function fn() { console.log(this.length) }; var obj = { length: 5, method: function (fn) { fn(); arguments[0](); fn.call(obj, 12); } }; obj.method(fn, 1);
请问输出是什么,当时那手机看的时候给出了答案java
10 10 5
实际上并非如此,答案是:git
10 2 5
仔细分析了一下才知道缘由,首先介绍一下四种this的类型:github
默认绑定数组
隐式绑定app
显示绑定函数
new绑定this
其中,默认绑定就是什么都匹配不到的状况下,非严格模式this
绑定到全局对象window
或者global
,严格模式绑定到undefined
;隐式绑定就是函数做为对象的属性,经过对象属性的方式调用,这个时候this
绑定到对象;显示绑定就是经过apply
和call
调用的方式;new绑定就是经过new
操做符时将this
绑定到当前新建立的对象中,它们的匹配有限是是从小到大的。
那么如今来解释一下:code
obj.method(fn, 1);
上述执行其实对应的是下面三条语句:对象
fn(); arguments[0](); fn.call(obj, 12);
经过将函数赋值给函数参数(fn
),而后调用fn
,这个时候能匹配到的this
类型就是第一条默认绑定,由于实在非严格模式下,因此this
绑定的是window
,固然首先输出的是10
。
先解释一下第三个,这个也很简单,由于用了call
,因此实际匹配了显示绑定
,因此当前this
绑定了obj
,那么输出的确定是2
。
下面着重解释一下第二个,这个我当时理解成和第一次彻底同样,但实际并非的,其实在JavaScript中数组算是一种特殊的对象(关于JavaScript对象的部分,我如今还在写,下一篇就会出的),arguments[0]
其实就是经过对象的属性去调用(数组的默认属性类型是数值而普通对象的属性类型是字符串),那么如今其实运用的是规则2,this
被绑定到arguments
上,而arguments
确实存在一个length
属性,而且值为2(这个别告诉我你看不出来),因此输出的确定就是2
啦。
可见《你不知道的JavaScript》这本书说的很对,之因此会在ES6出现箭头函数,实质就像用词法做用域代替this
,由于这个真的特别特别容易误用和让人误解。
欢迎你们到个人我的博客看看,https://mrerhu.github.io ?