js进阶——this全面解析
全面解析 this
关键字
在 JavaScript 中,this
是一个经常让初学者困惑的概念。this
的值取决于函数的调用位置,而不是它定义的位置。因此,理解调用位置和不同的绑定规则非常重要。接下来我们详细讲解 this
的各个方面。
1. 调用位置
this
的绑定取决于调用位置,即函数被调用的上下文环境。调用位置是决定 this
如何绑定的关键。
function show() {
console.log(this);
}
show(); // 在全局环境中调用,this 默认绑定到全局对象 (浏览器中为 window)
2. this
绑定规则
2.1 默认绑定
默认绑定是最基本的规则。在非严格模式下,如果函数直接调用,this
将绑定到全局对象(在浏览器中是 window
)。在严格模式下(use strict
),this
会绑定为 undefined
。
function foo() {
console.log(this);
}
foo(); // 非严格模式下 this 是 window,严格模式下 this 是 undefined
2.2 隐式绑定
当函数作为对象的方法调用时,this
会被绑定到该对象。也就是说,调用该函数的对象是 this
的值。
const obj = {
name: 'Alice',
show() {
console.log(this.name);
}
};
obj.show(); // 输出 'Alice', this 绑定到 obj
2.3 显示绑定
通过 call
、apply
和 bind
方法,可以手动指定 this
的值,这称为显示绑定。
call
:直接调用函数并指定this
。apply
:类似于call
,但传递参数是以数组形式。bind
:返回一个新的函数,并永久绑定this
。
function greet() {
console.log(this.name);
}
const person = { name: 'Bob' };
greet.call(person); // 显式绑定 this,输出 'Bob'
greet.apply(person); // 输出 'Bob'
const boundGreet = greet.bind(person);
boundGreet(); // 输出 'Bob'
2.4 new
绑定
当通过 new
关键字调用函数时,会创建一个新的对象,并且这个对象会绑定到 this
。同时,新创建的对象会被自动返回。
function Person(name) {
this.name = name;
}
const alice = new Person('Alice');
console.log(alice.name); // 输出 'Alice'
3. this
绑定的优先级
当多个规则同时出现时,this
的绑定优先级如下:
new
绑定:如果使用了new
关键字,this
会被绑定到新创建的对象。- 显式绑定:
call
、apply
和bind
的显示绑定优先级高于隐式绑定和默认绑定。 - 隐式绑定:如果函数作为对象的方法调用,
this
会绑定到该对象。箭头函数除外
。 - 默认绑定:如果没有特殊的绑定规则,
this
会绑定到全局对象(非严格模式)或undefined
(严格模式)。
例子:
function foo() {
console.log(this.name);
}
const obj1 = { name: 'obj1', foo };
const obj2 = { name: 'obj2' };
foo.call(obj2); // 显示绑定到 obj2,输出 'obj2'
obj1.foo(); // 隐式绑定到 obj1,输出 'obj1'
4. 绑定例外
4.1 被忽略的 this
如果通过 null
或 undefined
显式绑定 this
,在调用时会忽略这种绑定,this
将会回退到默认绑定。
function foo() {
console.log(this);
}
foo.call(null); // 在非严格模式下 this 会绑定到全局对象,严格模式下 this 是 undefined
4.2 间接引用
当将对象的方法赋值给另一个变量时,this
的绑定会丢失,回退到默认绑定。
const obj = {
name: 'Alice',
greet() {
console.log(this.name);
}
};
const greetFunc = obj.greet;
greetFunc(); // this 绑定丢失,回退到默认绑定 (全局对象/undefined)
4.3 软绑定
通过自定义函数,可以创建一个软绑定 this
的方案。如果 this
是 null
或 undefined
,则 this
会被绑定到指定的默认对象。
if (!Function.prototype.softBind) {
Function.prototype.softBind = function(obj) {
const fn = this;
return function() {
return fn.apply(
(!this || this === global) ? obj : this, arguments
);
};
};
}
function foo() {
console.log(this.name);
}
const person = { name: 'Alice' };
const softBoundFoo = foo.softBind(person);
softBoundFoo(); // 输出 'Alice'
5. this
词法
箭头函数没有自己的 this
绑定。箭头函数中的 this
是从定义它的上下文继承而来的,而不是调用时确定的。
const obj = {
name: 'Alice',
arrowFunc: () => {
console.log(this.name); // 由定义它的上下文继承而来的,所以箭头函数中的 this 绑定到外部作用域,也就是全局window,obj此时还没有形成自己的上下文,因为obj的定义还没结束
},
normalFunc() {
console.log(this.name); // 普通函数的 this 绑定到 obj
}
};
obj.arrowFunc(); // 输出 undefined(取决于外部作用域的 this)
obj.normalFunc(); // 输出 'Alice'
6. 小结
this
的值取决于函数的调用位置。- 绑定规则分为:默认绑定、隐式绑定、显示绑定和
new
绑定。 - 不同绑定规则有优先级,其中
new
绑定优先于显式绑定,显式绑定优先于隐式绑定。 - 例外情况包括:被忽略的
this
、间接引用和软绑定。 - 箭头函数的
this
由外部词法作用域决定,不依赖调用时的上下文。
原文地址:https://blog.csdn.net/2301_79858914/article/details/142448669
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!