分享關於JavaScript中執行上下文(this)的使用心得

接觸JavaScript這門語言已有兩年多了,剛開始使用時覺着這門語言真是通俗易懂,能夠說是代碼隨着想法而出。但用着用着就發現某些功能與你所想要的結果不一樣(閉包中的this,對象中的函數,對象上的原型...)。期間在網上查閱各類JavaScript學習資料,其中對this這個關鍵的內容佔了不小的一部分,本身也一直想系統對this相關知識進行梳理梳理,最近項目不是太忙就抽了點時間寫一下本身對this的理解,有興趣的小夥伴能夠查閱查閱(各位大神就沒必要浪費大家寶貴的時間了)。bash

先來張本文的思惟導圖:閉包

1.爲何使用this呢?

先看看不使用this和使用this的代碼對比:函數

var me = {
    name: '小明'
}
//不使用this
function name(context){
    console.log("個人名字是"+context.name)
}
name(me)//個人名字是小明
//使用this
function name(){
    console.log("個人名字是"+this.name)
}
name.call(me)//個人名字是小明
複製代碼

顯而易見,若是沒有this咱們就須要給函數顯示的傳入一個上下文對象。對於不使用this來講,若是咱們調用函數時傳遞的變量愈來愈複雜,那咱們的代碼確定會顯得很混亂。反之使用this就不會出現這些狀況。 結論:this提供了一種更優雅的方式來隱示的傳遞一個對象的引用,能夠使咱們的API設計顯得更加簡潔和易於複用。學習

2.常見的對this理解的誤區

1).this是指向自身的麼? this指向自身,從英語的語法角度能夠說的通。可是在JavaScript語法中若是這樣理解,就會產生意想不到的bug。 分析以下代碼:ui

foo.myname = "who am I?"
function foo(){
   this.myname = "I am foo"
}
foo()
console.log(foo.myname)// "who am I?"
複製代碼

若是this是指向自身的話那麼輸出的應該是 I am foo,然而控制檯輸出的是"who am I?"。那麼this.myname指向的哪裏呢?若是此時你在控制檯輸入 console.log(myname)//"I am foo",可見咱們建立了一個全局變量。關於this是否指向自身的結論一目瞭然。答案是NOthis

2).this指向他所處函數(或對象)的做用域麼? 思考以下代碼:spa

function foo(){
    var a=2;
    this.bar()//目的爲了聯通foo和bar的做用域
}
function bar(){
    console.log(this.a)
}
foo()//undefined
*代碼引用你不知道的Javascript上卷80頁,有興趣能夠去看看這本書,書中的例子都很是經典*
複製代碼

上述例子是個很經典的js代碼片斷,表面上看沒有什麼語法錯誤。它的錯誤之處是在於將JavaScript的this和詞法做用域混合使用了,所以這段代碼是不可能實現的。 結論:不管什麼時候咱們都要分清JavaScript中的this和詞法做用域是兩個不一樣的概念。設計

3.this究竟是什麼?

在JavaScript內部每當js運行時,每個做用域都會生成一個內部對象,這個內部對象用關鍵字this表示。這句話總結了this是如何出現的(動態的產生,很符合JavaScript這門語言的動態特色),也說明的this的綁定其實跟他的聲明位置沒有半毛錢關係,值取決於函數的調用方式。code

var obj={
    name:"i am obj",
    func:function (){
        console.log(this==obj)
    }
}
obj.func()//true
複製代碼

(func:「你是屬於個人。」this:「NO,只是暫時住你這而已,我是屬於obj的.」)cdn

4.用好this的須要理解什麼?

要想將JavaScript中this綁定這個功能化爲己用咱們還須要理解this的各類調用方式即全局調用局部調用

1.全局調用(此時爲全局上下文)不用多說了,此時this至關於window

console.log(this==window)//true
複製代碼

2.局部調用(此時做爲函數上下文)

  • 函數調用
function foo(){
   console.log(this == window)//true
}
foo()
複製代碼

此種調用至關於全局調用的結果(符合咱們第三節所說的,this的值取決於函數的調用方式),由於調用函數的位置是在全局變量下。

  • 方法調用 console.log('Hello World!') 1)對象方法調用
var myname = "window"
var obj={
    myname:"object",
    func: function(){
        console.log(this.myname)
    }
}
obj.func()//"object"
複製代碼

當函數做爲對象裏的方法被調用時,它們的 this 是調用該函數的對象.

2)bind方法調用

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});//g是與f具備相同函數體和做用域的函數
console.log(g()); // azerty //此時this至指向{a:"azerty"}

複製代碼

3)構造函數中調用

function foo(){
  this.name = "function";
}

var o = new foo();
console.log(o.name); //"function"
複製代碼

當一個函數用做構造函數時(使用new關鍵字),它的this被綁定到正在構造的新對象。 關於this的調用方式MDN中的this章節developer.mozilla.org/zh-CN/docs/…說明比較詳細,有興趣的小夥伴能夠去看看。

相關文章
相關標籤/搜索