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

資訊專欄INFORMATION COLUMN

關(guān)于this的知識(shí)歸納(通俗易懂版)

enda / 3428人閱讀

摘要:于是決定寫(xiě)個(gè)歸納。如果懂了,那么下面的例子也就會(huì)做了已知調(diào)用函數(shù)的對(duì)象是,所以指向,即。相當(dāng)于在全局作用域聲明了變量,并且賦值。實(shí)際上,調(diào)用函數(shù)的是關(guān)鍵字。使用來(lái)調(diào)用函數(shù),即函數(shù)的構(gòu)造調(diào)用時(shí),我們會(huì)構(gòu)造一個(gè)新對(duì)象,并把它綁定到調(diào)用中的上。

對(duì)this的理解,我一直都是用一句話概括:誰(shuí)調(diào)用它,它就指向誰(shuí)。

好像也沒(méi)有什么問(wèn)題,但仔細(xì)看了<你不知道的JavaScript>這本書(shū)和網(wǎng)上一些文章后,發(fā)現(xiàn)this的原理還挺講究的。于是決定寫(xiě)個(gè)歸納。
(對(duì)了,無(wú)知的我實(shí)在沒(méi)想到原來(lái)bind也和this扯上關(guān)系。。)

this的綁定規(guī)則有4種。分別是:
1、默認(rèn)綁定
2、隱式綁定
3、顯示綁定
4、new綁定

需要明確:this的值雖然會(huì)隨著函數(shù)使用場(chǎng)合的不同而發(fā)生變化,但有一個(gè)原則,它指向的是調(diào)用它所在的函數(shù)的那個(gè)對(duì)象。

1、默認(rèn)綁定(純函數(shù)調(diào)用)
function test(){
    console.log(this.a);
}
var a = 1;
test();

當(dāng)調(diào)用test()時(shí),因?yàn)閼?yīng)用了this的默認(rèn)綁定,this.a被解析成全局變量a,this指向全局對(duì)象window。所以結(jié)果為1。

怎么知道應(yīng)用了默認(rèn)綁定呢?當(dāng)前test()是直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的。這個(gè)簡(jiǎn)單來(lái)說(shuō)就是沒(méi)有任何前綴啊等東西,很純粹!而其調(diào)用位置是全局作用域,更能確定除了默認(rèn)綁定,無(wú)法應(yīng)用其他規(guī)則了。

如果懂了,那么下面的例子也就會(huì)做了

function test(){
    this.a = 2;
    console.log(a);
}
test();

已知調(diào)用函數(shù)test()的對(duì)象是window,所以this指向window,即this.a===window.a。由于window可以省略,因此簡(jiǎn)寫(xiě)成a。
相當(dāng)于在全局作用域聲明了變量a,并且賦值a=2。
this.a = 2
-->window.a = 2
-->a = 2
所以結(jié)果為2。

可能說(shuō)得太啰嗦了,直接說(shuō)下一種綁定。

2、隱式綁定(作為方法調(diào)用)

通俗地說(shuō)就是一個(gè)函數(shù),被當(dāng)作引用屬性添加到了一個(gè)對(duì)象中了,然后以 “對(duì)象名.函數(shù)名()” 形式進(jìn)行調(diào)用,這時(shí)如果函數(shù)引用有上下文對(duì)象,隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this綁定到這個(gè)上下文對(duì)象。

下面看下例子。

function test(){
    console.log(this.a);
}
var obj = {
    a:3,
    test:test
};
obj.test();

對(duì)象obj中包含兩個(gè)屬性a和test,其值分別是3和一個(gè)函數(shù)test()。
obj.test()表示函數(shù)引用時(shí)有上下文對(duì)象(也就是這里的obj)。
根據(jù)隱式綁定規(guī)則,會(huì)把test()中的this綁定到這個(gè)上下文對(duì)象,即this被綁定到obj,this.a===obj.a。
所以結(jié)果為3。

如果懂了,那么下面的例子也就會(huì)做了

 function test(){
     console.log(this.a);
 }
 var obj2 = {
     a:4,
     test:test
 };
 var obj1 = {
     a:400,
     obj2:obj2
 }
 obj1.obj2.test()

看起來(lái)復(fù)雜了些,不過(guò)只要記住下面這個(gè)準(zhǔn)則就可以了。

對(duì)象屬性引用鏈中,只有上一層或者說(shuō)最后一層在調(diào)用位置中起作用

