1. 程式人生 > >js中this物件的理解

js中this物件的理解

最近在參加的幾場面試中都涉及到了對於jsthis物件的理解,那麼怎樣去理解this呢?這裡針對不同的場景通過程式碼來幫助我們理解好this

this到底指向什麼?

this指向什麼呢?一言以蔽之:

this最終指向的是那個呼叫它的物件

下面通過程式碼來分析this的指向問題。

預設繫結全域性變數window

var a = 'hello';

function foo() {
    console.log( this.a );
}

foo(); // hello 

這裡呼叫foo()就相當於window.foo()。因此this引用的是window。也就是下面這句話:

如果一個函式中有this

,但是它沒有被上一級的物件所呼叫,那麼this指向的就是window

隱式繫結

function foo() {
    console.log( this.a );
}

var obj = {
    a: 'hello',
    foo: foo
};

obj.foo(); // hello 

這裡呼叫foo的是obj,因此this指向的是obj物件。

再來看一個例子:

function foo() {
    console.log( this.a );
}
var obj2 = {
    a: 'hello',
    foo: foo
};
var obj1 = {
    a:
'world', obj2: obj2 }; obj1.obj2.foo(); // hello

這個例子可能看起來比較暈,那麼this指向的是obj1還是obj2呢?其實關於this的引用還有一句話要記住:

如果一個函式中有this,這個函式中包含多個物件,儘管這個函式是被最外層的物件所呼叫,this指向的也只是它上一級的物件

理解了上面兩個例子之後再看一種情況:

function foo() {
    console.log( this.a );
}

var obj = {
    a: 'hello',
    foo: foo
};

var bar = obj.foo;
// 函式引用傳遞 var a = "Global"; bar(); // "Global"

這裡this指向的是window物件,想要理解這點還需要記住一句話:

this永遠指向的是最後呼叫它的物件,也就是看它執行的時候是誰呼叫的

上面的例子中雖然函式foo是被物件obj所引用,但是在將foo賦值給變數bar的時候並沒有執行,最終foo是由bar來執行的,而bar指向的是window物件。

顯示繫結

通過bind(),apply(),call()函式可以顯示的繫結this作用域,它接收的第一個引數即是上下文物件並將其賦給this。

function foo() {
    console.log( this.a );
}

var obj = {
    a: 'hello'
};

foo.call(obj); // hello

如果我們傳遞第一個值為簡單值,那麼後臺會自動轉換為對應的封裝物件。如果傳遞為null,那麼結果就是在繫結預設全域性變數。看下面的例子:

function foo() {
     console.log( this.a );
}

var obj = {
     a: 2
};

var a = 'hello';
foo.call( null); // hello

new新物件繫結

如果是一個建構函式,那麼用new來呼叫,那麼繫結的將是新建立的物件。如:

function foo(a) {
    this.a = a;
}

var bar = new foo('hello');
console.log(bar.a);// hello

this在閉包裡的簡單應用

如果已經理解了上面this的基本用法,那麼我們來看一個this在閉包的指向問題:

var flag = "window";
var object = {
    flag : "local",
    sayFlag: function(){
        //返回一個匿名函式
        return function(){
            console.log(this.flag);
        }
    }
}
object.sayFlag()(); //window

這裡的this是在一個匿名函式裡面呼叫的,object.sayFlag()函式返回的是一個匿名函式,也就是說this應該指向的是匿名函式的執行環境,那麼匿名函式的執行環境到底應該是什麼呢?

匿名函式的執行環境具有全域性性,this通常指向window

那麼如何訪問“local呢”?

var flag = "window";
var object = {
    flag : "local",
    sayFlag: function(){
        var that = this; //此處的this是object的引用
        //返回一個匿名函式
        return function(){
            alert(that.flag);
        }
    }
}
object.sayFlag()(); //local