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

資訊專欄INFORMATION COLUMN

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

enda / 3501人閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

下面看下例子。

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

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

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

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

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

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

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

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

這個網(wǎng)上貌似很少提及,隱式丟失,通俗來講就是“變low”了!
原本應(yīng)用隱式綁定的,因為丟失綁定對象,變回應(yīng)用默認綁定了!把this綁定到全局對象或undefined。

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

到底在說什么,看個例子。

 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ù)本身,此時的b()是一個不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認綁定。

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

 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"

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

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

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

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

看下面例子。

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

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

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

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

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

 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()這個函數(shù),但在其內(nèi)部手動調(diào)用了 obj.foo.call(obj),
把foo()強制綁定到了obj對象,之后無論如何調(diào)用doFoo(),它總會手動在obj上調(diào)用foo。

對于硬綁定,ES5提供了一個內(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í)行,我的天!啥也沒有????
這就對了,這是bind的“效果”,也是和apply、call的主要區(qū)別——延遲調(diào)用。
也就是說bind其實只是函數(shù)的引用,要想執(zhí)行需要進行回調(diào),即fn.bing(obj)(),
此時就能輸出5了。

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

 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的特點,函數(shù)在回調(diào)時執(zhí)行,把bind改成call,最后3行代碼變成

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

結(jié)果報錯了,對,因為call和apply都是綁定后立刻執(zhí)行的,都執(zhí)行完了,bar就只是一個沒有賦值的變量而已。

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

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

什么是構(gòu)造函數(shù),一個函數(shù)被new調(diào)用時,該函數(shù)就是構(gòu)造函數(shù)。
(變身前:普通函數(shù);使用地攤貨new變身器,變身后:構(gòu)造函數(shù))

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

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

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

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

最后總結(jié)

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

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

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

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

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

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

相關(guān)文章

  • 寫技術(shù)博客那點事

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

    ddongjian0000 評論0 收藏0
  • 寫技術(shù)博客那點事

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

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

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

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

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

    MRZYD 評論0 收藏0

發(fā)表評論

0條評論

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