【搬运翻译】理解JavaScript中的关键字`this`

96 阅读2分钟

原链接:www.30secondsofcode.org/articles/s/…

什么是this?

javaScript中,this关键词指向了正在执行代码的对象,可以简单总结如下:

  • 默认情况下,this指向全局对象global object
  • 非严格模式下,普通函数中的this指向全局对象global object
  • 严格模式下,普通函数中的thisundefined
  • 箭头函数中,this的指向与其词法上下文环境中的this保持一致;
  • 对象函数中,this指向了调用该方法的对象;
  • 构造函数中,this指向(绑定,binding)正在新建的对象;
  • 事件回调函数中,this指向了(绑定,binding)放置监听函数的元素;

全局上下文Global Context

在全局执行上下文,this指向全局对象global object

console.log(this === window); // true

函数上下文Function Context

非严格模式下,函数this指向全局对象

function f() {
  return this;
}

console.log(f() === window); // true

严格模式下,若没有设置执行上下文,函数中的thisundefined

'use strict';

function f() {
  return this;
}

console.log(f()); // undefined

对象上下文Object Context

当调用对象函数时,this指向调用该函数的对象Caller Object,指向对象可以定位在原型链上任何位置(原生或继承方法)

const obj = {
  f: function() {
    return this;
  }
};

const myObj = Object.create(obj);
myObj.foo = 1;

console.log(myObj.f()); // { foo: 1 }

当对象函数是构造函数constructor时,this指向新建对象

class C {
  constructor() {
    this.x = 10;
  }
}

const obj = new C();
console.log(obj.x); // 10

箭头函数上下文Arrow Function Context

在箭头函数中,this指向封闭词法上下文中的this

const f = () => this;

console.log(f() === window); // true

const obj = {
  foo: function() {
    const baz = () => this;
    return baz();
  },
  bar: () => this
};

console.log(obj.foo()); // { foo, bar }
console.log(obj.bar() === window); // true

注意console.log(obj.bar() === window); // truethis指向了全局对象window而不是obj,并没有像对象函数中的this,指向调用方;

事件回调上下文Event Handler Context

当在DOM元素中绑定一个事件回调函数时,函数this指向了绑定该监听器的DOM元素

const el = document.getElementById('my-el');

el.addEventListener('click', function() {
  console.log(this === el); // true
});

el.addEventListener('click', () => {
  console.log(this === el); // false
});

注意() => { console.log(this === el); // false },箭头函数仍指向了全局对象window,其事件回调函数是箭头函数,而不是普通函数;

绑定this

使用Function.prototype.bind(),从已有的函数返回一个新的函数,其this永久绑定bind()传入的第一个参数对象

function f() {
  return this.foo;
}

var x = f.bind({foo: 'hello'});
console.log(x()); // 'hello'

也可以用Function.prototype.call()或者Function.prototype.apply(),其也会绑定this至传入的第一个参数,但不会返回一个新的函数,只在本次调用生效;

function f() {
  return this.foo;
}

console.log(f.call({foo: 'hi'})); // 'hi'