简介
this是函数内部的特殊对象之一(其他还有arguments、caller、new.target)。
this的指向或值是不确定的,取决于函数的调用方式。并且在严格模式和非严格模式下的表现也不同。
全局上下文中的this
当函数不作为对象的属性被调用时,this指向全局对象,浏览器中是window对象。
console.log(this);
this.name = 'Hello';
console.log(window.name); // Hello
无论使不使用严格模式,上面的this都指向全局对象。
不论在哪个上下文环境,都可以使用globalThis获取全局对象。
函数上下文中的this
函数内部的this由函数的调用方式决定。
const obj = {
getThis: function () {
console.log(this);
},
};
function getThis() {
console.log(this);
}
obj.getThis();
getThis();
若是使用严格模式,this的值需要自行指定为任意值,默认为undefined。
function getThis() {
"use strict";
console.log(this);
}
函数作为对象方法被调用时,this绑定为调用的对象。
形式为obj.func(),func的this被绑定为obj,无论func是否是obj原型链上的方法。
类上下文中的this
类的本质是也是函数。
类的所有非静态方法都被添加到类的构造函数中的this的原型上。
class Example {
constructor() {
const proto = Object.getPrototypeOf(this);
console.log(Object.getOwnPropertyNames(proto));
}
first(){}
second(){}
static third(){}
}
new Example(); // ['constructor', 'first', 'second']
派生类中的this
派生类中的构造函数中的this不会自动绑定,需要使用super(),相当于this = new Base(),其中Base为基类。
class Base {}
// 派生类没有构造函数
class Good extends Base {}
// 派生类构造函数返回一个对象替换this
class AlsoGood extends Base {
constructor() {
return { a: 5 };
}
}
class Better extends Good {
constructor() {
super();
}
}
// 派生类带有空构造函数
class Bad extends Base {
constructor() {}
}
new Good();
new AlsoGood();
new Better();
new Bad(); // Uncaught ReferenceError: must call super constructor before using 'this' in derived class constructor
call、apply和bind绑定this
当使用call或apply调用时,this指向传入的第一个参数。
func.call(thisArg, arg1, arg2, ...);
func.apply(thisArg, [argsArray]); // argsArray为参数数组
func.bind(thisArg, arg1, arg2, ...);
call和bind的区别:call会立即执行函数,bind不会立即执行函数,而是返回一个新函数,你可以随时调用它。但是bind只生效一次。
function add(c, d) {
return this.a + this.b + c + d;
}
var o = { a: 1, b: 3 };
// 第一个参数是用作“this”的对象
// 其余参数用作函数的参数
add.call(o, 5, 7); // 16
// 第一个参数是用作“this”的对象
// 第二个参数是一个数组,数组中的两个成员用作函数参数
add.apply(o, [10, 20]); // 34
// 第一个参数是用作“this”的对象
// 其余参数用作函数的参数
let newAdd = add.bind(o, 11, 22);
newAdd(); // 37
newAdd = newAdd.bind({ a: 0, b: 0 }, 11, 22); // 37
call、apply和bind如果传入的this参数不是对象,而是原始值:
- 数字,
this = new Number(num) - 字符串,
this = new String(str) - null或undefined,
this = globalThis
箭头函数中的this
箭头函数中的this与封闭词法环境的this保持一致。
通俗点说,就是与定义时而非调用时在的词法环境的this保持一致。
var globalObject = this;
var foo = () => this;
console.log(foo() === globalObject); // true
// 作为对象的一个方法调用
var obj = { foo: foo };
console.log(obj.foo() === globalObject); // true
// 尝试使用 call 来设定 this
console.log(foo.call(obj) === globalObject); // true
// 尝试使用 bind 来设定 this
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
call、apply和bind都无法改变箭头函数的this。
位于函数中的箭头函数:
function foo(){
return () => this;
}
foo返回了一个匿名函数,称为A,那么A返回的this与foo函数的this保持一致,而foo的this与其调用时所在词法环境的this一致。
function foo() {
return () => this;
}
foo()(); // Window
function bar() {
return foo();
}
bar()(); // Window
const obj = { a:1}
foo.call(obj)().a; // 1