所以只有obj2這個(gè)上下文對(duì)象生效,結(jié)果為4。

隱式綁定的番外篇——隱式丟失

這個(gè)網(wǎng)上貌似很少提及,隱式丟失,通俗來(lái)講就是“變low”了!
原本應(yīng)用隱式綁定的,因?yàn)閬G失綁定對(duì)象,變回應(yīng)用默認(rèn)綁定了!把this綁定到全局對(duì)象或undefined。

當(dāng)對(duì)象將其引用屬性給了新的引用,再次調(diào)用這個(gè)新的引用時(shí),原本this指向的對(duì)象就會(huì)改為指向window。

到底在說(shuō)什么,看個(gè)例子。

 function foo(){
     console.log(this.a);
 }
 var obj = {
     a:5,
     foo:foo
 };
 var bar = obj.foo; //這句就是關(guān)鍵
 var a = "oops, global";
 bar(); // "oops, global"

b引用了test()函數(shù)本身,此時(shí)的b()是一個(gè)不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認(rèn)綁定。

如果懂了,那么下面的例子也就會(huì)做了

 function foo(){
     console.log(this.a);
 }
 function doFoo(fn){
     fn();
 }
 var obj = {
     a:5,
     foo:foo
 }
 var a = "oops, global";
 doFoo(obj.foo); // "oops, global"

其實(shí)和上面的沒(méi)什么區(qū)別,只是這里把函數(shù)作為參數(shù)傳遞了,參數(shù)傳遞是一種隱式賦值。此時(shí)的this指向的是調(diào)用它的函數(shù)的對(duì)象即全局對(duì)象,因此應(yīng)用了默認(rèn)綁定。

3、顯示綁定(apply/call調(diào)用)

回顧一下隱式綁定,其關(guān)鍵是把函數(shù)當(dāng)作引用屬性添加到了對(duì)象中,通過(guò)這個(gè)屬性間接引用這個(gè)函數(shù),把this簡(jiǎn)介(隱式)綁定到這個(gè)對(duì)象上。
如果不想在對(duì)象內(nèi)部包含函數(shù)引用,而想簡(jiǎn)單粗暴地在某個(gè)對(duì)象強(qiáng)制調(diào)用一個(gè)函數(shù),這時(shí)就用到了函數(shù)的call()和apply()方法。
call和apply,以往我單純理解為“控制this的指向”,現(xiàn)在才發(fā)現(xiàn)是原來(lái)是this綁定規(guī)則中的一種。

call和apply區(qū)別
apply接收的是數(shù)組參數(shù),call接收的是連續(xù)參數(shù)。所以當(dāng)傳入的參數(shù)數(shù)目不確定時(shí),多使用apply。
(tips:這里推薦個(gè)方法記憶apply和call各自接收的參數(shù):apply為a開(kāi)頭,數(shù)組Array也是a開(kāi)頭,所以apply接收的是數(shù)組參數(shù))

看下面例子。

function test(){
    console.log(this.a);
}
var obj = {
    a:6
};
test.call(obj);

當(dāng)調(diào)用test時(shí)強(qiáng)制把它的this綁定到obj上。所以this.a===obj.a,結(jié)果為6。
注意:后續(xù)參數(shù)傳入的是原始值的話,會(huì)被轉(zhuǎn)換成它的對(duì)象形式(如字符串類型-->new String()如此類推)

這次我們不用call,用apply。

var a = 0;
function test(){
    console.log(this.a);
}
var obj = {};
obj.a = 7;
obj.m = test;
obj.m.apply();
obj.m.apply(obj);

同樣的,對(duì)象obj包含了兩個(gè)屬性a和m,m引用了函數(shù)test()。
obj.m.apply(obj)即把test()這個(gè)函數(shù)中的this綁定到對(duì)象obj上。即this指向的是obj。所以this.a===obj.a。
“apply沒(méi)有參數(shù)怎么辦,基本語(yǔ)法都是包含參數(shù)的啊,至少給個(gè)對(duì)象,讓this有個(gè)指向啊。”
apply定義了當(dāng)沒(méi)有參數(shù)時(shí),全局對(duì)象會(huì)自動(dòng)默認(rèn)成為其第一個(gè)參數(shù),apply()等價(jià)于apply(window)。
因此obj.m.apply(),test()中的this就指向了全局對(duì)象window,結(jié)果為0。

顯示綁定的番外篇——硬綁定

