摘要:隱式綁定即綁定到最頂層或最近調(diào)用對象上顯式綁定即用或手動進行綁定方法實現(xiàn)綁定構(gòu)造函數(shù)不存在其實在中不存在構(gòu)造函數(shù),我們所說的構(gòu)造函數(shù)其實就是普通的函數(shù),它只是用被構(gòu)造調(diào)用而已。
JS是編譯型語言
編譯發(fā)生在代碼執(zhí)行前幾微秒,簡單來說就是js在執(zhí)行前要進行編譯,編譯過程發(fā)生在代碼執(zhí)行前幾微妙,甚至更短。
編譯的步驟詞法分析
以var a = 2 為例,詞法分析會將其分成三個有意義的代碼塊即詞法單元。
語法分析
將詞法單元組合生成代表了程序語法的結(jié)構(gòu)的樹,即抽象語法書(AST)。
代碼生成
將AST生成可執(zhí)行的代碼。即將AST轉(zhuǎn)化成一組機器指令。???
如果查找的目的是對變量進行賦值,那么就會使用 LHS 查詢;如果目的是獲取變量的值,就會使用 RHS 查詢。
詞法作用域決定于你在寫代碼時的塊級作用域
優(yōu)化依賴于詞法的靜態(tài)分析
eval with 會創(chuàng)建新的作用域在詞法分析階段,無法知道eval with會對作用域做怎樣的修改,此時引擎不再對作用域進行任何優(yōu)化
函數(shù)作用域 函數(shù)聲明 函數(shù)表達式區(qū)分函數(shù)聲明和表達式最簡單的方法是看 function 關(guān)鍵字出現(xiàn)在聲明中的位
置(不僅僅是一行代碼,而是整個聲明中的位置)。如果 function 是聲明中
的第一個詞,那么就是一個函數(shù)聲明,否則就是一個函數(shù)表達式。
隱式的生成塊級作用域
不存在變量提升
提升 原因變量(包括函數(shù)在內(nèi))的所有聲明都會優(yōu)先執(zhí)行,只有聲明本身會提升,而賦值或其他運行邏輯會留在原位置
過程這意味著無論作用域中的聲明出現(xiàn)在什么地方,都將在代碼本身被執(zhí)行前首先進行處理。
可以將這個過程形象地想象成所有的聲明(變量和函數(shù))都會被“移動”到各自作用域的
最頂端,這個過程被稱為提升。
聲明本身會被提升,而包括函數(shù)表達式的賦值在內(nèi)的賦值操作并不會提升。
當函數(shù)能夠記住或訪問所在的詞法作用域,及時是被作用域外調(diào)用,就產(chǎn)生了閉包
模塊現(xiàn)代模塊機制
未來的模塊機制
關(guān)于this 綁定時間點是在函數(shù)運行時綁定的,而非定義時。它的上下文取決于函數(shù)調(diào)用時的各種條件,和在哪里定義的沒有關(guān)系,只取決于函數(shù)的調(diào)用方式。
綁定過程當函數(shù)被調(diào)用時,會創(chuàng)建一個執(zhí)行上下文,在這個上下文里包含了函數(shù)在哪里沒調(diào)用(調(diào)用棧),調(diào)用函數(shù)的方法,參數(shù)等。this作為執(zhí)行上下文的一個屬性,可以在函數(shù)執(zhí)行的過程中用到。
綁定類型
默認綁定
即綁定到全局,嚴格模式下回綁定到undefined。
function foo() { console.log( this.a ); } var a = 2; (function(){ "use strict"; foo(); // 2 })()
隱式綁定
即綁定到最頂層(或最近調(diào)用對象)上
function fun() { console.log(this.a) } var obj2 = { a: 3, fun: fun, } var obj1 = { a: 2, obj2: obj2, } obj1.obj2.fun() // 3
顯式綁定
即用call或apply手動進行綁定
bind方法實現(xiàn)
new綁定(構(gòu)造函數(shù))
不存在
其實在js中不存在構(gòu)造函數(shù),我們所說的構(gòu)造函數(shù)其實就是普通的函數(shù),它只是用new被“構(gòu)造調(diào)用”而已。
new發(fā)生了什么?
創(chuàng)建(或者說構(gòu)造)一個全新的對象。
這個新對象會被執(zhí)行[[原型]]連接。
這個新對象會綁定到函數(shù)調(diào)用的this。
如果函數(shù)沒有返回其他對象,那么new表達式中的函數(shù)調(diào)用會自動返回這個新對象。
箭頭函數(shù) =>
對象 內(nèi)置對象基本類型在需要的時候(比如說獲取長度),會被引擎默認轉(zhuǎn)成內(nèi)置對象,從而進行方法的調(diào)用。
基礎(chǔ)類型并不是繼承自內(nèi)置對象?
var strPrimitive = "I am a string"; typeof strPrimitive; // "string" strPrimitive instanceof String; // false var strObject = new String( "I am a string" ); typeof strObject; // "object" strObject instanceof String; // true Object.prototype.toString.call( strObject ); // [object String]null
typeof null === Object;
原理是這樣的,不同的對象在底層都表示為二進制,在 JavaScript 中二進制前三位都為 0 的話會被判
斷為 object 類型,null 的二進制表示是全 0,自然前三位也是 0,所以執(zhí)行 typeof 時會返回“object”
淺拷貝
Object.assign({}, obj)
深拷貝
JSON.stringify
getOwnPropertyDescriptor(myObj, "a") defineProperty Object.defineProperty(myObj, "a", { value: 2, ?writable: true, configurable: true, enumerable: true ?})Getter 、Setter
var obj = { get a() { return this._a_ }, set a(val) { this._a_ = val * 5 } } obj.a = 10 console.log(obj.a) // 50 ? var obj2 = {} Object.defineProperty(obj2, "a", { get: function() { return this._a_ }, set: function(val) { this._a_ = val * 2 } }) obj2.a = 15 console.log(obj2.a) // 30存在性
in
"a" in obj1 會檢查obj及其原型鏈上是否有"a"
hasOwnProperty
不會檢查原型鏈,如果需要可以O(shè)bject.prototype.hasOwnProperty.call(myObj, "a")
返回實例對象O的構(gòu)造函數(shù)(的引用)。任何一個prototype對象都有一個constructor屬性,指向它的構(gòu)造函數(shù),每一個實例也有一個constructor屬性,默認調(diào)用prototype對象的constructor屬性?
例如
function Test() { this.name = "test" } var test = new Test() console.log(test.constructor === Test) // true類constructor
構(gòu)造函數(shù) constructor 是用于創(chuàng)建和初始化類中創(chuàng)建的一個對象的一種特殊方法.
class Polygon { constructor() { this.name = "Polygon"; } } class Square extends Polygon { constructor() { super(); } } class Rectangle {} Object.setPrototypeOf(Square.prototype, Rectangle.prototype); console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true let newInstance = new Square(); console.log(newInstance.name); //Polygon?proto
實例對象__proto__指向生成改對象的構(gòu)造函數(shù)的原型
例如
|function Test() { this.name = "test" } Test.prototype = { color: "red" } var test = new Test() console.log(test.__proto__ === Test.prototype) // true console.log(test.__proto__)Object.create
var foo = { something: function() { console.log( "Tell me something good..." ); } }; var bar = Object.create( foo ); bar.something(); // Tell me something good... Object.create(..) 會創(chuàng)建一個新對象(bar)并把它關(guān)聯(lián)到我們指定的對象(foo)
這樣 我們就可以充分發(fā)揮 [[Prototype]]
機制的威力(委托)并且避免不必要的麻煩
(比如使 用 new 的構(gòu)造函數(shù)調(diào)用會生成 .prototype 和 .constructor 引用)。
?
缺點
實例的屬性都會指向同一個引用
實現(xiàn)
function Parent() { this.names = [1, 2, 3] } function Child() { } Child.prototype = new Parent() var child1 = new Child() var child2 = new Child() child1.names.push(4) console.log(child1.names) // [1,2, 3,4] console.log(child2.names) // [1,2, 3,4]借用構(gòu)造函數(shù)
實現(xiàn)
function Parent() { this.names = [1, 2, 3] this.getName = function () { console.log(this.name) } } function Child() { Parent.call(this) } var child1 = new Child() var child2 = new Child() child1.names.push(4) console.log(child1.names) console.log(child2.names)
缺點
每個子實例都會實例化方法一次,內(nèi)存爆炸
實現(xiàn)
function Parent() { this.names = [1, 2, 3] } Parent.prototype.getName = function () { console.log(this.names) } function Child() { Parent.call(this) } Child.prototype = new Parent() var child1 = new Child() var child2 = new Child() child1.names.push(4) child1.getName() child2.getName()
缺點
子類實例上有一份父類的屬性,二者重復造成內(nèi)存浪費
父類的構(gòu)造函數(shù)被調(diào)用了兩次?
寄生式組合繼承實現(xiàn)
function Parent() { this.names = [1, 2, 3] } Parent.prototype.getName = function () { console.log(this.names) } function Child() { Parent.call(this) } Child.prototype = Object.create(Parent.prototype) var child1 = new Child() var child2 = new Child() child1.names.push(4) child1.getName() child2.getName()
優(yōu)點
屬性不會再原型鏈上重復
js中的繼承其實就是在對象間建立關(guān)聯(lián)關(guān)系,而行為委托就是建立這種關(guān)聯(lián)關(guān)系的紐帶。
("原型")面向?qū)ο箫L格function Foo(who) { this.me = who; } Foo.prototype.identify = function () { return "I am" + this.me; }; function Bar(who) { Foo.call(this,who); } Bar.prototype = Object.create(Foo.prototype); Bar.prototype.speak = function () { alert("Hello," + this.identify() + "."); }; var b1 = new Bar("b1"); var b2 = new Bar("b2"); b1.speak(); b2.speak();對象關(guān)聯(lián)風格
Foo = { init:function (who) { this.me = who; }, identify:function () { return "I am" + this.name } }; Bar = Object.create(Foo); Bar.speak = function () { alert("hello," + this.identify() + "."); }; var b3 = Object.create(Bar); b3.init("b3"); var b4 = Object.create(Bar); b4.init("b4"); b1.speak(); b2.speak();
?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/97508.html
摘要:注此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀你不知道的后的理解。作用域及閉包基礎(chǔ),代碼運行的幕后工作者引擎及編譯器。 注:此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀《你不知道的JS》后的理解。 作用域及閉包基礎(chǔ),JS代碼運行的幕后工作者:引擎及編譯器。引擎負責JS程序的編譯及執(zhí)行,編譯器負責詞法分析和代碼生成。那么作用域就像一個容器,引擎及編譯器都從這里提取東西。 ...
摘要:異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個回調(diào)再放入事件循環(huán)隊列中。 基礎(chǔ):瀏覽器 -- 多進程,每個tab頁獨立一個瀏覽器渲染進程(瀏覽器內(nèi)核) 每個瀏覽器渲染進程是多線程的,主要包括:GUI渲染線程 JS引擎線程 也稱為JS內(nèi)核,負責處理Javascript腳本程序。(例如V8引擎) JS引擎線程負...
摘要:如果存在于原型鏈上層,賦值語句的行為就會有些不同。中包含的屬性會屏蔽原型鏈上層的所有屬性,因為總是會選擇原型鏈中最底層的屬性。如果不直接存在于中而是存在于原型鏈上層時會出現(xiàn)的三種情況。類構(gòu)造函數(shù)原型函數(shù),兩個函數(shù)通過屬性和屬性相關(guān)聯(lián)。 1 [[Prototype]] 對于默認的 [[Get]] 操作來說,如果無法在對象本身找到需要的屬性,就會繼續(xù)訪問對象的 [[Prototype]] ...
摘要:如果存在于原型鏈上層,賦值語句的行為就會有些不同。中包含的屬性會屏蔽原型鏈上層的所有屬性,因為總是會選擇原型鏈中最底層的屬性。如果不直接存在于中而是存在于原型鏈上層時會出現(xiàn)的三種情況。類構(gòu)造函數(shù)原型函數(shù),兩個函數(shù)通過屬性和屬性相關(guān)聯(lián)。 1 [[Prototype]] 對于默認的 [[Get]] 操作來說,如果無法在對象本身找到需要的屬性,就會繼續(xù)訪問對象的 [[Prototype]] ...
摘要:閉包在循環(huán)中的應(yīng)用延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行事實上,當定時器運行時即使沒給迭代中執(zhí)行的是多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個出來。 閉包在循環(huán)中的應(yīng)用 延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行;事實上,當定時器運行時即使沒給迭代中執(zhí)行的是 setTime(..., 0),多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個6出來。 for(var...
showImg(https://segmentfault.com/img/bVbtd6M?w=1181&h=1365); showImg(https://segmentfault.com/img/bVbtd6T?w=1243&h=1984);
閱讀 4100·2021-09-23 11:51
閱讀 3213·2021-09-22 15:59
閱讀 1082·2021-09-09 11:37
閱讀 2246·2021-09-08 09:45
閱讀 1416·2019-08-30 15:54
閱讀 2229·2019-08-30 15:53
閱讀 622·2019-08-29 12:12
閱讀 3437·2019-08-29 11:15