亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript this關(guān)鍵字

ghnor / 1631人閱讀

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

涵義

this關(guān)鍵字是一個非常重要的語法點。毫不夸張地說,不理解它的含義,大部分開發(fā)任務都無法完成。

首先,this總是返回一個對象,簡單說,就是返回屬性或方法“當前執(zhí)行環(huán)境”的對象。

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";        // 等價于 window.name = "window"; 和this.name = "window"; 因為此時window===this
showName();         // My name is window

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

當通過這兩個對象調(diào)用describe方法時,分別輸出zs和ls的name屬性。

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

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

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

zs.describe(); this === zs

ls.describe(); this === ls

showName(); this === window

再看一個例子:




點擊三個按鈕,控制臺輸出結(jié)果分別是什么呢?

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

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

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

使用場合

this的使用是很廣泛的,其作用也非常強大。我們可以將this的使用歸為一下幾類。

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

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

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ù)賦值給了實例對象就是通過this來完成的。

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 

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

對象的方法

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

大多數(shù)情況下,this指的是當前的這個對象,比如:

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"}

上面代碼中在通過box對象來調(diào)用setNamegetName方法的情況下,this指的就是當前的這個對象,此處為box,也正是由于這種情況下的this指的是當前對象,我們才能通過這兩個方法對box的name屬性進行讀寫。

但是只有box.getName() box.setName("box1")這樣使用時,this才指向當前對象。請看下面例子:

當將一個對象的一個方法賦給另一個對象時,this的指向也會改變。

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

雖然bag.getName 實際是對box.getName 的一個引用,由于運行時使用的是bag.getName(),此時是在bag對象下運行的,this也就指的是bag了。

再看一點奇怪的:

// 注意 box.getName 沒有括號
(false || box.getName)(); // window
(false ? alert : box.getName)(); // window

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

可以這么理解:

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

全局環(huán)境

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

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

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

thisIs(); // true

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

Node

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

ES6箭頭函數(shù)

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

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

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

foo(); // name: window

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

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

我們再看一下箭頭函數(shù)中這一點的表現(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é)果來看一下,上面代碼轉(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直接固定成了其定義時所在的對象,此處為foo。實際在箭頭函數(shù)中的所有this都是一個對象,這個對象就是其定義時所在對象的this,上面轉(zhuǎn)換后的結(jié)果中在foo中首先使用一個變量記錄下this,而在箭頭函數(shù)中的this被替換成了之前存儲this的那個變量。

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

使用注意點 避免多層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é)果卻并不是想要的這樣,這是因為在立即執(zhí)行的函數(shù)內(nèi)部,this的執(zhí)行不再是box對象而變成了頂層對象window,因此第二行輸出為undefined。

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

將上例進行改寫:

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提供的嚴格模式use strict,如果函數(shù)內(nèi)部的this直接指向了頂層對象會直接報錯。

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,應該需要了解其含義,否則可能出現(xiàn)意料之外的結(jié)果。

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

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

綁定this的方法

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

function.prototype.call()

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

var obj = {};

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

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

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

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

function.prototype.apply()

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

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

function.prototype.bind()

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

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

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

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



這樣點擊第二個按鈕,將可以正確輸出張三的名字。

bind第一個參數(shù)為一個對象,為undefinednull是默認傳入window。

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

參考鏈接

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

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

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/82151.html

相關(guān)文章

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

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

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

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

    LeoHsiun 評論0 收藏0
  • Javascript 深入淺出This

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

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

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

    jayzou 評論0 收藏0
  • javascriptthis的理解

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

    jimhs 評論0 收藏0
  • 理解JavaScript的核心知識點:This

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

    TerryCai 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<