- 函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象。
请看下面这个例子:
var a = {
x: 'haha',
f: () => {
console.log(this.x);
}
};
var b = {
x: 'heiehi'
};
a.f(); // undefined
a.f.call(b); // undefined
输出undefined
是因为箭头函数定义时所在对象为global
对象,没有x属性(是在global
对象的环境下定义的,即定义时this
指向global
,而不是a对象,这里容易混淆)。该函数在定义时,this
就被绑定了定义时的所在对象。
再看一个例子:
function get() {
return {
f: () => {
console.log(this.x);
}
}
};
var b = {
x: 'heiehi'
};
get.call(b).f(); // heihei
// 或
var b = {
x: 'heiehi',
get: function () {
return {
f: () => {
console.log(this.x);
}
}
}
};
b.get().f(); // heihei
这里get函数运行时的this
指向b,f定义时this
绑定了b。
PS: 在node中,运行一个js程序:
//test.js
function a() {
console.log(this === global ? 'global' : this);
}
console.log(this); // {}
console.log(this === global); // false
a(); // global
a.call({x:1}); // {x:1}
可见与浏览器环境不同,全局环境下代码执行时的this
指向一个空对象,全局环境下调用函数,会将global
对象传给this
。而在浏览器环境中(global
为window
对象),全局环境下的this
即指向window
。
- 不可以使用
arguments
对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
请看下面例子:
function a() {
return () => {
console.log(arguments);
}
}
a(1,2,3)(5,6); // {'0':1,'1':2,'2':3}
箭头函数内访问arguments
时,访问的是外层代码块的arguments
。
再看一个例子:
//test.js
var a = 0;
// arguments = {};
setTimeout(() => {
console.log(a);
if (++a<10) {
setTimeout(arguments.callee, 500);
}
}, 500); // 1,1,1,1,1.................无限
在node环境中,上述代码里的arguments.callee
指向node运行test.js文件时,用来包裹代码的函数。因此以上所有代码就会不断重复执行
在浏览器环境中,会报出arguments undefined
的错误。因为浏览器运行js代码不像node会包个函数在外面,所以箭头函数中的代码运行时,直接找外层代码块中的arguments,不在函数中所以就找不到了。
这时如果把arguments = {}
这句去注释,则不会报错。看来箭头函数运行时查找arguments
也和查找普通变量一样。
总结:
this
、arguments
在箭头函数内的调用过程:箭头函数运行时,引擎不定义这俩变量,这样就会沿着作用域链向上查找,找到了箭头函数定义时的this
与arguments
变量(这句话可能不严谨,还不了解js引擎,大概意思就是箭头函数根本没有自己的this
,导致内部的this
就是外层代码块的this
)。
这也是为什么箭头函数不能作为构造函数的原因。