干嘛用的?解決前面提到的隱式丟失問(wèn)題。
回顧當(dāng)初隱式丟失的第二個(gè)例子。

 function foo(){
     console.log(this.a);
 }
 function doFoo(fn){
     fn();
 }
 var obj = {
     a:5,
     foo:foo
 }
 var a = "oops, global";
 doFoo(obj.foo); // "oops, global"

將其改一下變成:

 function foo(){
     console.log(this.a);
 }
 function doFoo(fn){
     fn.call(obj);
 }
 var obj = {
     a:5,
     foo:foo
 }
 var a = "oops, global";
 doFoo(obj.foo);

依舊是創(chuàng)建了doFoo()這個(gè)函數(shù),但在其內(nèi)部手動(dòng)調(diào)用了 obj.foo.call(obj),
把foo()強(qiáng)制綁定到了obj對(duì)象,之后無(wú)論如何調(diào)用doFoo(),它總會(huì)手動(dòng)在obj上調(diào)用foo。

對(duì)于硬綁定,ES5提供了一個(gè)內(nèi)置方法Function.prototype.bind,我們把上面的例子再改!

 function foo(){
     console.log(this.a);
 }
 function doFoo(fn){
     fn.bind(obj);
 }
 var obj = {
     a:5,
     foo:foo
 }
 var a = "oops, global";
 doFoo(obj.foo);

一執(zhí)行,我的天!啥也沒(méi)有????
這就對(duì)了,這是bind的“效果”,也是和apply、call的主要區(qū)別——延遲調(diào)用。
也就是說(shuō)bind其實(shí)只是函數(shù)的引用,要想執(zhí)行需要進(jìn)行回調(diào),即fn.bing(obj)(),
此時(shí)就能輸出5了。

好,現(xiàn)在把隱式丟失的第一個(gè)例子改動(dòng)

 function foo(){
     console.log(this.a);
 }
 var obj = {
     a:5,
     foo:foo
 };
 var bar = obj.foo.bind(obj); 
 var a = "oops, global";
 bar(); //5

為了能證明bind的特點(diǎn),函數(shù)在回調(diào)時(shí)執(zhí)行,把bind改成call,最后3行代碼變成

var bar = obj.foo.call(obj); 
var a = "oops, global";
bar(); //Uncaught TypeError: bar is not a function

結(jié)果報(bào)錯(cuò)了,對(duì),因?yàn)閏all和apply都是綁定后立刻執(zhí)行的,都執(zhí)行完了,bar就只是一個(gè)沒(méi)有賦值的變量而已。

總結(jié)下“顯示綁定三人組”:

 共同點(diǎn):
     1、都用于控制this指向;
     2、第一個(gè)參數(shù)都是this需要指向的對(duì)象,也就是上下文;
     3、都可以后續(xù)參數(shù)傳遞;
     4、沒(méi)有任何參數(shù)時(shí),this都指向全局對(duì)象window              
 區(qū)別:
     1、call、apply綁定后立刻執(zhí)行,bind是延遲執(zhí)行。換言之,當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時(shí)候,就使用bind()方法吧。
     
4、new綁定(作為構(gòu)造函數(shù)調(diào)用)

什么是構(gòu)造函數(shù),一個(gè)函數(shù)被new調(diào)用時(shí),該函數(shù)就是構(gòu)造函數(shù)。
(變身前:普通函數(shù);使用地?cái)傌沶ew變身器,變身后:構(gòu)造函數(shù))

function test(){
    this.x = 8;
}
var obj = new test();
console.log(obj.x);

你可以簡(jiǎn)單粗暴理解為:就相當(dāng)于test()被對(duì)象obj調(diào)用,其this指向obj。
但貌似很不規(guī)范。。

實(shí)際上,調(diào)用函數(shù)的是new關(guān)鍵字。

使用new來(lái)調(diào)用函數(shù),即函數(shù)的“構(gòu)造調(diào)用”時(shí),我們會(huì)構(gòu)造一個(gè)新對(duì)象,
并把它綁定到test()調(diào)用中的this上。所以在代碼中,this就指向了新對(duì)象obj

最后總結(jié)

判斷this的4種規(guī)則根據(jù)優(yōu)先級(jí)從高到低排序如下:

1、函數(shù)在 new 中調(diào)用,this綁定的是這個(gè)新對(duì)象
2、函數(shù)通過(guò) call、apply或bind 調(diào)用,this綁定的是指定對(duì)象
3、函數(shù)在某上下文對(duì)象中調(diào)用,this綁定的是這個(gè)上下文對(duì)象
4、以上都不是,使用默認(rèn)綁定。(在全局作用域調(diào)用,this綁定window對(duì)象)

