一句话讲明白javascript的this

今天看了这篇文章What is “this” in JavaScript?,颇受启发,觉得总结得非常好,一句话可以概括:this指针依赖于谁来调用。

下面两句话 小明喜欢DC漫画; 小明喜欢漫威漫画。

概括为一句小明喜欢DC漫画,也喜欢漫威漫画。这个他就类似javascript中的this指代,要依据上下文来判断。

回到这一句this指针依赖于谁来调用(这个方法,函数,构造器)。再来查看官方定义,全都是围绕这个解释的。

Global context

// In web browsers, the window object is also the global object:
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b)  // "MDN"
console.log(b)         // "MDN"

可以看作是window是调用者,没毛病。

Function context

function f1() {
  return this;
}

// In a browser:
f1() === window; // true 

// In Node:
f1() === global; // true

window调用的

// An object can be passed as the first argument to call or apply and this will be bound to it.
var obj = {a: 'Custom'};

// This property is set on the global object
var a = 'Global';

function whatsThis() {
  return this.a;  // The value of this is dependent on how the function is called
}

whatsThis();          // 'Global'
whatsThis.call(obj);  // 'Custom'
whatsThis.apply(obj); // 'Custom'

直接指明调用者

function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = g.bind({a: 'yoo'}); // bind only works once!
console.log(h()); // azerty

var o = {a: 37, f: f, g: g, h: h};
console.log(o.f(),o.f(), o.g(), o.h()); // 37,37, azerty, azerty

bind就是为了绑定this到指定的对象

箭头函数(Arrow functions)

var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true

箭头函数的this指的是定义这个箭头函数时的上下文的this,call, bind, apply指定this的方式对箭头函数无效。

另外,一个类的方法如果需要override(重写),就不能用箭头函数的定义方式,因为它始终指向的是基类。

As an object method

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // 37

依然是看调用者

getter or setter

function sum() {
  return this.a + this.b + this.c;
}

var o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  }
};

Object.defineProperty(o, 'sum', {
    get: sum, enumerable: true, configurable: true});

console.log(o.average, o.sum); // 2, 6

依然是看调用者

As a constructor

/*
 * Constructors work like this:
 *
 * function MyConstructor(){
 *   // Actual function body code goes here.  
 *   // Create properties on |this| as
 *   // desired by assigning to them.  E.g.,
 *   this.fum = "nom";
 *   // et cetera...
 *
 *   // If the function has a return statement that
 *   // returns an object, that object will be the
 *   // result of the |new| expression.  Otherwise,
 *   // the result of the expression is the object
 *   // currently bound to |this|
 *   // (i.e., the common case most usually seen).
 * }
 */

function C() {
  this.a = 37;
}

var o = new C();
console.log(o.a); // 37


function C2() {
  this.a = 37;
  return {a: 38};
}

o = new C2();
console.log(o.a); // 38

可以看作构造器所在的类为调用者

As a DOM event handler

<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>

可将元素当作调用者来理解

来个混淆的例子

<button onclick="alert((function() { return this; })());">
  Show inner this
</button>

上例中由于匿名函数不是在事件监听的代码顶层,而是被包含在一个闭包中,可看作是全局闭包,那自然this就是window了。


Total views.

© 2013 - 2018. All rights reserved.

Powered by Hydejack v6.6.1