this關(guān)鍵字

JavaScript中this關(guān)鍵字的幾點(diǎn)說(shuō)明:
****1.JavaScript中的this關(guān)鍵字綁定的內(nèi)容跟函數(shù)無(wú)關(guān),跟函數(shù)執(zhí)行的環(huán)境有關(guān)****
****2.函數(shù)的this綁定的內(nèi)容可以通過(guò)bind,apply和call函數(shù)來(lái)動(dòng)態(tài)進(jìn)行修改****
****3.閉包可以消除不必要的this動(dòng)態(tài)綁定來(lái)提高代碼的可讀性****

1.this綁定內(nèi)容與函數(shù)無(wú)關(guān),與執(zhí)行環(huán)境有關(guān)
一個(gè)函數(shù)在調(diào)用時(shí)會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象,活動(dòng)對(duì)象還包含一個(gè)this變量。

var name = "javascript";
var func = function(){
    console.log(this.name);
}
func();

當(dāng)調(diào)用func函數(shù)時(shí),js引擎會(huì)創(chuàng)建一個(gè)執(zhí)行上下文,同時(shí)還會(huì)創(chuàng)建一個(gè)作用域鏈,此作用域鏈為:

[[scope chain]] = [
{
      Active Object{
            arguments:...
            this:[global Object],
            ...
      },
      global Object:{
            name:'javascript'
            ...
      }
}
]

所以在執(zhí)行console.log(this.name)的時(shí)候this綁定的是全局對(duì)象,而之前定義的name就是屬于全局變量。

再看下面的例子:

var name = "jack";
var sex = "man"

var func = function(name){
      this.name = name;
}
func.prototype.print = function(){
      console.log(this.name);
      console.log(this.sex);
      console.log(sex);
}

var obj = new func("hello");
obj.print();//結(jié)果是hello     undefined      man

當(dāng)執(zhí)行obj對(duì)象的print函數(shù)的時(shí)候,執(zhí)行上下文的作用域鏈?zhǔn)沁@樣的:

[[scope chain]] = [
{
      Active Object{
            arguments:...
            this:obj,
            ...
      },
      global Object{
            name:'jack',
            sex:'man',
            ...
      }
}
]

從這個(gè)作用域鏈可以很清楚地看出上面代碼輸出的結(jié)果。

2.this綁定的內(nèi)容可以被動(dòng)態(tài)修改
把上面的例子稍作修改,如下:

var name = "jack";
var sex = "man";

var func = function(name){
        this.name = name;
}
func.prototype.print = function(){
        console.log(this.name);
        console.log(this.sex);
        console.log(sex);
}.bind(this);

var obj = new func("hello");
obj.print();//結(jié)果是jack    man     man

通過(guò)給func.prototype.print函數(shù)添加了bind的調(diào)用,輸出的結(jié)果就不一樣,此時(shí)的this綁定的是global對(duì)象了。

再把上面的代碼修改,如下:

var name = "jack";
var sex = "man";
var func = function(name){
       this.name = name;
}
func.prototype.print = function(){
       console.log(this.name);
       console.log(this.sex);
       console.log(sex);
}

var obj = new func("hello");
func.prototype.print.call(obj,"hello");//結(jié)果是hello   undefined    man

這個(gè)輸出結(jié)果跟直接調(diào)用obj.print是一樣的。但是如果改成:

var obj = new func("hello");
func.prototype.print.call(this,"hello");
//下面的window和this是等價(jià)的
//func.prototype.print.call(window,"hello");

那么輸出的結(jié)果是jack man man
使用bind可以顯式指定函數(shù)使用時(shí)的this綁定,而使用call可以指定this對(duì)象的指向,另外還可以使用apply來(lái)修改this的綁定。call和apply的區(qū)別就是call后面?zhèn)鲄⑹褂玫氖嵌禾?hào)分隔的參數(shù),而apply傳遞的是一個(gè)參數(shù)數(shù)組。

3.閉包消除this動(dòng)態(tài)綁定提高代碼可讀性
假設(shè)要把一個(gè)外部環(huán)境的this變量傳遞到一個(gè)內(nèi)部函數(shù)去使用,一般會(huì)這么做:

var a = 10;
var obj = {
    a:1;
    b:2;

    sum:function(){
         var addA = function(a){
               return this.a+a;
         }.bind(this);

         return addA(this.b);
    }
}

console.log(obj.sum());//結(jié)果是3

在聲明addA的時(shí)候使用了bind(this),那么addA函數(shù)內(nèi)部的this.a指向的是obj對(duì)象的a變量。如果不用bind,this默認(rèn)指向的是window對(duì)象,那么輸出的結(jié)果就是12了。一般情況下(考慮到sum函數(shù)里面的3個(gè)this)通常會(huì)添加一個(gè)self或者that局部變量來(lái)增加代碼的可讀性,同時(shí)也不用手動(dòng)去調(diào)用bind函數(shù)。

var a = 10;
var obj = {
      a:1,
      b:2,

      sum:function(){
            var self = this;
            var addA = function(a){
                   return self.a + a;
            };
            return addA(this.b);
      }
}

console.log(obj.sum());//結(jié)果是3

這里面的self變量利用了閉包的特性,同時(shí)讓代碼更加具有可讀性,也消除了不必要的bind(this)調(diào)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容