国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

fnngj / 1583人閱讀

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

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

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

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

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

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

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

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

讓我們來解析一下原因:

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

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

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

改造一下

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

就像這道題,從語義上來看,我們期望 fn() 輸出的是 obj 自己的 length,也就是 5,而不是 10。那么如果要得到 5 的結(jié)果,我們該如何修改這段代碼呢?

其實(shí)只要多做一步處理就好。就是讓 this 指向 obj 自己。這里,我們可以用 call 來改變 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 也沒那么復(fù)雜吧,我們只需要一些簡單的操作,就能控制 this 的指向了。那么,問題來了,為什么有時候 this 會失控呢?

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

this 是什么?

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

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

為什么要用this?

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

讓我們先看下面這個例子:

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

var me = {
    name: "Kyle"
};

var you = {
    name: "Reader"
};

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

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

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

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

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

this 的原理

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

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

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

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

來看一個簡單的示例:

var obj = { foo: 5 };

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

也就是說,變量 obj 其實(shí)只是一個地址。后面如果要讀取 obj.foo,引擎先從 obj 拿到內(nèi)存地址,然后再從該地址讀出原始的對象,返回它的 foo 屬性。

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

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

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

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

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

this 的用法

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

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

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

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

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

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ù),就是通過這個函數(shù)生成一個新對象(object)。這時,this 就指這個新對象。

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

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

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

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

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

5、箭頭函數(shù)

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

因?yàn)槠鶅?nèi)容較多,我會另寫一篇文章來介紹。

另一道面試題

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

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

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

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

解析:

執(zhí)行 obj.dbl(); 時, 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)行時才會進(jìn)行綁定。請牢記總原則:this 總會指向,調(diào)用函數(shù)的那個對象。

參考文獻(xiàn)

this 與對象原型

JavaScript 的 this 原理

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

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/101252.html

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

    fjcgreat 評論0 收藏0

發(fā)表評論

0條評論

fnngj

|高級講師

TA的文章

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