在JS中this有以下几种绑定规则。this的绑定是在函数调用时才被确定的
- 默认绑定
- 隐私绑定
- 显示绑定
- new绑定
this默认绑定
独立函数调用,this会绑定到全局对象中。严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined。
const foo = () => console.log(this);
foo(); // 输出: window
"use strict"
const bar = () => console.log(`this指向-->:`, this)
bar() // undefined
this隐式绑定
当函数作为对象的方法被调用时,this会绑定该对象。
const obj = {
name: 'Alice',
sayName() {
console.log(this.name);
}
};
obj.sayName(); // 输出: Alice
隐式绑定丢失
参数传递丢失
将一个对象方法传入另一个函数进行调回,这里相当于在一个函数中进行独立函数调用
const obj= {
baz: function() {
console.log(this) // window
}
}
function lose(fn) {
fn()
}
lose(obj.baz)
变量赋值丢失
对象中的函数赋值给一个变量再调用这个变量,这里相当于独立函数调用,指向window全局对象。
const obj= {
baz: function() {
console.log(this) // window
}
}
let fn = obj.baz
fn()
this显式绑定
通过调用函数来改变this指向。在JS中有三个方法能够实现。
bind、call、apply 方法都有可以有目的的改变函数this指向。简单说一下它们之间的区别。使用语法参考MDN文档。
- bind:放回一个永久指向目标的函数,并且传入的参数形式为是参数列表。
- apply:立即调用,传入的参数形式为数组,并且只是临时的改变一次this指向。
- call:立即调用,传入的参数形式为是参数列表,并且只是临时的改变一次this指向。
const foo = function.bind(targetObj, arg1, arg2, ...)
function.call(targetObj, arg1, arg2, ...)
function.apply(targetObj, [argsArray])
new绑定
当使用new操作符创建一个对象实例时,this会绑定到该实例对象。
function Person(name) {
this.name = name;
}
const person = new Person('Alice');
console.log(person.name); // 输出: Alice
- 在内存中创建一个空对象
- this指向空对象
- 将构造函数中的显式原型赋值给这个对象作为对象的隐式原型(那么就意味着通过该构造函数创建出来的所有对象的隐式原型指向该构造函数的显式原型)
- 执行函数体, 为新对象添加实例属性和实例方法
- 如果函数没有返回其他对象,自动返回这个新对象。
this绑定优先级
显式绑定 > 隐式绑定 > 默认绑定
new绑定 > 隐式绑定 > 默认绑定
显示绑定和new绑定不能同时存在,故这里不做比较!
箭头函数绑定规则
由于箭头函数没有自己的this。当在箭头函数中使用this并调用函数时,this会自动往上层作用域的非箭头函数进行相应的绑定。