成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

「前端面試題系列4」this的原理以及用法

fnngj / 1641人閱讀

摘要:但是有一個(gè)總的原則那就是總會(huì)指向,調(diào)用函數(shù)的那個(gè)對(duì)象。作為對(duì)象方法的調(diào)用函數(shù)作為某個(gè)對(duì)象的方法調(diào)用,這時(shí)就指這個(gè)上級(jí)對(duì)象。

這是前端面試題系列的第 4 篇,你可能錯(cuò)過(guò)了前面的篇章,可以在這里找到:

偽類與偽元素的區(qū)別及實(shí)戰(zhàn)

如何實(shí)現(xiàn)一個(gè)圣杯布局?

今日頭條 面試題和思路解析

在前端的面試中,經(jīng)常會(huì)問(wèn)到有關(guān) this 的指向問(wèn)題。最近,朋友Z 向我求助說(shuō),他一看到 this 的題目就犯難,搞不清楚 this 究竟指向了誰(shuí)。我為他做了解答,并整理成了這篇文章,希望能幫到有需要的同學(xué)。

一道面試題

朋友Z 給我看了這樣一道題:

var length = 10;

function fn () {
    console.log(this.length);
}
 
var obj = {
    length: 5,
    method: function (fn) {
        fn();
        arguments[0]();
    }
};
 
obj.method(fn, 1);

問(wèn):瀏覽器的輸出結(jié)果是什么?

它的答案是:先輸出一個(gè) 10,然后輸出一個(gè) 2

讓我們來(lái)解析一下原因:

在我們這道題中,雖然 fn 作為 method 的參數(shù)傳了進(jìn)來(lái),但它的調(diào)用者并不受影響,任然是 window,所以輸出了 10。

arguments[0]();這條語(yǔ)句并不常見(jiàn),可能大家有疑惑的點(diǎn)在這里。 其實(shí),arguments 是一種特殊的對(duì)象。在函數(shù)中,我們無(wú)需指出參數(shù)名,就能訪問(wèn)??梢哉J(rèn)為它是一種,隱式的傳參形式

當(dāng)執(zhí)行 arguments[0](); 時(shí),其實(shí)調(diào)用了 fn()。而這時(shí),fn 函數(shù)中 this 就指向了 arguments,這個(gè)特殊的對(duì)象。obj.method 方法接收了 2 個(gè)參數(shù),所以 arguments 的 length,很顯然就是 2 了。

改造一下

再來(lái),不少同學(xué)對(duì) this 的指向感到疑惑,是因?yàn)?this 并沒(méi)有指向我們預(yù)期的那個(gè)對(duì)象。

就像這道題,從語(yǔ)義上來(lái)看,我們期望 fn() 輸出的是 obj 自己的 length,也就是 5,而不是 10。那么如果要得到 5 的結(jié)果,我們?cè)撊绾涡薷倪@段代碼呢?

其實(shí)只要多做一步處理就好。就是讓 this 指向 obj 自己。這里,我們可以用 call 來(lái)改變 this 的指向,像下面這樣:

var length = 10;

function fn () {
    console.log(this.length);
}

var obj = {
    length: 5,
    method: function (fn) {
        // 在這里用call 將 this 指向 obj 自己
        fn.call(this);
    }
};
 
obj.method(fn);

輸出的結(jié)果就是 5 了,搞定。

看吧,this 也沒(méi)那么復(fù)雜吧,我們只需要一些簡(jiǎn)單的操作,就能控制 this 的指向了。那么,問(wèn)題來(lái)了,為什么有時(shí)候 this 會(huì)失控呢?

其實(shí),這與 this 機(jī)制背后的原理有關(guān)。不過(guò)別急,讓我們從理解 this 的基本概念開(kāi)始,先來(lái)看看 this 到底是什么?

this 是什么?

this 是 JavaScript 中的一個(gè)關(guān)鍵字。它通常被運(yùn)用于函數(shù)體內(nèi),依賴于函數(shù)調(diào)用的上下文條件,與函數(shù)被調(diào)用的方式有關(guān)。它指向誰(shuí),則完全是由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。

