成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript this關(guān)鍵字

ghnor / 1591人閱讀

摘要:第二種和第三種分別為級(jí)事件和級(jí)事件,其實(shí)質(zhì)是給點(diǎn)擊事件指定了一個(gè)回調(diào)函數(shù),其為。也是和實(shí)例對(duì)象嚴(yán)格相等的,可以說(shuō)明,構(gòu)造函數(shù)中的是指代實(shí)例對(duì)象。參考鏈接關(guān)鍵字深入理解上下文在線(xiàn)轉(zhuǎn)化構(gòu)造函數(shù)原文發(fā)表在我的博客關(guān)鍵字,歡迎訪問(wèn)

涵義

this關(guān)鍵字是一個(gè)非常重要的語(yǔ)法點(diǎn)。毫不夸張地說(shuō),不理解它的含義,大部分開(kāi)發(fā)任務(wù)都無(wú)法完成。

首先,this總是返回一個(gè)對(duì)象,簡(jiǎn)單說(shuō),就是返回屬性或方法“當(dāng)前執(zhí)行環(huán)境”的對(duì)象。

var showName = function() {
    console.log("My name is", this.name);
};
var zs = {
        name: "Zhang San",
        describe: showName
    },
    ls = {
        name: "Li Si",
        describe: showName
    };
zs.describe();         // My name is Zhang San
ls.describe();         // My name is Li Si
showName();         // My name is 
name = "window";        // 等價(jià)于 window.name = "window"; 和this.name = "window"; 因?yàn)榇藭r(shí)window===this
showName();         // My name is window

上面代碼中定義了showName方法,將在控制臺(tái)輸出"My name is "并拼接上this.name,并將這個(gè)方法賦給了zs和li這兩個(gè)對(duì)象的describe方法。

當(dāng)通過(guò)這兩個(gè)對(duì)象調(diào)用describe方法時(shí),分別輸出zs和ls的name屬性。

直接在全局環(huán)境下調(diào)用showName方法并沒(méi)有報(bào)錯(cuò),但也沒(méi)有輸出任何內(nèi)容。不報(bào)錯(cuò)的原因是此時(shí)的this指的是瀏覽器的window對(duì)象,window對(duì)象有name屬性。沒(méi)有輸出內(nèi)容的原因是window.name初始值是一個(gè)空字符串。

我們給name屬性賦值為"window"后再次執(zhí)行showName方法時(shí),將輸出: My name is window

以上示例中實(shí)際都是執(zhí)行的showName方法,但是由于環(huán)境不同,輸出的結(jié)果也不同,根本原因是不同情況下的this是不一樣的。

zs.describe(); this === zs

ls.describe(); this === ls

showName(); this === window

再看一個(gè)例子:




點(diǎn)擊三個(gè)按鈕,控制臺(tái)輸出結(jié)果分別是什么呢?

第一個(gè)為:My name is window 第二個(gè)為:My name is 按鈕2 ,第三個(gè)為My name is 按鈕3

這是為什么呢?這個(gè)和綁定事件的機(jī)制有關(guān)系。第一種形式是HTML事件,onclick="showName()"表示在點(diǎn)擊時(shí)執(zhí)行showName方法,此時(shí)執(zhí)行環(huán)境為全局環(huán)境,this為window,所以輸出window。

第二種和第三種分別為DOM0級(jí)事件DOM2級(jí)事件,其實(shí)質(zhì)是給點(diǎn)擊事件指定了一個(gè)回調(diào)函數(shù),其為showName。在點(diǎn)擊事件的回調(diào)函數(shù)中,this是指當(dāng)前這個(gè)dom元素,因此輸出的值為這兩個(gè)按鈕的name屬性。

使用場(chǎng)合

this的使用是很廣泛的,其作用也非常強(qiáng)大。我們可以將this的使用歸為一下幾類(lèi)。

構(gòu)造函數(shù)

在構(gòu)造函數(shù)中,this的出現(xiàn)頻率是非常高的,它指的是實(shí)例對(duì)象。

function Person(name, gender) {    
    this.name = name;
    this.gender = gender;
}
zs = new Person( "zs" , "male" );
// {
//    name: "zs",
//    gender: "male"
// }

上面使用構(gòu)造函數(shù)產(chǎn)生實(shí)例對(duì)象時(shí),兩個(gè)參數(shù)賦值給了實(shí)例對(duì)象就是通過(guò)this來(lái)完成的。

