下一篇:《你不知道的javascript》筆記_對象&原型
寫在前面上一篇博客我們知道詞法作用域是由變量書寫的位置決定的,那this又是在哪里確定的呢?如何能夠精準的判斷this的指向?這篇博客會逐條闡述
書中有這樣幾句話:
this是在運行時進行綁定的,并不是在編寫時綁定,它的上下文取決于函數(shù)調用時的各種條件
this的綁定和函數(shù)聲明的位置沒有任何關系,只取決于函數(shù)的調用方式當一個函數(shù)被調用時,會創(chuàng)建一個活動記錄(有時候也稱為執(zhí)行上下文)。這個記錄會包含函數(shù)在哪里被調用(調用棧)、函數(shù)的調用方法、傳入的參數(shù)等信息。this 就是記錄的其中一個屬性,會在函數(shù)執(zhí)行的過程中用到。
關于執(zhí)行上下文,可以參考《javascript高級程序設計》筆記:內(nèi)存與執(zhí)行環(huán)境
一、 綁定規(guī)則 1.1 默認綁定最常用的函數(shù)調用類型——獨立函數(shù)調用,使用的即為默認綁定規(guī)則,在非strict mode下,this指向全局對象
function foo1() { console.log(this.a); } var a = 10; foo1(); // 10 // 即使函數(shù)嵌套比較深 function foo2() { foo1(); } function foo3() { foo2(); } foo3();
當然,我們實際使用中,難以判別的并不是直接型的默認綁定模式,而是隱式綁定丟失型的默認綁定(下面會著重說明)
1.2 隱式綁定【重點】調用的位置是否有上下文對象,或者說被某個對象擁有或包含
// 基本形式 function foo() { console.log(this.a); } var obj = { a: 10, foo }; obj.foo(); // 10
隱式綁定中的幾個雷區(qū):
1. 多個對象嵌套引用時,只有最后一層在調用位置中起作用
function foo() { console.log(this.a); } var obj2 = { a: 42, foo }; var obj1 = { a: 10, obj2 }; obj1.obj2.foo(); // 42
2.【隱式丟失】當調用函數(shù)被重新賦值為新變量,調用新變量時this指向會有不同
// 共用部分 function foo(){ console.log(this.a); } var obj = { a: 10, foo }; var a = "opps, global"; // 直接賦值 var bar = obj.foo; bar(); // "oops, global" // 回調間接賦值1 function doFoo(fn) { fn(); } doFoo(obj.foo); // "oops, global" 相當于間接賦值 // 回調間接賦值2 setTimeout(obj.foo, 100); // "oops, global" 內(nèi)置的setTimeout也相當于間接賦值
經(jīng)典綜合案例:
var length = 10; function fn(){ console.log(this.length); } var obj = { length: 5, method: function (fn) { fn(); arguments[0](); } }; obj.method(fn, 123);
分析:fn()為函數(shù)fn的引用,默認綁定,指向全局;arguments[0]();相當于下面的引用,數(shù)據(jù)隱式綁定,綁定對象為arguments,其屬性length值為參數(shù)數(shù)量2
arguments: { "0": function fn(){ console.log(this.length); } }
答案:10 2
1.3 顯式綁定call()/apply()/bind()能夠顯式修改this指向
通過上述方法調用的方式為顯示綁定,它們第一個參數(shù)是一個對象,在調用函數(shù)時,綁定在this中。
關于三者的基本用法和說明在之前博客《javascript高級程序設計》函數(shù)調用模式 & this深度理解中已作說明,在此不做嘮述
兩點注意:
1. 通過顯式綁定的不能再修改它的this指向
function foo() { console.log(this.a); } var obj = { a: 2 }; var bar = function() { foo.call(obj); } bar(); // 2 setTimeout(bar, 200); // 2 bar.call(window); // 2
2. 將null/undefined作為第一個參數(shù)時,調用會忽略這些值,采用默認綁定規(guī)則
function foo() { console.log(this.a); } var a = 2; foo.call(null); // 21.4 new綁定
使用關鍵字new執(zhí)行函數(shù),當函數(shù)無返回值或返回值非對象時,this指向為實例對象
new關鍵字執(zhí)行函數(shù)流程:
創(chuàng)建一個全新的對象
這個新對象會被執(zhí)行[[prototype]]連接
這個新對象會綁定到函數(shù)調用的this上
如果函數(shù)沒有返回其他對象,所執(zhí)行函數(shù)會自動返回這個新的對象
須知:構造函數(shù)與普通函數(shù)無異,作為區(qū)分,我們一般講通過new調用的函數(shù)稱為構造函數(shù),并大寫第一個單詞。所有函數(shù)均可由關鍵字new調用
function foo(a) { this.a = a; } var bar = new foo(2); console.log(bar.a); // 2二、優(yōu)先級&判斷規(guī)則 2.1 優(yōu)先級
new綁定 --> 顯式綁定 --> 隱式綁定 --> 默認綁定
2.2. 判斷規(guī)則【重點】【new綁定】函數(shù)是否在new中調用?如果是,this綁定的是新創(chuàng)建的對象
【顯式綁定】函數(shù)是否在call/aplly/bind中調用?如果是,this綁定的是指定對象
【隱式綁定】函數(shù)是否在某個上下文中調用?如果是,this綁定到那個上下文對象
【默認綁定】如果都不是,this綁定嚴格模式下為undefined,非嚴格模式下為全局對象
三、箭頭函數(shù)中的thisES6中箭頭函數(shù)不使用上面this的四種標準規(guī)格,而是根據(jù)外層(函數(shù)或者全局)作用域來決定this指向
下面是一個普通函數(shù)和箭頭函數(shù)的對比:
function foo1() { setTimeout(() => { console.log(this.a) }, 100) } function foo2() { setTimeout(function() { console.log(this.a) }, 100) } var a = 10; var obj = { a: 2 }; foo1.call(obj); // 2 箭頭函數(shù)this指向外層(obj) foo2.call(obj); // 10 隱式丟失,默認綁定
【利用閉包】理解箭頭函數(shù)中的this:
// 上例中的箭頭函數(shù)相當于 function foo1() { var self = this; setTimeout(function() { console.log(self.a) }, 100) }
上一篇:《你不知道的javascript》筆記_作用域與閉包
下一篇:《你不知道的javascript》筆記_對象&原型
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/100381.html
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學習清單,發(fā)現(xiàn)僅有部分完成了。當然,這并不影響年是向上的一年在新的城市穩(wěn)定連續(xù)堅持健身三個月早睡早起游戲時間大大縮減,學會生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學習清單,發(fā)現(xiàn)僅有部分完成了。當然,這并不影響2018年是向上的一年:在新的城市穩(wěn)定、...
摘要:建筑的頂層代表全局作用域。實際的塊級作用域遠不止如此塊級作用域函數(shù)作用域早期盛行的立即執(zhí)行函數(shù)就是為了形成塊級作用域,不污染全局。這便是閉包的特點吧經(jīng)典面試題下面的代碼輸出內(nèi)容答案個如何處理能夠輸出閉包方式方式下一篇你不知道的筆記 下一篇:《你不知道的javascript》筆記_this 寫在前面 這一系列的筆記是在《javascript高級程序設計》讀書筆記系列的升華版本,旨在將零碎...
摘要:本書屬于基礎類書籍,會有比較多的基礎知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱不錯,下冊的知識點就這么少,非常不推介看下冊上中下三本的讀書筆記你不知道的上讀書筆記你不知道的中讀書筆記你不知道的下讀書筆記第三 本書屬于基礎類書籍,會有比較多的基礎知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱; 不錯,下冊的知識點就這么少,非...
摘要:但是如果非全局的變量如果被遮蔽了,無論如何都無法被訪問到。但是如果引擎在代碼中找到,就會完全不做任何優(yōu)化。結構的分句中具有塊級作用域。第四章提升編譯器函數(shù)聲明會被提升,而函數(shù)表達式不會被提升。 本書屬于基礎類書籍,會有比較多的基礎知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱; 上中下三本的讀書筆記: 《你不知道的JavaScript》 (上) 讀書筆記...
摘要:隱式綁定即綁定到最頂層或最近調用對象上顯式綁定即用或手動進行綁定方法實現(xiàn)綁定構造函數(shù)不存在其實在中不存在構造函數(shù),我們所說的構造函數(shù)其實就是普通的函數(shù),它只是用被構造調用而已。 JS是編譯型語言 編譯發(fā)生在代碼執(zhí)行前幾微秒,簡單來說就是js在執(zhí)行前要進行編譯,編譯過程發(fā)生在代碼執(zhí)行前幾微妙,甚至更短。 編譯的步驟 詞法分析以var a = 2 為例,詞法分析會將其分成三個有意義的代碼...
閱讀 2908·2021-11-24 09:39
閱讀 1720·2021-09-28 09:35
閱讀 1176·2021-09-06 15:02
閱讀 1444·2021-07-25 21:37
閱讀 2831·2019-08-30 15:53
閱讀 3709·2019-08-30 14:07
閱讀 764·2019-08-30 11:07
閱讀 3602·2019-08-29 18:36