所以,this,是在運(yùn)行時(shí)綁定的,而與編寫(xiě)時(shí)的綁定無(wú)關(guān)。隨著函數(shù)使用場(chǎng)合的不同,this 的值也會(huì)發(fā)生變化。但是有一個(gè)總的原則:那就是this 總會(huì)指向,調(diào)用函數(shù)的那個(gè)對(duì)象。

為什么要用this?

從概念上理解起來(lái),似乎有點(diǎn)費(fèi)勁。那我們?yōu)槭裁催€要使用 this 呢?用了 this 會(huì)帶來(lái)什么好處?

讓我們先看下面這個(gè)例子:

function identify() {
    return this.name.toUpperCase();
}

var me = {
    name: "Kyle"
};

var you = {
    name: "Reader"
};

identify.call( me ); // KYLE
identify.call( you ); // READER

一開(kāi)始我們可能太不明白為何這樣輸出。那不如先換個(gè)思路,與使用 this 相反,我們可以明確地將環(huán)境對(duì)象,傳遞給 identify()。像這樣:

function identify(context) {
    return context.name.toUpperCase();
}
identify( you ); // READER

在這個(gè)簡(jiǎn)單的例子中,結(jié)果是一樣的。我們可以把環(huán)境對(duì)象直接傳入函數(shù),這樣看來(lái)比較直觀。但是,當(dāng)模式越發(fā)復(fù)雜時(shí),將執(zhí)行環(huán)境作為一個(gè)明確的參數(shù)傳遞給函數(shù),就會(huì)顯得非常混亂了。

而 this 機(jī)制,可以提供一種更優(yōu)雅的方式,來(lái)隱含地“傳遞”一個(gè)對(duì)象的引用,這會(huì)使得 API 的設(shè)計(jì)更加地干凈,復(fù)用也會(huì)變得容易。

this 的原理

明白了 this 的概念之后,不經(jīng)讓我好奇,為何 this 指向的就是函數(shù)運(yùn)的執(zhí)行環(huán)境呢?

之前,看到了 阮老師 的一篇文章,十分透徹地分析了 this 的原理。我根據(jù)自己的理解,整理如下。

很多教科書(shū)會(huì)告訴你,this 指的是函數(shù)運(yùn)行時(shí)所在的環(huán)境。但是,為什么會(huì)這樣?也就是說(shuō),函數(shù)的運(yùn)行環(huán)境到底是怎么決定的?

理解 this 的原理,有助于幫我們更好地理解它的用法。JavaScript 語(yǔ)言之所以有 this 的設(shè)計(jì),跟內(nèi)存里面的數(shù)據(jù)結(jié)構(gòu)有關(guān)系。

來(lái)看一個(gè)簡(jiǎn)單的示例:

var obj = { foo: 5 };

上面的代碼將一個(gè)對(duì)象賦值給變量 obj。JavaScript 引擎會(huì)先在內(nèi)存里面,生成一個(gè)對(duì)象 { foo: 5 },然后把這個(gè)對(duì)象的內(nèi)存地址賦值給變量 obj。

也就是說(shuō),變量 obj 其實(shí)只是一個(gè)地址。后面如果要讀取 obj.foo,引擎先從 obj 拿到內(nèi)存地址,然后再?gòu)脑摰刂纷x出原始的對(duì)象,返回它的 foo 屬性。

這樣的結(jié)構(gòu)很清晰,但如果屬性的值是一個(gè)函數(shù),又會(huì)怎么樣呢?比如這樣:

var obj = { foo: function () {} };

這時(shí),JavaScript 引擎會(huì)將函數(shù)多帶帶保存在內(nèi)存中,然后再將函數(shù)的地址賦值給 foo 屬性的 value 屬性。

可以看到,函數(shù)是一個(gè)多帶帶的值(以地址形式賦值),所以才可以在不同的環(huán)境中執(zhí)行。