function Person(name, gender) {
    this.name = name;
    this.gender = gender;
}
Person.prototype.showSelf = function() {
    return this;
}
zs = new Person("zs", "male");     // {name: "zs", gender: "male"}
zs.showSelf();                     // {name: "zs", gender: "male"}
zs === zs.showSelf();             // true 

上面代碼通過(guò)showSelf方法返回了構(gòu)造函數(shù)里的this,它的輸出內(nèi)容和實(shí)例對(duì)象一致。也是和實(shí)例對(duì)象嚴(yán)格相等的,可以說(shuō)明,構(gòu)造函數(shù)中的this是指代實(shí)例對(duì)象。

對(duì)象的方法

在對(duì)象里面定義的方法中也經(jīng)??吹?b>this的身影,那么此時(shí)的this指的又是什么呢?

大多數(shù)情況下,this指的是當(dāng)前的這個(gè)對(duì)象,比如:

var box = {
    id: +new Date(),
    name: "noName",
    setName: function(name) {
        this.name = name;
    },
    getName:function(){
        return this.name;
    }
}
box.getName();     // "noName"
box.setName("box1"); 
box;             // {id: 1476846238291, name: "box1"}

上面代碼中在通過(guò)box對(duì)象來(lái)調(diào)用setNamegetName方法的情況下,this指的就是當(dāng)前的這個(gè)對(duì)象,此處為box,也正是由于這種情況下的this指的是當(dāng)前對(duì)象,我們才能通過(guò)這兩個(gè)方法對(duì)box的name屬性進(jìn)行讀寫(xiě)。

但是只有box.getName() box.setName("box1")這樣使用時(shí),this才指向當(dāng)前對(duì)象。請(qǐng)看下面例子:

當(dāng)將一個(gè)對(duì)象的一個(gè)方法賦給另一個(gè)對(duì)象時(shí),this的指向也會(huì)改變。

var box = {
    name: "box",
    getName: function() {
        return this.name;
    }
};
var bag = {
    name: "bag"
};
bag.getName = box.getName;
bag.getName(); // "bag"

雖然bag.getName 實(shí)際是對(duì)box.getName 的一個(gè)引用,由于運(yùn)行時(shí)使用的是bag.getName(),此時(shí)是在bag對(duì)象下運(yùn)行的,this也就指的是bag了。

再看一點(diǎn)奇怪的:

// 注意 box.getName 沒(méi)有括號(hào)
(false || box.getName)(); // window
(false ? alert : box.getName)(); // window

上面這兩種情況下,輸出的都不再是box對(duì)象的name屬性,而是window(之前設(shè)置了window.name="window")。表示此時(shí)方法內(nèi)部的this指向的是瀏覽器頂層對(duì)象window。

可以這么理解:

box對(duì)象指向了一個(gè)地址M1box.getName作為box的一個(gè)方法,但本身也是對(duì)象,它自己也有一個(gè)地址M2,只有通過(guò)box.getName() 調(diào)用時(shí),是從M1中調(diào)用M2,所以this指向的是box。上面兩種情況都是直接拿到M2來(lái)調(diào)用,此時(shí)和M1已經(jīng)沒(méi)有任何關(guān)系了,this的指向當(dāng)前代碼塊所在的對(duì)象。

全局環(huán)境

在全局環(huán)境中使用this,在瀏覽器中,指的就是頂層對(duì)象window。

console.log(this === window); // true

function thisIs() {
    console.log(this === window);
}

thisIs(); // true

上面代碼說(shuō)明,不管this是寫(xiě)在全局環(huán)境下,還是一個(gè)函數(shù)作用域內(nèi),只要是在全局環(huán)境下運(yùn)行,this的指向都是頂層對(duì)象window。

Node

在Node中,this的指向又分成兩種情況。全局環(huán)境中,this指向全局對(duì)象global;模塊環(huán)境中,this指向module.exports。

ES6箭頭函數(shù)

ES6中新增的箭頭函數(shù)里面所使用的this和之前介紹的情況都不一樣了,在箭頭函數(shù)中this不隨其運(yùn)行環(huán)境的改變而改變,而是在聲明箭頭函數(shù)時(shí),就已經(jīng)固定下來(lái)了。箭頭函數(shù)中this的指向就是聲明箭頭函數(shù)是所在的對(duì)象。

先看一個(gè)常規(guī)的例子:

function foo() {
    setTimeout(function() {
        console.log("name:", this.name);
    }, 100);
}

foo(); // name: window

foo.call({ name: "an obj" }); // name: window

定義一個(gè)函數(shù)foo內(nèi)部使用定時(shí)器調(diào)用一個(gè)匿名函數(shù),此時(shí)函數(shù)有多層了,this的指向應(yīng)該是全局對(duì)象window,輸出結(jié)果證明了這一點(diǎn)。使用foo.call結(jié)果也相同的原因是,call替換的是foo函數(shù)內(nèi)的this指向,而輸出的this是在定時(shí)器的回調(diào)中的,故結(jié)果依然是window。

我們?cè)倏匆幌录^函數(shù)中這一點(diǎn)的表現(xiàn):

// ES6箭頭函數(shù)
function arrow_foo() {
    setTimeout(() => {
        console.log("name:", this.name);
    }, 100);
}

arrow_foo(); // name: window

arrow_foo.call({ name: "an obj" }); // name: an obj

我們發(fā)現(xiàn)結(jié)果,居然和上面不一樣了。為什么呢?我們將其轉(zhuǎn)化成ES5的結(jié)果來(lái)看一下,上面代碼轉(zhuǎn)化后的結(jié)果是這樣的:

function arrow_foo() {
    var $__1 = this;
    setTimeout(function() {
      console.log("name:", $__1.name);
    }, 100);
  }
  arrow_foo();
  arrow_foo.call({name: "an obj"});

看一下轉(zhuǎn)換后的結(jié)果,原因就一目了然了,箭頭函數(shù)中this直接固定成了其定義時(shí)所在的對(duì)象,此處為foo。實(shí)際在箭頭函數(shù)中的所有this都是一個(gè)對(duì)象,這個(gè)對(duì)象就是其定義時(shí)所在對(duì)象的this,上面轉(zhuǎn)換后的結(jié)果中在foo中首先使用一個(gè)變量記錄下this,而在箭頭函數(shù)中的this被替換成了之前存儲(chǔ)this的那個(gè)變量。

因此直接運(yùn)行時(shí),this是指全局對(duì)象,而使用call時(shí),將foo內(nèi)的this替換成了指定的對(duì)象{name: "an obj"},從而輸出的上面的結(jié)果。

使用注意點(diǎn) 避免多層this

由于this的指向是不確定的,所以切勿在函數(shù)中包含多層的this。

var box = {
    name: "box",
    size: {
        width: 300,
        height: 300
    },
    show: function() {
        console.log("name", this.name);
        (function() {
            console.log("size", this.size);
        })();
    }
};
box.show();
// name box
// size undefined

我們本意是想在show方法內(nèi)部輸出name,并輸出size,但是結(jié)果卻并不是想要的這樣,這是因?yàn)樵诹⒓磮?zhí)行的函數(shù)內(nèi)部,this的執(zhí)行不再是box對(duì)象而變成了頂層對(duì)象window,因此第二行輸出為undefined。

解決方法為,在外層用一個(gè)變量記錄下this,在要使用的地方使用那個(gè)變量。

將上例進(jìn)行改寫(xiě):

var box = {
    name: "box",
    size: {
        width: 300,
        height: 300
    },
    show: function() {
        console.log("name", this.name);
        var that = this;
        (function() {
            console.log("size", that.size);
        })();
    }
};
box.show();
// name box
// size Object {width: 300, height: 300}

這樣就能得到我們想要的正確結(jié)果了。

還用一種做法是JavaScript提供的嚴(yán)格模式use strict,如果函數(shù)內(nèi)部的this直接指向了頂層對(duì)象會(huì)直接報(bào)錯(cuò)。

var box = {
    name: "box",
    size: {
        width: 300,
        height: 300
    },
    show: function() {
        "use strict"
        console.log("name", this.name);        
        (function() {
            console.log("size", this.size);
        })();
    }
};
box.show();  
// Uncaught TypeError: Cannot read property "size" of undefined(…)
避免在回調(diào)函數(shù)中使用this

通?;卣{(diào)函數(shù)中的this都有其特定的,如果在回調(diào)函數(shù)中使用this,應(yīng)該需要了解其含義,否則可能出現(xiàn)意料之外的結(jié)果。

事件處理函數(shù)作為一種特殊的回調(diào)函數(shù),其this是指當(dāng)前的DOM對(duì)象,最開(kāi)始的例子已經(jīng)說(shuō)明了這個(gè)問(wèn)題。

回調(diào)函數(shù)本身是一個(gè)函數(shù),其作為另一個(gè)函數(shù)的參數(shù)傳遞進(jìn)去,然后在那個(gè)函數(shù)內(nèi)部執(zhí)行,這本身已經(jīng)構(gòu)成了多層this,此時(shí)this的指向是不確定的,需要慎用。

綁定this的方法

this的動(dòng)態(tài)性給JavaScript帶來(lái)了很大的靈活性,但是前面所描述的內(nèi)容中也表現(xiàn)出了其不確定性,因此有時(shí)希望能夠?qū)?b>this固定下來(lái)。

