理解JavaScript中的this关键字

JavaScript函数调用中关于对象的引用一直是一个令人头疼的问题,造成这种困扰的很大一部分的原因是this关键字造成的。本文将深入探讨this关键字的各种用法,以及在不同情景中的表现。
this是一个关键字,不是变量,也不是属性名,JavaScript的语法不允许给this赋值,它没有作用域的限制。

普通的函数调用

在JavaScript中,每一个函数调用都会包含一个this值。对于普通的函数调用this指向全局对象,在严格模式下,this则为undefined
以函数形式调用的函数通常不用指定this关键字,不过可以使用this来判断当前是否处于严格模式中。

var strict = (function() { return !this; }());

普通函数调用的例子:

JavaScript Code:
function sayHi(name) {
  console.log(this + " says hello " + name);
}
sayHi("Jack");//[object Window] says hello Jack
sayHi.call("Jones", "Jack");//Jones says hello Jack
window.sayHi("Jack");//[object Window] says hello Jack
sayHi.call(window,"Jack");//[object Window] says hello Jack

嵌套的函数调用

嵌套的函数不会从调用它的函数中继承this,如果嵌套函数作为方法调用,那么this指向调用它的对象。如果嵌套函数作为函数调用,那么this
的值是全局对象或者undefined,这取决与处于何种模式下(严格模式、非严格模式)。如果想访问外部函数的this值,则需要将this的值保存到一个变量中。

JavaScript Code:
var person = {
  getName: function() {
    var that = this;
    console.log(this === person);//true
    f();
    function f() {
      console.log(this === person);//false
      console.log(that === person);//true
    }
  }
};

成员函数调用

一种常见的情形是成员函数的使用,通过该对象来调用。
JavaScript Code:
var person = {
name: “Jack”;
sayHi: function(thing) {
console.log(this.name + “ says hello “ + thing);
}
};
person.sayHi(“world!”);//Jack says hello world!

函数sayHi如何同person对象关联并不影响this的指向,我们来看一个动态关联的例子:

JavaScript Code:
var person = { name: "Jack"};
function sayHi(thing) {
    console.log(this.name + " says hello " + thing);
}
person.sayHi = sayHi;
person.sayHi("world!");//Jack says hello world!
sayHi("world!");//[object window] says hello world!

间接调用

我们可以通过callapply来间接的调用函数,这两个都允许显示的指定调用所需的this值,也就是说任何函数都可以作为任何对象的方法来调用,即使这个函数不是某对象的方法。这两个方法的不同之处在于call使用自有的实参列表作为函数的实参,apply接受一个数组。

JavaScript Code:
function sayHi(name) {
  console.log(this + " says hello " + name);
}
sayHi.call("Jones", "Jack");//Jones says hello Jack
sayHi.call(window,"Jack");//[object Window] says hello Jack
sayHi.apply("Jones", ["Jack"]);//Jones says hello Jack

有时候我们希望能够引用一个有着持久化this值的函数,那么我们可以使用bind函数。

JavaScript Code:
function bind(func, obj) {
  if (func.bind) {
    return func.bind(obj);
  } else {
    return function() {
      func.apply(obj, arguments);
    };
  }
}
var bindSayHi = bind(person.sayHi, person);
bindSayHi("world!");//Jack says hello world!

jQuery中的this

JavaScript Code:
$("button").click(function(event) {
  console.log($(this).prop("name"));
});

$(this)等同于jQuery中的this关键字,它被用在一个匿名函数内部,该函数在buttonclick方法中执行。jQuery$(this)绑定到调用click方法的对象上,所以$(this)指向$("button")对象,即使$(this)被用在匿名函数内部,外部this对其不可见。

参考文献: