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

資訊專欄INFORMATION COLUMN

前端進擊的巨人(六):知否知否,須知this

Andrman / 2004人閱讀

摘要:有關函數(shù)柯里化的詳解,請回閱前端進擊的巨人五學會函數(shù)柯里化。構造函數(shù)中的通過操作符可以實現(xiàn)對函數(shù)的構造調用。在了解構造函數(shù)中的前,有必要先了解下實例化對象的過程。

常見this的誤解

指向函數(shù)自身(源于this英文意思的誤解)

指向函數(shù)的詞法作用域(部分情況)

this的應用環(huán)境 1. 全局環(huán)境

無論是否在嚴格模式下,全局執(zhí)行環(huán)境中(任何函數(shù)體外部)this都指向全局對象

var name = "以樂之名";
this.name;  // 以樂之名
2. 函數(shù)(運行內)環(huán)境

函數(shù)內部,this的值取決于函數(shù)被調用的方式(被誰調用)

var name = "無名氏";
function getName() {
 console.log(this.name);
}
getName();         // 無名氏 調用者是全局對象

var myInfo = {
  name: "以樂之名",
  getName: getName
};
myInfo.getName();  // 以樂之名 調用者是myInfo對象
this的正解

"this的指向是在運行時進行綁定的,而不是代碼書寫(函數(shù)聲明)時確定?。?!"

"看誰用",this的指向取決于調用者,這也是很多文章提到過的觀點。"誰調用,this指向誰",只是這句話稍有偏頗,某些情況不見得都適用。

生活栗子:你的錢并不一定是你的錢,只有當你使用消費了才是你的錢 。
"看誰用"),借出去的錢就不是你的了。。。

回到正文,我們先通過棧,來理解什么是調用位置?

JavaScript中函數(shù)的調用是以棧的方式來存儲,棧頂是正在運行的函數(shù),函數(shù)調用時入棧,執(zhí)行完成后出棧。

function foo() {
  // 此時的棧:全局 -> foo,調用位置在foo
  bar();
}

function bar() {
  // 此時的棧:全局 -> foo -> bar,調用位置在bar
  baz();
}

function baz() {
  // 此時的棧:全局 -> foo -> bar -> baz,調用位置在baz
  // ...
}

foo();

代碼中雖然函數(shù)存在多層嵌套使用,但處于棧頂?shù)闹挥姓趫?zhí)行的函數(shù),也即調用者只有頂層的那一個(或最后一個),理清調用位置(調用者)有助于我們理解this

this的綁定規(guī)則

默認綁定(函數(shù)多帶帶調用)

隱式綁定(作為對象的屬性方法調用,帶有執(zhí)行上下文)

顯示綁定(call/apply/bind

new綁定(new創(chuàng)建實例)

箭頭函數(shù)綁定(ES6新增,基于詞法作用域)

默認綁定下(函數(shù)多帶帶調用)區(qū)分嚴格模式

非嚴格模式,this會指向全局對象(瀏覽器全局對象是window,NodeJS全局對象是global);

嚴格模式,this指向undefined

// 非嚴格模式
function getName() {
  console.log(this.name);  // this指向全局對象
}
getName();  // "",并不會報錯,如果外部有全局變量name,則會輸出對應值

// 嚴格模式
function getName() {
  "use strict"
 console.log(this.name);   // this指向undefined
}
getName();  // TypeError: Cannot read property "name" of undefined

TIPS: 嚴格模式中,對函數(shù)中this的影響,只在函數(shù)內聲明了嚴格模式才會存在,如果是調用時聲明嚴格模式則不會影響。

function getName() {
  console.log(this.name);
}

// 調用時聲明嚴格模式
"use strict";
getName();  // ""
隱式綁定

隱式綁定中,函數(shù)一般作為對象的屬性調用,帶有調用者的執(zhí)行上下文。因此this值取決于調用者的上下文環(huán)境。如果存在多層級屬性引用,只有對象屬性引用鏈中最頂層(最后一層)會影響調用位置,而this的值取決于調用位置。文章開頭以棧來理解調用者的例子。

function getName() {
  return this.name;
}

var myInfo = {
  name: "以樂之名",
  getName: getName
};

var leader = {
  name: "大神組長"
  man: myInfo
};
leader.man.getName();  // "以樂之名"
// man 指向 myInfo,最頂層(最后一層)對象為 myInfo
apply/call的區(qū)別

apply/call方法兩者類似,都可以顯示綁定this,兩者的區(qū)別是參數(shù)傳遞的方式不同。apply/call第一個參數(shù)都為要指定this的對象,不同的是apply第二個參數(shù)接受的是一個參數(shù)數(shù)組,而call從第二個參數(shù)開始接受的是參數(shù)列表。

apply語法:func.apply(thisArg, [argsArray])

call語法:func.call(thisArg, arg1, arg2, ...)

var numbers = [5, 6, 2, 3, 7];

// 求numbers的最大值

// apply
var max = Math.max.apply(null, numbers);

// call
var max = Math.max.call(null, ...numbers); // ...展開運算符

TIPS: 如果thisArg為原始值(數(shù)字,字符串,布爾值),this會指向該原始值的自動包裝對象,如Number, String, Boolean

func.apply(1);
// func中的this -> Number對象;
bind的特別(柯里化的應用)

bind是ES5新增的方法,跟apply/call功能一樣,可以顯示綁定this。

bind語法:function.bind(thisArg[, arg1[, arg2[, ...]]])

bind()方法創(chuàng)建一個新的函數(shù),在調用時設置this關鍵字為提供的值,并在調用新函數(shù)時,將給定參數(shù)列表作為原函數(shù)的參數(shù)序列的前若干項。

-- 《Function.prototype.bind() | MDN》

"bind與apply/call的區(qū)別:apply/call傳入this并立即執(zhí)行函數(shù),而bind傳入this則返回一個函數(shù),并不會立即執(zhí)行,只有調用返回的函數(shù)才會執(zhí)行原始函數(shù)"。

bind方法是函數(shù)柯里化的一種應用,看過上篇《前端進擊的巨人(五):學會函數(shù)柯里化(curry) 》的小伙伴,應該還記得"函數(shù)柯里化的特點:延遲執(zhí)行,部分傳參,返回一個可處理剩余參數(shù)的函數(shù)"

bind相較apply/call的優(yōu)點,可以通過部分傳參提前對this進行一次"永久綁定",也就是說this只需綁定一次,省卻每次執(zhí)行都要進行this綁定的操作。

function getName() {
  return this.name;
}

var myInfo = {
  name: "以樂之名",
  job: "前端工程師"
};

var getName = getName.bind(myInfo);
getName();  // "以樂之名";
getName(); //  "以樂之名";

// 一次性綁定,之后調用無需再修改this

TIPS: 函數(shù)柯里化可以用于參數(shù)預設,像一次性操作(判斷/綁定)等。

有關函數(shù)柯里化的詳解,請回閱:《前端進擊的巨人(五):學會函數(shù)柯里化(curry) 》。

構造函數(shù)中的this

通過new操作符可以實現(xiàn)對函數(shù)的構造調用。JavaScript中本身并沒有"構造函數(shù)",一個函數(shù)如果沒有使用new操作符調用,那么它就是個普通函數(shù),new Func()實際上是對函數(shù)Func的"構造調用"。

在了解構造函數(shù)中的this前,有必要先了解下new實例化對象的過程。

new實例過程

創(chuàng)建(構造)一個全新的空對象

這個新對象會被執(zhí)行"原型"鏈接(新對象的__proto__會指向函數(shù)的prototype)

構造函數(shù)的this會指向這個新對象,并對this屬性進行賦值

如果函數(shù)沒有返回其他對象,則返回這個新對象(注意構造函數(shù)的return,一般不會有return)

// 正常不帶return的構造函數(shù)
function People(name, sex) {
  this.name = name;
  this.sex = sex;
}

var man = new People("亞當", "男");
var woman = new People("夏娃", "女");
// 實例化對象成功
// 構造函數(shù)帶了return
function People(name, sex) {
  return 1;  // 返回的是Number對象
}
function People(name, sex) {
  return "hello world";  // 返回的是String對象
}
function People(name, sex) {
  return function() {}
}
function People(name, sex) {
  return {};
}
// 以上并未正確實例化對象

構造函數(shù)自定義return,會造成new無法完成正確的實例化操作。如果返回值為基本類型,則返回其包裝對象Number/String/Bollean。

TIPS: 原型鏈中的this指向其實例化的對象

People.prototype.say = function() {
  console.log(`我的名字:${this.name}`);
};

var man = new People("亞當", "男");
man.say();  // 我的名字:亞當
this綁定規(guī)則的優(yōu)先級

顯示綁定 / new綁定 > 隱式綁定 > 默認綁定

TIPS: new無法跟apply/call同時使用

this判定步驟

函數(shù)被new操作符使用(new綁定)? YES --> this綁定的是new創(chuàng)建的新對象

函數(shù)通過call/apply/bind(顯示綁定)? YES --> this綁定的是指定的對象

函數(shù)在某個上下文對象中調用(隱式綁定)? YES --> this綁定的是那個上下文對象

默認綁定,嚴格模式指向undefined,否則指向全局對象

ES6的箭頭函數(shù)(詞法作用域的this機制,規(guī)則之外)

箭頭函數(shù)的this機制不同于傳統(tǒng)的this機制,它采取的是另外一種機制,詞法作用域的this判定規(guī)則。

// 例子一
var name = "無名氏";
var myInfo = {
  name: "以樂之名",
  getName: () => {
    console.log(this.name);
  }
};
var getName = myInfo.getName;
window.getName();     // 無名氏
myInfo.getName();     // 無名氏
// myInfo是在全局環(huán)境定義的,因此根據(jù)詞法作用域,this指向全局對象

// 例子二
var name = "無名氏";
var myInfo = {
  name: "以樂之名",
  say: () => {
    setTimeout(() => {
      console.log(this.name);
    })
  }
};
myInfo.say();  // 無名氏
// 箭頭函數(shù)通過作用域鏈來逐層查找this,最終找到全局變量myInfo,this指向全局對象

// 例子三
var name = "無名氏";
var myInfo = {
  name: "以樂之名",
  say: function() {
    setTimeout(() => {
      console.log(this.name);
    })
  }
};
myInfo.say(); // 以樂之名
// 箭頭函數(shù)找到say: function(){},因此this的作用域來自myInfo

TIPS: setTimeout/setInterval/alert的調用者都是全局對象

"箭頭函數(shù)的this始終指向函數(shù)定義時的this,而非執(zhí)行(調用)時的this。箭頭函數(shù)中的this必須通過作用域鏈一層一層向外查找,來確定this指向。"

擴展:箭頭函數(shù)的書寫規(guī)則
1. 箭頭函數(shù)只能用函數(shù)表達式,不能用函數(shù)聲明式寫法(不包括匿名函數(shù))
// 函數(shù)表達式
const getName = (name) => { return "myName: " + name };

// 匿名函數(shù)
setTimeout((name) => {
  console.log(name);
}, 1000)
2. 如果參數(shù)只有一個,可不加括號();如果沒有參數(shù)或多個參數(shù)需加括號()
// 只有一個參數(shù)
const getName = name => {
  return `myName: ${name}`;
}

// 無參數(shù)
const getName = () => {
  return "myName: "以樂之名"";
}

// 多參數(shù)
const getName = (firstName, lastName) => {
  return `myName: ${firstName} ${lastName}`;
}
3. 函數(shù)體只有一個可不加花括號{}
const getName = name => return `myName: ${name}`;
4. 函數(shù)體沒有花括號{},可不寫return,會自動返回
const getName = name => `myName: ${name}`;

參考文檔:

你不知道的JavaScript(上卷)

徹底理解js中this的指向,不必硬背。

this|MDN

本文首發(fā)Github,期待Star!
https://github.com/ZengLingYong/blog

作者:以樂之名
本文原創(chuàng),有不當?shù)牡胤綒g迎指出。轉載請指明出處。

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

轉載請注明本文地址:http://systransis.cn/yun/108949.html

相關文章

  • 數(shù)據(jù)結構否知否系列之 — 隊列篇

    摘要:初始化隊列初始化一個存儲隊列中元素的數(shù)據(jù)結構,如果未傳入默認賦值空數(shù)組,傳入需先校驗類型是否正確。頭等艙和商務艙乘客的優(yōu)先級要高于經(jīng)濟艙乘客。在有些國家,老年人和孕婦或帶小孩的婦女登機時也享有高于其他乘客的優(yōu)先級。 有一天,當回顧自己走過的路時,你會發(fā)現(xiàn)這些奮斗不息的歲月,才是最美好的人生?!ヂ逡恋?隊列,英文 First In First Out 簡稱 FIFO,遵從先進先出的原...

    galois 評論0 收藏0
  • 超融合后勁兒,SmartX韌勁兒

    摘要:超融合的持續(xù)演進與企業(yè)數(shù)字化轉型的步調是一致的,這也是超融合受到業(yè)界追捧的原因。對于超融合市場的每一個參與者來說,目前最重要的任務是如何快速有效地獲客。而這也正是超融合市場走向縱深所需的后勁兒,也是持續(xù)發(fā)展所需要的韌勁兒。超融合(HCI)市場可以一直火熱,但超融合應用的落地最好理智而冷靜。最熱時,據(jù)說中國市場有上百家超融合供應商。隨著超融合應用逐步落地,在市場和用戶需求的雙重考驗下,有人離開...

    DangoSky 評論0 收藏0
  • 【Copy攻城獅日志】Node.js之http下載圖片失敗

    摘要:當用戶或搜索引擎向網(wǎng)站服務器發(fā)出瀏覽請求時,服務器返回的數(shù)據(jù)流中頭信息中的狀態(tài)碼的一種,表示本網(wǎng)頁永久性轉移到另一個地址。通過在源代碼中添加日志輸出,我們也能清楚地看到的狀態(tài)碼。 Created 2019-4-5 22:24:33 by huqi Updated 2019-4-5 23:23:56 by huqi showImg(https://segmentfault.com/...

    darkbaby123 評論0 收藏0
  • 前端進擊巨人(八):淺談函數(shù)防抖與節(jié)流

    摘要:隆重請出主角防抖與節(jié)流。防抖與節(jié)流的異同相同都是防止某一時間段內,函數(shù)被頻繁調用執(zhí)行,通過時間頻率控制,減少回調函數(shù)執(zhí)行次數(shù),來實現(xiàn)相關性能優(yōu)化。參考文章分鐘理解的節(jié)流防抖及使用場景函數(shù)防抖和節(jié)流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇課題,或許早已是爛大街的解讀文章。不過春招系列面試下來,不少伙伴們還...

    _Zhao 評論0 收藏0

發(fā)表評論

0條評論

Andrman

|高級講師

TA的文章

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