function.prototype.call()

使用函數(shù)的call方法,可以指定函數(shù)內(nèi)部this的指向,使其在指定的作用域中運(yùn)行。

var obj = {};

var f = function () {
  return this;
};

f() === this;  // true this === window
f.call(obj) === obj;  // true

上面代碼中,在全局環(huán)境運(yùn)行函數(shù)f時(shí),this指向全局環(huán)境;call方法可以改變this的指向,指定this指向?qū)ο?b>obj,然后在對(duì)象obj的作用域中運(yùn)行函數(shù)f

call方法的第一個(gè)參數(shù)為一個(gè)對(duì)象,其表示要為函數(shù)所指定的運(yùn)行上下文環(huán)境的對(duì)象(當(dāng)指定為undefinednull是默認(rèn)傳入window),之后的參數(shù)依次作為原函數(shù)的參數(shù)。

function.prototype.apply()

使用函數(shù)的apply方法同樣可以指定函數(shù)運(yùn)行的環(huán)境,作用和call相同,使用方法也類(lèi)似,都是第一個(gè)參數(shù)傳入要指定的上下文對(duì)象。不同點(diǎn)在于,apply方法最多接收兩個(gè)參數(shù),第二個(gè)參數(shù)為一個(gè)數(shù)組(無(wú)論原函數(shù)需要的參數(shù)是何種類(lèi)型,此數(shù)組中的每個(gè)元素將依次傳遞給原函數(shù)),表示傳遞給原函數(shù)的參數(shù),而call可以接收多個(gè)參數(shù),從第二個(gè)參數(shù)開(kāi)始,之后的所有參數(shù)都傳遞給原函數(shù)。

由于apply第二個(gè)參數(shù)接收的是數(shù)組,其有很多巧用。由于此文重點(diǎn)是描述this關(guān)鍵字,就不再贅述了。

function.prototype.bind()

ES5中有bind這樣一個(gè)方法,也可以指定函數(shù)的運(yùn)行環(huán)境,但是和call、apply有所不同,bind方法可接收一個(gè)參數(shù),用于指定函數(shù)運(yùn)行的上下文環(huán)境,返回一個(gè)函數(shù)作為綁定指定上下文環(huán)境后的新函數(shù)。

這樣bindcall、apply的區(qū)別就出來(lái)了:前者是根據(jù)指定的上下文環(huán)境返回一個(gè)新函數(shù),而后兩者是使用指定的上下文壞境運(yùn)行原函數(shù)

其實(shí)bindjQuery.proxy()類(lèi)似,雖然沒(méi)有后者處理多種情況,但作為JavaScript原生方法,更輕量、高效。

用本文最開(kāi)始的例子來(lái)演示此方法的使用,某對(duì)象下有某方法,我們要將此對(duì)象這個(gè)方法作為作為一個(gè)事件處理函數(shù),但不希望方法內(nèi)部的this被改變:



這樣點(diǎn)擊第二個(gè)按鈕,將可以正確輸出張三的名字。

bind第一個(gè)參數(shù)為一個(gè)對(duì)象,為undefinednull是默認(rèn)傳入window。

除此之外,bind還可以接收額外參數(shù),用于在生成新函數(shù)時(shí),從原函數(shù)的第一個(gè)參數(shù)開(kāi)始替換一部分參數(shù)(和jQuery.proxy()類(lèi)似)。比如原函數(shù)要接收兩個(gè)參數(shù),使用bind產(chǎn)生新函數(shù)時(shí),除了第一個(gè)參數(shù)的外,可以再傳入一個(gè)參數(shù),此參數(shù)將替換原函數(shù)的第一個(gè)參數(shù),這樣生成的新函數(shù)就只用接收一個(gè)參數(shù)了,詳情見(jiàn)jQuery 工具方法簡(jiǎn)析 (target=_blank)中jQuery.proxy( function, context [, additionalArguments ] )。

參考鏈接

this 關(guān)鍵字 (target=_blank)

深入理解上下文this (target=_blank)

ES6在線(xiàn)轉(zhuǎn)化 (target=_blank)

js構(gòu)造函數(shù) (target=_blank)

原文發(fā)表在我的博客JavaScript this關(guān)鍵字,歡迎訪問(wèn)!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/82151.html