又因?yàn)?,JavaScript 允許在函數(shù)體內(nèi)部,引用當(dāng)前環(huán)境的其他變量。所以需要有一種機(jī)制,能夠在函數(shù)體內(nèi)部獲得當(dāng)前的運(yùn)行環(huán)境(context)。所以,this就出現(xiàn)了,它的設(shè)計(jì)目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。

this 的用法

在理解了 this 的原理之后,我們用下面的 5 種情況,來(lái)討論 this 的用法。

1、純粹的函數(shù)調(diào)用

這是函數(shù)的最通常用法,屬于全局性調(diào)用,因此 this 就代表全局對(duì)象 window。

function test(){
    this.x = 1;
    console.log(this.x);
}
test(); // 1
2、作為對(duì)象方法的調(diào)用

函數(shù)作為某個(gè)對(duì)象的方法調(diào)用,這時(shí) this 就指這個(gè)上級(jí)對(duì)象。

function test(){
    console.log(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1
3、作為構(gòu)造函數(shù)調(diào)用

所謂構(gòu)造函數(shù),就是通過(guò)這個(gè)函數(shù)生成一個(gè)新對(duì)象(object)。這時(shí),this 就指這個(gè)新對(duì)象。

function test(){
    this.x = 1;
}
var o = new test();
console.log(o.x); // 1
4、apply調(diào)用

apply() 是函數(shù)對(duì)象的一個(gè)方法,它的作用是改變函數(shù)的調(diào)用對(duì)象,它的第一個(gè)參數(shù)就表示改變后的調(diào)用這個(gè)函數(shù)的對(duì)象。因此,this 指的就是這第一個(gè)參數(shù)。

var x = 0;
function test() {
    console.log(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m.apply(); //0

apply() 的參數(shù)為空時(shí),默認(rèn)調(diào)用全局對(duì)象。因此,這時(shí)的運(yùn)行結(jié)果為0,證明this指的是全局對(duì)象。

它與上文中提到的 call 的作用是一樣的,只是寫(xiě)法上略有區(qū)別。由于篇幅原因,我會(huì)另啟一篇,來(lái)詳述它們的用法。

5、箭頭函數(shù)

ES6 中的箭頭函數(shù),在大部分情況下,使得 this 的指向,變得符合我們的預(yù)期。但有些時(shí)候,它也不是萬(wàn)能的,一不小心的話,this 同樣會(huì)失控。

因?yàn)槠鶅?nèi)容較多,我會(huì)另寫(xiě)一篇文章來(lái)介紹。

另一道面試題

最后,讓我們來(lái)鞏固一下 this 的概念和用法。來(lái)看一道面試題:

window.val = 1;
 
var obj = {
    val: 2,
    dbl: function () {
        this.val *= 2; 
        val *= 2;       
        console.log("val:", val);
        console.log("this.val:", this.val);
    }
};

 // 說(shuō)出下面的輸出結(jié)果
 obj.dbl();
 var func = obj.dbl;
 func();

答案是輸出:2 、 4 、 8 、 8

解析:

執(zhí)行 obj.dbl(); 時(shí), this.val 的 this 指向 obj,而下一行的 val 指向 window。所以,由 window.val 輸出 2,obj.val 輸出 4 。

最后一行 func(); 的調(diào)用者是 window。 所以,現(xiàn)在的 this.val 的 this 指向 window。

別忘了剛才的運(yùn)算結(jié)果,window.val 已經(jīng)是 2 了,所以現(xiàn)在 this.val *= 2; 的執(zhí)行結(jié)果就是 4。

val *= 2; 的執(zhí)行結(jié)果,就是 8 了。 所以,最終的結(jié)果就是輸出 8 和 8 。

總結(jié)

this 指代了函數(shù)當(dāng)前的運(yùn)行環(huán)境,依賴于函數(shù)調(diào)用的上下文條件,在運(yùn)行時(shí)才會(huì)進(jìn)行綁定。請(qǐng)牢記總原則:this 總會(huì)指向,調(diào)用函數(shù)的那個(gè)對(duì)象

參考文獻(xiàn)

this 與對(duì)象原型

JavaScript 的 this 原理

PS:歡迎關(guān)注我的公眾號(hào) “超哥前端小?!?,交流更多的想法與技術(shù)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/101252.html

相關(guān)文章

  • 前端面試系列5」ES6 中箭頭函數(shù)用法

    摘要:在這里,如果用箭頭函數(shù),可以這樣改寫(xiě)箭頭函數(shù)并沒(méi)有自己的,所以事件處理函數(shù)的調(diào)用者并不受影響。比如,在需要?jiǎng)討B(tài)上下文的場(chǎng)景中,使用箭頭函數(shù)需要格外地小心,這些場(chǎng)景包括對(duì)象的方法原型方法事件的回調(diào)構(gòu)造函數(shù)。 showImg(https://segmentfault.com/img/bVboce6?w=1304&h=734); 前言 年味兒漸散,收拾下心情,繼續(xù)敲代碼吧。 對(duì)于即將到來(lái)金三...

    betacat 評(píng)論0 收藏0
  • 前端面試系列6」理解函數(shù)柯里化

    摘要:原題如下寫(xiě)一個(gè)方法,當(dāng)使用下面的語(yǔ)法調(diào)用時(shí),能正常工作這道題要考察的,就是對(duì)函數(shù)柯里化的理解。當(dāng)參數(shù)只有一個(gè)的時(shí)候,進(jìn)行柯里化的處理。這其實(shí)就是函數(shù)柯里化的簡(jiǎn)單應(yīng)用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 這是前端面試題系列的第 6 篇,你可能錯(cuò)過(guò)了前面的篇章,可以在這里找到: ES6 中箭頭函數(shù)的...

    liaorio 評(píng)論0 收藏0
  • 前端面試系列7」Javascript 中事件機(jī)制(從原生到框架)

    摘要:要想注冊(cè)過(guò)的事件能夠被解除,必須將回調(diào)函數(shù)保存起來(lái),否則無(wú)法解除。當(dāng)用阻止瀏覽器的默認(rèn)行為時(shí),會(huì)做下面這件事停止回調(diào)函數(shù)執(zhí)行并立即返回。 showImg(https://segmentfault.com/img/bVboOcb?w=750&h=422); 前言 這是前端面試題系列的第 7 篇,你可能錯(cuò)過(guò)了前面的篇章,可以在這里找到: 理解函數(shù)的柯里化 ES6 中箭頭函數(shù)的用法 thi...

    Tony 評(píng)論0 收藏0
  • 18年求職面經(jīng)及總結(jié)

    摘要:年求職面經(jīng)及總結(jié)我的求職之路差不多走到盡頭了感覺(jué)真是精疲力盡了把這大半年的經(jīng)歷和面試總結(jié)寫(xiě)下來(lái)希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫助先說(shuō)背景微電子科學(xué)與工程專業(yè)學(xué)過(guò)兩門(mén)和相關(guān)的課程語(yǔ)言和單片機(jī)這個(gè)專業(yè)的唯一好處就是大部分人并不知道這個(gè)專 18年求職面經(jīng)及總結(jié) 我的求職之路差不多走到盡頭了,感覺(jué)真是精疲力盡了.把這大半年的經(jīng)歷和面試總結(jié)寫(xiě)下來(lái),希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫...

    zhangwang 評(píng)論0 收藏0
  • 18年求職面經(jīng)及總結(jié)

    摘要:年求職面經(jīng)及總結(jié)我的求職之路差不多走到盡頭了感覺(jué)真是精疲力盡了把這大半年的經(jīng)歷和面試總結(jié)寫(xiě)下來(lái)希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫助先說(shuō)背景微電子科學(xué)與工程專業(yè)學(xué)過(guò)兩門(mén)和相關(guān)的課程語(yǔ)言和單片機(jī)這個(gè)專業(yè)的唯一好處就是大部分人并不知道這個(gè)專 18年求職面經(jīng)及總結(jié) 我的求職之路差不多走到盡頭了,感覺(jué)真是精疲力盡了.把這大半年的經(jīng)歷和面試總結(jié)寫(xiě)下來(lái),希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫...

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

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

0條評(píng)論

fnngj

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<