乐趣区

面对对象四对象的方法中this

var obj ={
foo: function () {

console.log(this);

}
};

obj.foo() // obj
上面代码中,obj.foo 方法执行时,它内部的 this 指向 obj。
但是,下面这几种用法,都会改变 this 的指向。

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window
上面代码中,obj.foo 就是一个值。这个值真正调用的时候,运行环境已经不是 obj 了,而是全局环境,所以 this 不再指向 obj。

可以这样理解,JavaScript 引擎内部,obj 和 obj.foo 储存在两个内存地址,称为地址一和地址二。obj.foo()这样调用时,是从地址一调用地址二,因此地址二的运行环境是地址一,this 指向 obj。但是,上面三种情况,都是直接取出地址二进行调用,这样的话,运行环境就是全局环境,因此 this 指向全局环境。上面三种情况等同于下面的代码。

上面三种情况等同于下面的代码。

// 情况一
(obj.foo = function () {
console.log(this);
})()
// 等同于
(function () {
console.log(this);
})()

// 情况二
(false || function () {
console.log(this);
})()

// 情况三
(1, function () {
console.log(this);
})()

2.this 所在的方法不在对象的第一层(一个函数一层)

这时 this 只是指向当前一层的对象,而不会继承更上面的层

var a = {
p: ‘Hello’,
b: {

m: function() {console.log(this.p);
}

}
};

a.b.m() // undefined
上面代码中,a.b.m 方法在 a 对象的第二层,该方法内部的 this 不是指向 a,而是指向 a.b,因为实际执行的是下面的代码。

var b = {
m: function() {
console.log(this.p);
}
};

var a = {
p: ‘Hello’,
b: b
};

(a.b).m() // 等同于 b.m()

var a = {
b: {

m: function() {console.log(this.p);
},
p: 'Hello'

}
};

var hello = a.b.m;
hello() // undefined
上面代码中,m 是多层对象内部的一个方法。为求简便,将其赋值给 hello 变量,结果调用时,this 指向了顶层对象。为了避免这个问题,可以只将 m 所在的对象赋值给 hello,这样调用时,this 的指向就不会变。

var hello = a.b;
hello.m() // Hello

退出移动版