相關(guān)文章

  • JavaScript 工廠函數(shù) vs 構(gòu)造函數(shù)

    摘要:當(dāng)談到語(yǔ)言與其他編程語(yǔ)言相比時(shí),你可能會(huì)聽(tīng)到一些令人困惑東西,其中之一是工廠函數(shù)和構(gòu)造函數(shù)。好的,讓我們用構(gòu)造函數(shù)做同樣的實(shí)驗(yàn)。當(dāng)我們使用工廠函數(shù)創(chuàng)建對(duì)象時(shí),它的指向,而當(dāng)從構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),它指向它的構(gòu)造函數(shù)原型對(duì)象。 showImg(https://segmentfault.com/img/bVbr58T?w=1600&h=900); 當(dāng)談到JavaScript語(yǔ)言與其他編程語(yǔ)言...

    RayKr 評(píng)論0 收藏0
  • javascript基礎(chǔ):this關(guān)鍵字

    摘要:它代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用類(lèi)似的還有??偨Y(jié)關(guān)鍵字就是,誰(shuí)調(diào)用我,我就指向誰(shuí)。注意由于已經(jīng)被定義為函數(shù)內(nèi)的一個(gè)變量。因此通過(guò)關(guān)鍵字定義或者將聲明為一個(gè)形式參數(shù),都將導(dǎo)致原生的不會(huì)被創(chuàng)建。 題目 封裝函數(shù) f,使 f 的 this 指向指定的對(duì)象 。 輸入例子 bindThis(function(a, b) { return this.test +...

    LeoHsiun 評(píng)論0 收藏0
  • Javascript 深入淺出This

    摘要:中函數(shù)的調(diào)用有以下幾種方式作為對(duì)象方法調(diào)用,作為函數(shù)調(diào)用,作為構(gòu)造函數(shù)調(diào)用,和使用或調(diào)用。作為構(gòu)造函數(shù)調(diào)用中的構(gòu)造函數(shù)也很特殊,構(gòu)造函數(shù),其實(shí)就是通過(guò)這個(gè)函數(shù)生成一個(gè)新對(duì)象,這時(shí)候的就會(huì)指向這個(gè)新對(duì)象如果不使用調(diào)用,則和普通函數(shù)一樣。 this 是 JavaScript 比較特殊的關(guān)鍵字,本文將深入淺出的分析其在不同情況下的含義,可以這樣說(shuō),正確掌握了 JavaScript 中的 th...

    Y3G 評(píng)論0 收藏0
  • 理解 JavaScript 中的 this 關(guān)鍵字

    摘要:原文許多人被中的關(guān)鍵字給困擾住了,我想混亂的根源來(lái)自人們理所當(dāng)然地認(rèn)為中的應(yīng)該像中的或中的一樣工作。盡管有點(diǎn)難理解,但它的原理并不神秘。在瀏覽器中,全局對(duì)象是對(duì)象。運(yùn)算符創(chuàng)建一個(gè)新對(duì)象并且設(shè)置函數(shù)中的指向調(diào)用函數(shù)的新對(duì)象。 原文:Understanding the this keyword in JavaScript 許多人被JavaScript中的this關(guān)鍵字給困擾住了,我想混亂的...

    jayzou 評(píng)論0 收藏0
  • javascriptthis的理解

    摘要:的關(guān)鍵字總是讓人捉摸不透,關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,的指向也不同。其實(shí)只要理解語(yǔ)言的特性就很好理解。個(gè)人對(duì)中的關(guān)鍵字的理解如上,如有不正,望指正,謝謝。 javascript的this關(guān)鍵字總是讓人捉摸不透,this關(guān)鍵字代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用,因?yàn)楹瘮?shù)的調(diào)用場(chǎng)景不同,this的指向也不...

    jimhs 評(píng)論0 收藏0
  • 理解JavaScript的核心知識(shí)點(diǎn):This

    摘要:關(guān)鍵字計(jì)算為當(dāng)前執(zhí)行上下文的屬性的值。毫無(wú)疑問(wèn)它將指向了這個(gè)前置的對(duì)象。構(gòu)造函數(shù)也是同理。嚴(yán)格模式無(wú)論調(diào)用位置,只取顯式給定的上下文綁定的,通過(guò)方法傳入的第一參數(shù),否則是。其實(shí)并不屬于特殊規(guī)則,是由于各種事件監(jiān)聽(tīng)定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個(gè)關(guān)鍵字,它的值指向了一個(gè)對(duì)象的引用。這個(gè)引用的結(jié)果非常容易引起開(kāi)發(fā)者的誤判,所以必須對(duì)這個(gè)關(guān)...

    TerryCai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<