typeof null 爲 」object」 解釋
- 不一樣的對象在底層都表示爲二進制,在JavaScript中二進制前三位都爲0的話會被判斷爲object類型,null 的二進制表示都是0,天然前三位都是0,因此執行 typeof null 時,會返回 」object」。
傳統編程語言編譯的三個步驟
- 分詞/詞法分析
- 解析/語法分析
- 代碼生成
變量的賦值操做
- 編譯階段 -- 首次編譯器會在當前做用域中聲明一個變量(變量提高),若是以前沒用聲明過。
- 運行階段 -- 運行時引擎會在做用中查找該變量,若是可以找到就會對它賦值(LHS查詢。
做用域
- 做用域是一套規則,用於肯定在何處以及如何查找變量。
- 若是查找的目的是對變量賦值,那麼就會使用 LHS 查詢。
- 若是查找的目的是獲取變量的值,那麼就會使用 RHS 查詢。
- 不管函數在哪裏被調用,也不管它如何被調用,它的詞法做用域都只由函數被聲明時所處的位置決定。
閉包
- 當函數能夠記住並訪問所在的詞法做用域,即便函數是在當前詞法做用域以外執行,這時就產生了閉包。
this
- this 在任何狀況下都不指向函數的詞法做用域。
- 在 JavaScript 中做用域確實和對象相似,可見的標識符都是它的屬性。
- 可是做用域「對象」沒法經過 JavaScript 代碼訪問,它存在 JavaScript 引擎的內部。
- this 是在運行時進行綁定的,並非在編寫時綁定,它的上下文取決於函數調 用時的各類條件。
- this 的綁定和函數聲明的位置沒有任何關係,只取決於函數的調用方式。
- 當一個函數被調用時,會建立一個活動記錄(有時也稱爲執行上下文)。
- 這個記錄會包含函數在哪裏被調用(調用棧),函數的調用方法,傳入的參數等信息。this 就是記錄其中的一個屬性,會在函數執行的過程當中用到。
- this 其實是在函數被調用時發生的綁定,它指向什麼徹底取決於函數在哪裏被調用。
- 調用棧 — 就是爲了到達當前執行位置所調用到的所用函數。
bind()
- 會返回一個硬編碼的新函數,它會把參數設置爲 this 的上下文並調用原始函數。
new 操做符
使用 new 來調用函數時,會自動執行下面的操做:javascript
- 建立一個新的空對象;
- 這個對象會被執行[[原型]]鏈接;
- 這個新對象會綁定到函數調用的 this;
- 若是函數沒用返回其餘對象,那麼 new 表達式中的函數調用會自動返回這個新對象。
判斷 this
能夠根據下面的順序來進行判斷:java
-
函數是否在 new 中調用(new綁定)若是是的話,this 是綁定的是新建立的對象。web
var bar = new foo();
-
函數是不是經過 call apply (顯示綁定)或者硬綁定調用,若是是的話,this綁定的是指定的對象。編程
var bar = foo.call(obj2);
-
函數是否在某個上下文對象中調用(隱式調用),若是是的話,this綁定的是那個上下文對象。數組
var bar = obj.foo();
-
若果都不是的話,使用默認綁定,若是在嚴格模式下,就綁定到 undefined,不然綁定到全局對象上。微信
var bar = foo();
ES6 新增可計算屬性名
var prefix = "foo";
var myObject = {
[prefix + "bar"]: "hello",
[prefix + "baz"]: "world"
}
myObject["foobar"]; // hello
myObject["foobaz"]; // world
in / hasOwnProperty() -- 判斷某個對象是否存在某個屬性
- in 操做符會檢查屬性是否在對象及其 [[Prototype]] 原型鏈中。
- hasOwnProperty() 只會檢查屬性是否在 myObject 對象中,不會檢查 [[Prototype]] 鏈。
forEach() / every() / sone() -- 歷數組的值
- forEach() 會遍歷數組中的全部值並忽略回調函數的返回值(忽略返回值)。
- every() 方法測試數組的全部元素是否都經過了指定函數的測試(返回值是false終止)。
- some() 方法測試是否至少有一個元素經過由提供的函數實現的測試(返回值是true終止)。
for...in -- 遍歷數組下標/對象可枚舉屬性
for...of -- 遍歷可迭代對象的值
- 在可迭代對象上(包括 Array,Map,Set,String,TypedArray,arguments
對象等)上建立一個迭代循環,調用自定義迭代鉤子自定義的 @@iterator 對象 ,併爲每一個不一樣屬性的值執行語句。
var randoms = {
[Symbol.iterator]: function() {
return {
next: function() {
return {
value: Math.random()
};
}
};
}
};
var randoms_pool = [];
for (var n of randoms) {
randoms_pool.push( n );
// 防止無限運行!
if (randoms_pool.length === 100) break;
}
類的繼承和多態
- 多態並不表示子類和父類有關聯,子類獲得的只是父類的一份副本,類的繼承其實就是複製。
屬性的設置和屏蔽
var myObject = {};
myObject.foo = "bar";
- 若是 myObject 對象中包含名爲 foo 的普通數據訪問屬性,這條賦值語句只會修改已有的屬性值。
- 若是 foo 不是直接存在於 myObject 中,[[Prototype]] 鏈就會被遍歷,相似 [[Get]] 操做。
- 若是原型鏈上找不到 foo,foo 就會被直接添加到 myObject 上。
- 然而,若是 foo 存在於原型鏈上層,賦值語句 myObject.foo = "bar" 的行爲就會有些不一樣 (並且可能很出人意料)。
- 若是屬性名 foo 既出如今 myObject 中也出如今 myObject 的 [[Prototype]] 鏈上層,那 麼就會發生屏蔽。
- myObject 中包含的 foo 屬性會屏蔽原型鏈上層的全部 foo 屬性,由於 myObject.foo 老是會選擇原型鏈中最底層的
foo 屬性。
轉載請註明出處,若是想要了解更多,請搜索微信公衆號:webinfoq。閉包