本文中主要涉及了 this 的指向与作用域相关问题。
入门级
var length = 10;
function logLength() {
console.log(this.length);
}
logLength()
复制代码
结果非常简单是 10
说明:此时 this
指向 window
, 我们知道在全局声明 var length = 10;
等同于 window.length = 10;
需要动一点点脑筋的
var length = 10;
function logLength() {
console.log(this.length);
}
var obj = {
length:5,
method:function(func) {
this.func = func
this.func()
func()
}
}
obj.method(logLength);
复制代码
结果是 5, 10
5
这个结果也没什么难的,只不过将函数引用赋给了对象 obj
的属性 func
,因此这时候 this
指向 obj
,对应的 length
为 5
。
那么 10
这个结果怎么解释呢?众所周知,this.func()
是方法调用模式, func()
是函数调用模式。
说明:方法调用模式会绑定 this
为调用对象,而函数调用模式 this
有全局性即 window
。
有点意思的
var length = 10;
function logLength() {
console.log(this.length);
}
var obj = {
length:5,
method:function(func) {
func.apply(null)
func.call(this)
}
}
obj.method(logLength);
复制代码
结果是 10, 5
我们已经知道,函数调用模式, this
只能指向 window
。 为此,存在 call
和 apply
起到了扩展作用域的功能。
不妨使点坏
var length = 10;
function logLength() {
console.log(this.length);
}
var obj = {
length:5,
method:function(func) {
arguments[0]()
}
}
obj.method(logLength, "do something bad");
复制代码
这时候输出结果是什么呢?
结果是 2
如果你都答对了,可以停下来去欣赏别的文章了。没答对的请跟我来,我们继续来看另一个例子:
var arr = [logLength]
function logLength() {
console.log(this.length);
}
arr[0]()
复制代码
结果输出 1
那么不难看出,arr[0]
是引用的函数 logLength
, 方法调用的时候 this
是指向数组 arr
的。同理,arr
相当于上个例子的 arguments
,因为传了两个参数,所以输出为 2
。
演绎
如果用箭头函数呢?
var length = 10;
var logLength = ()=> {
console.log(this.length);
}
var obj = {
length:5,
method:function(func) {
func();
func.call(this)
this.func = func
this.func()
arguments[0]()
}
}
obj.method(logLength);
复制代码
结果输出 10, 10, 10, 10
上面的规则貌似全部被摧毁……
因为箭头函数在声明时 this
指向什么,那么就会一直指向什么。