全局作用域:
1. 在浏览器全局作用域下
- 在浏览器的全局作用域中进行 var 声明:
this的指向是统一的,都是 window (self, frames, globalThis)
var a = 'aa';
var b = function () { return 'function b'; }
console.log(a); // 'aa'
console.log(b()); // 'function b'
console.log(this.a); // 'aa'
console.log(this.b()); // 'function b'
console.log(window.a); // 'aa'
console.log(window.b()); // 'function b'
2.在对象作用域下, window 和 this 的指向是不同的
var a = 'global a';
var obj = {
a: 'obj a',
foo: function () {
console.log(this.a);
console.log(window.a, self.a, frames.a);
}
};
obj.foo();
- 在严格模式下 (
'use strict';)和 ESModule 中,函数中的this指向为undefined - DOM 绑定的事件处理函数中,
this指向绑定的元素
2. 在 node 环境的作用域下
- var 声明的变量, 不会加挂到
global(或者globalThis)中 - 在 Node.js 模块中,函数中的
this指向为module.exports
类 / 构造函数下
- 类与构造函数是相似的,
this指向那个被类 / 构造函数实例化出来的对象
function Person1(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
Person1.prototype.d = function () {}
Person1.prototype.e = [
'welcome',
'to'
];
class Person2 {
constructor(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
d() {
// ...
}
}
Person2.prototype.e = ['', ''];
extends继承:this指向实例化的类示例对象
class Father {
constructor(fName) {
this.fName = fName;
}
}
class Son extends Father {
constructor(sName) {
super('Micheal');
this.sName = sName;
}
}
const s = new Son('Jackie');
补充 -
super的本质
- 调用了父类上的
constructor- 生成了
this绑定 -> Fatherthis-> Son 实例能够访问this->new Father()->{/**/}
注意
在
super调用之前, 不可以访问 class 的 this (为了指向同一个对象引用)
强制改变 this 指向
举个例子:
- 使用 bind 改变 this 指向
function foo(b, c) {
console.log(this.a, b, c);
}
var obj1 = {
a: 1
};
var obj2 = {
a: 5
};
var foo1 = foo.bind(obj1, 2, 3);
foo1(); // 1 2 3
var foo2 = foo1.bind(obj2, 2, 3);
foo2(); // 1 2 3 // bind只会生效一次 (foo.bind(obj1, 2, 3).bind(obj2, 2, 3))
关于箭头函数中的 this
const foo1 = () => {
console.log(this, this.a);
}
var a = 2;
var obj1 = {
a: 1,
};
foo1(); // window ('use strict'也是window)
foo1.call(obj1); // 2
foo1.apply(obj1); // 2
var foo2 = foo1.bind(obj1);
foo2(); // 2
- 箭头函数是忽略任何形式的
this指向的改变 (无法使用 call, apply, bind 进行修改)- 箭头函数中看到的
this表现出静态性- 箭头函数一定不是一个构造函数 (不能被实例化), 所以箭头函数本身是不存在
this的- 箭头函数中的
this不是谁绑定就指向谁- 箭头函数的
this指向上下文 (外层作用域的this指向), 但是外层函数不能是箭头函数
规律总结
this指向的基本原则, 谁调用this的宿主,this就指向谁- 对象方法中的
this指向通常是寻找最近的引用
var obj2 = {
a: 1,
b: 2,
c: function () {
// 独立的函数
function d1 () {
console.log(this);
}
obj2.d2 = function () {
console.log(this);
}
this.d3 = function () {
console.log(this);
}
d1();
}
};
obj2.c();
obj2.d2();
obj2.d3();
class Father {
constructor() {
this.eat = this.eat.bind(this);
}
get fruit() {
return 'orange';
}
eat() {
console.log('eating fruits : ', this.fruit);
}
}
class Son {
get fruit() {
return 'apple';
}
}
let f = new Father();
let s = new Son();
s.eat = f.eat;
s.eat();