JavaScript 中的 this 关键字

和其它许多面向对象的语言一样,JavaScript 中也有 this 关键字,this 在函数中用来指向调用此方法的对象。实际编程中要判断 this 到底指向谁,一般可遵循以下原则:

  1. 如果该函数被 Function.call 或者 Function.apply 调用,那么 this 指向 call/apply 的第一个参数,如果参数是 null 或者 undefinedthis 则指向全局对象(在浏览器中的话,全局对象就是 window 对象)。
  2. 如果该函数被 Function.bind 调用,那么 this 将指向 bind 的第一个参数(方法被创建时)。
  3. 如果该函数被一个对象作为方法调用,那么 this 指向这个对象。
  4. 如果该函数只是光溜溜的作为函数被调用,不附属于任何对象,那么 this 指向全局变量 window

函数被 Function.call 调用的例子:

var myObject = {
    sayHello : function() {
        console.log('Hi! My name is ' + this.myName);
    },

    myName : 'Rebecca'
};

var secondObject = {
    myName : 'Colin'
};

myObject.sayHello();                  // logs 'Hi! My name is Rebecca'
myObject.sayHello.call(secondObject); // logs 'Hi! My name is Colin'

函数被 Function.call 调用过的例子:

var myName = 'the global object',

    sayHello = function () {
        console.log('Hi! My name is ' + this.myName);
    },

    myObject = {
        myName : 'Rebecca'
    };

var myObjectHello = sayHello.bind(myObject);

sayHello();       // logs 'Hi! My name is the global object'
myObjectHello();  // logs 'Hi! My name is Rebecca'

函数被对象调用的例子:

var myName = 'the global object',

    sayHello = function() {
        console.log('Hi! My name is ' + this.myName);
    },

    myObject = {
        myName : 'Rebecca'
    },

    secondObject = {
        myName : 'Colin'
    };

myObject.sayHello = sayHello;
secondObject.sayHello = sayHello;

sayHello();               // logs 'Hi! My name is the global object'
myObject.sayHello();      // logs 'Hi! My name is Rebecca'
secondObject.sayHello();  // logs 'Hi! My name is Colin'

在调用一个很深的命名空间中函数的时候,我们通常会缓存一个变量指向那个要调用的函数,以减少代码量。但是这样做会改变函数中 this 的值,最终执行错误的操作。例如:

var myNamespace = {
    myObject : {
        sayHello : function() {
            console.log('Hi! My name is ' + this.myName);
        },

        myName : 'Rebecca'
    }
};

var hello = myNamespace.myObject.sayHello;

hello();  // logs 'Hi! My name is undefined'

所以,要缓存变量以节省代码量的话,正确的做法是只节省到调用那个函数的对象为止:

var myNamespace = {
    myObject : {
        sayHello : function() {
            console.log('Hi! My name is ' + this.myName);
        },

        myName : 'Rebecca'
    }
};

var obj = myNamespace.myObject;

obj.sayHello();  // logs 'Hi! My name is Rebecca'

总之,有一个大原则:谁调用了那个函数,this 就指向谁。

via http://jqfundamentals.com/

Posted on 2012-03-05

No Comments

Leave a Comment