javaScript 有一套完全不同于其它语言的对 this 的处理机制。this的指向不仅是由定义函数的方式和位置决定,同时还严重受到函数调用方式的影响
1. 在全局范围内
this 指向全局对象,浏览器是 window 对象, node 是 global 对象
2. 作为函数调用
在函数内部,this 指向全局对象。
function foo() {
console.log(this); // window or global
}
foo();
/*
<ref *1> Object [global] {
global: [Circular *1],
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
},
queueMicrotask: [Function: queueMicrotask],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
}
}
*/
3.作为一个方法调用,关联在一个对象上
this指向该方法所在的对象
// 方法调用
let name = 'xyz';
let ninja = {
name: 'skulk',
getName: function() {
console.log(this.name)
}
}
ninja.getName(); // skulk
4. 作为一个构造函数调用
在函数内部,this 指向新创建的对象。
//构造函数调用
function Bar(name) {
this.name = name;
this.skulk = function() {
console.log(this)
}
}
let bar = new Bar('abc');
bar.skulk();
// { name: 'abc', skulk: [Function (anonymous)] }
5.通过apply和call方法调用
当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this 将会被 显式设置为函数调用的第一个参数。
// call or apply 调用
function juggle() {
let result = 0;
for (let n=0; n<arguments.length; n++) {
result += arguments[n];
}
this.results = result;
}
let ninja1 = {};
let ninja2 = {};
juggle.apply(ninja1, [1,2,3,4]);
juggle.call(ninja2, 5,6,7,8);
console.log(ninja1); // { results: 10 }
console.log(ninja2); // { results: 26 }