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

資訊專欄INFORMATION COLUMN

筆記-你不知道的JS-this

leanote / 2217人閱讀

摘要:綁定使用來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時,會自動執(zhí)行下面的操作。

1 this的概念

this 在任何情況下都不指向函數(shù)的詞法作用域。作用域“對象”無法通過 JavaScript代碼訪問,它存在于 JavaScript 引擎內(nèi)部。

this 是在運(yùn)行時進(jìn)行綁定的,并不是在編寫時綁定,它的上下文取決于函數(shù)調(diào)用時的各種條件。this 的綁定和函數(shù)聲明的位置沒有任何關(guān)系,只取決于函數(shù)的調(diào)用方式。

當(dāng)一個函數(shù)被調(diào)用時,會創(chuàng)建一個活動記錄(有時候也稱為執(zhí)行上下文)。這個記錄會包含函數(shù)在哪里被調(diào)用(調(diào)用棧)、函數(shù)的調(diào)用方法、傳入的參數(shù)等信息。this 就是記錄的其中一個屬性,會在函數(shù)執(zhí)行的過程中用到。

2 this的綁定

函數(shù)的執(zhí)行過程中調(diào)用位置如何決定 this 的綁定對象,綁定規(guī)則:

1 默認(rèn)綁定

function foo(){
  console.log(a);
}
var a=2;
foo();

foo() 是直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的,因此只能使用默認(rèn)綁定,無法應(yīng)用其他規(guī)則。如果使用嚴(yán)格模式(strict mode),那么全局對象將無法使用默認(rèn)綁定,因此 this 會綁定
到 undefined。

2 隱式綁定
調(diào)用位置是否有上下文對象,或者說是否被某個對象擁有或者包含。當(dāng) foo() 被調(diào)用時,它的落腳點(diǎn)確實(shí)指向 obj 對象。當(dāng)函數(shù)引用有上下文對象時,隱式綁定規(guī)則會把函數(shù)調(diào)用中的 this 綁定到這個上下文對象。因為調(diào)用 foo() 時 this 被綁定到 obj,因此 this.a 和 obj.a 是一樣的。對象屬性引用鏈中只有最頂層或者說最后一層會影響調(diào)用位置。

function fooo(){
  conosle.log(this.a);
}
var obj={
  a:2,
  foo:foo
};
var obj2={
  a:22,
  obj: obj
}
obj.foo();  // 2
obj2.obj.foo();  // 2

隱式丟失
雖然 bar 是 obj.foo 的一個引用,但是實(shí)際上,它引用的是 foo 函數(shù)本身,因此此時的bar() 其實(shí)是一個不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認(rèn)綁定。

當(dāng)函數(shù)被作為參數(shù)傳遞時(如:回調(diào)函數(shù)),會丟失this,因為參數(shù)傳遞其實(shí)就是一種隱式賦值

function foo() { 
  console.log( this.a );
}
var obj = { 
  a: 2,
  foo: foo
};
var bar = obj.foo; // 函數(shù)別名!
var a = "oops, global"; // a 是全局對象的屬性 
bar(); // "oops, global"

3 顯式綁定
JavaScript 提供的絕大多數(shù)函數(shù)以及你自己創(chuàng)建的所有函數(shù)都可以使用 call(..) 和 apply(..) 方法。這兩個方法是如何工作的呢?它們的第一個參數(shù)是一個對象,它們會把這個對象綁定到this,接著在調(diào)用函數(shù)時指定這個 this。因為你可以直接指定 this 的綁定對象,因此我們稱之為顯式綁定。

function foo(){
  console.log(this.a);
}
var obj={a:2};
foo.call(obj);  // 2

如果你傳入了一個原始值(字符串類型、布爾類型或者數(shù)字類型)來當(dāng)作 this 的綁定對象,這個原始值會被轉(zhuǎn)換成它的對象形式(也就是new String(..)、new Boolean(..)或者new Number(..))。這通常被稱為“裝箱”。

4 new 綁定
使用 new 來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時,會自動執(zhí)行下面的操作。

創(chuàng)建(或者說構(gòu)造)一個全新的對象。

這個新對象會被執(zhí)行[[原型]]連接。

這個新對象會綁定到函數(shù)調(diào)用的this。

如果函數(shù)沒有返回其他對象,那么new表達(dá)式中的函數(shù)調(diào)用會自動返回這個新對象。

function foo(a) { 
  this.a = a;
}
var bar = new foo(2); 
console.log( bar.a ); // 2

使用 new 來調(diào)用 foo(..) 時,我們會構(gòu)造一個新對象并把它綁定到 foo(..) 調(diào)用中的 this上。new 是最后一種可以影響函數(shù)調(diào)用時 this 綁定行為的方法,我們稱之為 new 綁定。

3 判斷this綁定

?
注意:如果你把 null 或者 undefined 作為 this 的綁定對象傳入 call、apply 或者 bind,這些值在調(diào)用時會被忽略,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則。

那么什么情況下你會傳入 null 呢?一種非常常見的做法是使用 apply(..) 來“展開”一個數(shù)組,并當(dāng)作參數(shù)傳入一個函數(shù)。類似地,bind(..) 可以對參數(shù)進(jìn)行柯里化(預(yù)先設(shè)置一些參數(shù)),這種方法有時非常有用:

function foo(a,b) {
console.log( "a:" + a + ", b:" + b );
}
// 把數(shù)組“展開”成參數(shù)
foo.apply( null, [2, 3] ); // a:2, b:3
// 使用 bind(..) 進(jìn)行柯里化
var bar = foo.bind( null, 2 ); 
bar( 3 ); // a:2, b:3

軟綁定會對指定的函數(shù)進(jìn)行封裝,首先檢查調(diào)用時的 this,如果 this 綁定到全局對象或者 undefined,那就把指定的默認(rèn)對象 obj 綁定到 this,否則不會修改 this。

if (!Function.prototype.softBind) { 
  Function.prototype.softBind = function(obj) {
    var fn = this;
    // 捕獲所有 curried 參數(shù)
    var curried = [].slice.call( arguments, 1 ); var bound = function() {
      return fn.apply(
      (!this || this === (window || global)) ?
        obj : this
        curried.concat.apply( curried, arguments )
      ); 
    };
    bound.prototype = Object.create( fn.prototype );
    return bound; };
}
4 箭頭函數(shù)

箭頭函數(shù)并不是使用 function 關(guān)鍵字定義的,而是使用被稱為“胖箭頭”的操作符 => 定義的。箭頭函數(shù)不使用 this 的四種標(biāo)準(zhǔn)規(guī)則,而是根據(jù)外層(函數(shù)或者全局)作用域來決定 this。

function foo() {
// 返回一個箭頭函數(shù) 
  return (a) => {
//this 繼承自 foo()
  console.log( this.a ); };
}
var obj1 = { a:2};
var obj2 = { a:3};
var bar = foo.call( obj1 );
bar.call( obj2 ); // 2, 不是 3 !

foo() 內(nèi)部創(chuàng)建的箭頭函數(shù)會捕獲調(diào)用時 foo() 的 this。由于 foo() 的 this 綁定到 obj1,bar(引用箭頭函數(shù))的 this 也會綁定到 obj1,箭頭函數(shù)的綁定無法被修改。(new 也不行!)

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

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

相關(guān)文章

  • 你不知道javascript》筆記_this

    下一篇:《你不知道的javascript》筆記_對象&原型 寫在前面 上一篇博客我們知道詞法作用域是由變量書寫的位置決定的,那this又是在哪里確定的呢?如何能夠精準(zhǔn)的判斷this的指向?這篇博客會逐條闡述 書中有這樣幾句話: this是在運(yùn)行時進(jìn)行綁定的,并不是在編寫時綁定,它的上下文取決于函數(shù)調(diào)用時的各種條件this的綁定和函數(shù)聲明的位置沒有任何關(guān)系,只取決于函數(shù)的調(diào)用方式當(dāng)一個函數(shù)被調(diào)用時...

    cpupro 評論0 收藏0
  • 你不知道JavaScript》 (下) 閱讀摘要

    摘要:本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點(diǎn),不會全記,供大家和自己翻閱不錯,下冊的知識點(diǎn)就這么少,非常不推介看下冊上中下三本的讀書筆記你不知道的上讀書筆記你不知道的中讀書筆記你不知道的下讀書筆記第三 本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點(diǎn),不會全記,供大家和自己翻閱; 不錯,下冊的知識點(diǎn)就這么少,非...

    Jacendfeng 評論0 收藏0
  • 你不知道JS》讀書筆記---作用域及閉包

    摘要:注此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀你不知道的后的理解。作用域及閉包基礎(chǔ),代碼運(yùn)行的幕后工作者引擎及編譯器。 注:此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀《你不知道的JS》后的理解。 作用域及閉包基礎(chǔ),JS代碼運(yùn)行的幕后工作者:引擎及編譯器。引擎負(fù)責(zé)JS程序的編譯及執(zhí)行,編譯器負(fù)責(zé)詞法分析和代碼生成。那么作用域就像一個容器,引擎及編譯器都從這里提取東西。 ...

    denson 評論0 收藏0
  • 【讀書筆記你不知道JavaScript--內(nèi)置類型

    摘要:有種內(nèi)置類型,分別是除對象之外,其他統(tǒng)稱為基本類型。另一個需要注意的是數(shù)組確切地說,數(shù)組也是的一個子類型我們可以通過下面的方法檢查變量是不是數(shù)組處理未聲明的變量時,會返回這是因為有一個特殊的安全防范機(jī)制。 js有7種內(nèi)置類型,分別是undefined null boolean string number symbol object除對象之 Object 外,其他統(tǒng)稱為基本類型。符號 ...

    Integ 評論0 收藏0
  • 你不知道JS》讀書筆記之閉包在循環(huán)中應(yīng)用

    摘要:閉包在循環(huán)中的應(yīng)用延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行事實(shí)上,當(dāng)定時器運(yùn)行時即使沒給迭代中執(zhí)行的是多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個出來。 閉包在循環(huán)中的應(yīng)用 延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行;事實(shí)上,當(dāng)定時器運(yùn)行時即使沒給迭代中執(zhí)行的是 setTime(..., 0),多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個6出來。 for(var...

    weapon 評論0 收藏0

發(fā)表評論

0條評論

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