JavaScript中的“this”是什么?
在JavaScript中,this关键字指的是正在执行代码的当前对象。this的值可能会根据函数的调用方式而改变。
以下是一个示例,说明this的值如何在不同的上下文中发生变化:
const obj = {
name: 'John',
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
obj.sayHello(); // Output: "Hello, my name is John"
const greeting = obj.sayHello;
greeting(); // Output: "Hello, my name is undefined"
在第一次调用sayHello时,this指的是obj,因为该函数是作为obj上的方法调用的。
在对sayHello的第二次调用中,该函数被分配给变量greeting,并作为常规函数调用。所以,在这种情况下,this指的是全局对象(在浏览器中,这是window对象)。由于没有在全局级别声明变量name,它解析为undefined。
什么是绑定?
在JavaScript中,绑定是指设置this关键字值的过程。当调用一个函数时,该函数中this的值由函数的调用方式决定。
不要将绑定与bind()方法混淆!
有哪些不同类型的绑定?
有4种类型的绑定:
- 隐式绑定
- 显式绑定
- 全局绑定
- 无绑定(箭头函数)
隐式绑定
在JavaScript中,隐式绑定是指调用函数时确定this关键字值的方式。如果函数作为对象上的方法调用,则this的值设置为函数内的对象。这被称为“隐式绑定”,因为this的值是根据调用函数的上下文隐式(自动)确定的。
这是一个隐式绑定的示例:
const obj = {
name: 'John',
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
obj.sayHello(); // Output: "Hello, my name is John"
在上面的例子中,sayHello函数作为obj上的方法被调用,所以函数中this的值被设置为obj。当函数执行时,它输出“Hello, my name is John”,因为this.name相当于obj.name,也就是“John”。
显式绑定
在JavaScript中,显式绑定是指使用bind、call或apply方法显式(手动)设置this关键字的值的过程。
bind方法创建一个新函数,其主体和参数与原始函数相同,但this的值永久设置为传递给bind的第一个参数。
以下是使用bind方法创建具有显式值this的新函数的示例:
const obj = {
name: 'John',
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const greeting = obj.sayHello.bind(obj);
greeting(); // Output: "Hello, my name is John"
call和apply方法的工作方式类似于bind,但它们会立即使用this的指定值调用函数,而不是返回新函数。
以下是使用call方法调用具有显式值this的函数的示例:
const obj = {
name: 'John',
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
obj.sayHello.call(obj); // Output: "Hello, my name is John"
apply方法与call相同,但有一点不同。虽然call方法接受参数作为逗号分隔值,但apply逗号分隔值方法接受它们作为数组。
全局绑定
在JavaScript中,this关键字的值由调用函数的上下文决定,在全局执行上下文中(即在任何函数之外),this的值被设置为全局对象。
在浏览器中全局对象是window对象,所以this在全局执行上下文中的值是window对象
下面是如何在全局执行上下文中将this的值设置为全局对象的示例:
console.log(this); // Output: Window {...}
function sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
sayHello(); // Output: "Hello, my name is undefined"
在上面的例子中,this被设置为全局执行上下文中的全局对象(window对象),当调用sayHello函数时,函数内this的值也被设置为全局对象,因为函数被作为独立函数调用(而不是作为对象上的方法)
请注意,在严格模式下(当在脚本或函数的顶部使用“使用严格”指令时),全局执行上下文中this的值是未定义的,而不是全局对象。
无绑定:箭头函数和this关键字
在JavaScript中,箭头函数(也称为“胖箭头函数”)是编写函数表达式的一种简洁方式。与常规函数不同,箭头函数没有自己的this值。相反,它们继承周围上下文的this值。
以下是使用this关键字的箭头函数示例:
const obj = {
name: 'John',
sayHello: () => {
console.log(`Hello, my name is ${this.name}`);
}
};
obj.sayHello(); // Output: "Hello, my name is undefined"
在上面的例子中,sayHello函数是一个箭头函数,它使用this关键字来访问obj对象的name属性。但是,当调用该函数时,它会输出“Hello, my name is undefined”,因为函数中this的值没有按预期设置为obj。
这是因为箭头函数没有自己的this值;它们继承周围上下文的this值。在这种情况下,箭头函数中的this值是全局对象(在浏览器中是window对象),因为箭头函数不是作为对象上的方法调用的。
如果您想在箭头函数中使用this关键字并让它引用定义函数的对象,您可以在常规函数中使用箭头函数,或者使用bind方法显式设置this的值。
以下是在常规函数中使用箭头函数来访问周围上下文的this值的示例:
const obj = {
name: 'John',
sayHello: function() {
const sayName = () => {
console.log(`Hello, my name is ${this.name}`);
};
sayName(); // Output: "Hello, my name is John"
}
};
obj.sayHello();
在上面的例子中,sayName箭头函数是在sayHello函数内部定义的,因此它可以访问sayHello函数的this值,即obj。当调用sayName函数时,它会输出“Hello, my name is John”,因为this.name的值obj.name,即“John”。
进一步阅读
- 了解MDN中的“this”关键字。
- The ‘this’ keyword and the object methods.