學習this關鍵字(一)

this關鍵字是JavaScript中最複雜的機制之一。以致於我使用多年也很難說清它到底指向什麼,咱們有必要好好學習一下。this也是咱們學習和使用JavaScript中的一座大山,咱們必須翻過這座山。java

爲何要使用this

先看一段代碼以下:函數

var foo = {
    name:'tom',
    age:'24',
    say:function(){
        console.log('name: ' + this.name + ', age: ' + this.age);
    }
}
foo.say(); //name: tom, age: 24
var bar = {
    name:'cat',
    age:'25'
}
foo.say.call(bar); //name: cat, age: 25
複製代碼

這段代碼在不一樣的上下文對象(foobar)中重複使用了函數say(),不用寫不一樣版本的函數。若是不使用this那麼就須要給函數say()顯示傳入一個上下文對象。學習

say:function(context){
        console.log('name: ' + context.name + ', age: ' + context.age);
    }
複製代碼

this隱式的傳遞了一個對象的引用,由於咱們能夠將通用模塊和API方法設計的更加易用和簡潔。ui

什麼是this

this指向函數自身

在開始工做的時候很容易把this理解成指向函數自身,不過咱們如今來分析下,this是否是指向函數自身。思考下面一段代碼:this

function foo(){
    this.name = 'tom';
}
foo.name = 'cat';
foo();
console.log(foo.name); //'cat'
複製代碼

最終打印的是cat,顯然this不是指向函數自身。執行foo.name=cat,是向對象foo添加一個name屬性,可是函數內部代碼this.name中的this並非指向那個函數對象。spa

遇到這樣的問題,咱們會採用其餘的方式來達到目的,好比建立另外一個帶有name屬性的對象。設計

function foo(){
    obj.name = 'tom';
}
var obj = {
    name:'cat'
}
foo();
console.log(obj.name); //'tom'
複製代碼

雖然這種方式確實解決了問題,其使用的是另外一種咱們比較熟悉的技術詞法做用域,並無使用this解決。3d

另外一種方法是強制this指向foo函數對象。code

function foo(){
    this.name = 'tom';
}
foo.name = 'cat';
foo.call(foo);
console.log(foo.name);//'tom'
複製代碼

此次咱們沒有迴避this,並且使用call()來幫助咱們使用thiscdn

this指向它的做用域

this的另外一個誤區就是,指向函數的做用域。這個問題有點複雜,由於在某種狀況下它是正確的,可是在其餘狀況下它倒是錯誤的。須要說明的是,this在任何狀況下都不指向函數的詞法做用域。

javaScript中,做用域確實和對象相似,可見的標識符都是它的屬性。可是做用域「對象」沒法經過 javaScript代碼訪問,它存在於javaScript引擎內部。(詳細的能夠參考以前的文章)

思考下面一段代碼:

function foo() { 
    var a = 1;  
    this.bar(); 
}
function bar() { 
    console.log(this.a);
}
foo(); //undefined
複製代碼

這段代碼看起來像是故意爲之,但實則反映出對this的不瞭解。調用bar()最經常使用的方法是省略前面的this,直接使用詞法引用標識符。這段代碼還試圖經過thisfoo()函數中聯動bar()函數訪問變量a。這也是不可能的,不能使用this來引用一個詞法做用域內部的變量及函數。

this究竟是什麼

this是在運行時進行綁定的,並非在編寫時綁定,它的上下文取決於函數調用時的各類條件。this 的綁定和函數聲明的位置沒有任何關係,只取決於函數的調用方式。

當一個函數被調用時,會建立一個執行環境(也叫執行上下文)。執行環境中的活動對象會包含函數在哪裏被調用(調用棧)、函數的調用方法、傳入的參數等信息。this就是記錄的其中一個屬性,會在函數執行的過程當中用到。(詳細的能夠參考以前的文章)

總結

this 其實是在函數被調用時發生的綁定,它指向什麼徹底取決於函數在哪裏被調用。

參考

相關文章
相關標籤/搜索