關(guān)于this書(shū)中還提及到很多其他知識(shí),例如軟綁定、this詞法箭頭函數(shù)等,就不歸納到這里了

歸納前看過(guò)的相關(guān)書(shū)籍或文章:
1、<你不知道的JavaScript>(上)第二部分第二章 this全面解析
2、阮一峰的網(wǎng)絡(luò)日志-JavaScript的this用法
http://www.ruanyifeng.com/blo...
3、chanzen的個(gè)人博客-call,apply,bind用法和意義
http://ovenzeze.coding.me/use...
4、腳本之家-JS中的this變量的使用介紹
http://www.jb51.net/article/4...

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

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

相關(guān)文章

  • 寫(xiě)技術(shù)博客那點(diǎn)事

    摘要:從現(xiàn)在開(kāi)始,養(yǎng)成寫(xiě)技術(shù)博客的習(xí)慣,或許可以在你的職業(yè)生涯發(fā)揮著不可忽略的作用。如果想了解更多優(yōu)秀的前端資料,建議收藏下前端英文網(wǎng)站匯總這個(gè)網(wǎng)站,收錄了國(guó)外一些優(yōu)質(zhì)的博客及其視頻資料。 前言 寫(xiě)文章是一個(gè)短期收益少,長(zhǎng)期收益很大的一件事情,人們總是高估短期收益,低估長(zhǎng)期收益。往往是很多人堅(jiān)持不下來(lái),特別是寫(xiě)文章的初期,剛寫(xiě)完文章沒(méi)有人閱讀會(huì)有一種挫敗感,影響了后期創(chuàng)作。 從某種意義上說(shuō),...

    ddongjian0000 評(píng)論0 收藏0
  • 寫(xiě)技術(shù)博客那點(diǎn)事

    摘要:從現(xiàn)在開(kāi)始,養(yǎng)成寫(xiě)技術(shù)博客的習(xí)慣,或許可以在你的職業(yè)生涯發(fā)揮著不可忽略的作用。如果想了解更多優(yōu)秀的前端資料,建議收藏下前端英文網(wǎng)站匯總這個(gè)網(wǎng)站,收錄了國(guó)外一些優(yōu)質(zhì)的博客及其視頻資料。 前言 寫(xiě)文章是一個(gè)短期收益少,長(zhǎng)期收益很大的一件事情,人們總是高估短期收益,低估長(zhǎng)期收益。往往是很多人堅(jiān)持不下來(lái),特別是寫(xiě)文章的初期,剛寫(xiě)完文章沒(méi)有人閱讀會(huì)有一種挫敗感,影響了后期創(chuàng)作。 從某種意義上說(shuō),...

    NSFish 評(píng)論0 收藏0
  • 通俗易懂理解ES6 - ES6變量類型及Iterator

    摘要:迭代器在原有的數(shù)據(jù)結(jié)構(gòu)類型上新增了兩種類型,我們?cè)谑褂玫臅r(shí)候還可以通過(guò)自由組合的形式使用這些結(jié)構(gòu)類型達(dá)到自己想要的數(shù)據(jù)結(jié)構(gòu),這就需要一種統(tǒng)一的接口機(jī)制供我們調(diào)用處理不同的數(shù)據(jù)結(jié)構(gòu)。 引言 萬(wàn)丈高樓平地起,欲練此功,必先打好基本功: ) 在了解 ES6 新增的變量類型前,我們必須先知道 JavaScript 在ES6之前,有如下六種基本數(shù)據(jù)類型:Null、Undefined、Number...

    Keven 評(píng)論0 收藏0
  • 即將立秋《課多周刊》(第2期)

    摘要:即將立秋的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。課多周刊機(jī)器人運(yùn)營(yíng)中心是如何玩轉(zhuǎn)起來(lái)的分享課多周刊是如何運(yùn)營(yíng)并堅(jiān)持下來(lái)的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大...

    ruicbAndroid 評(píng)論0 收藏0
  • 即將立秋《課多周刊》(第2期)

    摘要:即將立秋的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。課多周刊機(jī)器人運(yùn)營(yíng)中心是如何玩轉(zhuǎn)起來(lái)的分享課多周刊是如何運(yùn)營(yíng)并堅(jiān)持下來(lái)的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大...

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

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

0條評(píng)論

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