這本書應該是 14 年(或15年)買的,那時人比較傻,看不明白,匆匆看了幾十頁就束之高閣了,但是一有點很確定,這是本好書。
今天終於來到了這裡,感覺過了一道坎。 參考型別就是對象,對象就是參考型別
類型分原始類型和參考型別,原始類型就是那五個(ES5)
booleannumberstringnullundefined
其他的都是參考型別,參考型別就是對象,對象就是參考型別。 值賦值和引用賦值的區別
這兩者的區別必須要理解,在《你不知道的JavaScript(中卷)》中說的很清楚,值賦值就是把資料拷貝一份,引用賦值就是把對象的引用拷貝一份。 typeof null === ‘object’是一個BUG
設計和維護 JavaScript 的委員會 TC39 認定這是一個錯誤。 null 和 undefined 沒有封裝類型
原始類型的封裝類型有 3 種 String、Number、Boolean,null 和 undefined 沒有封裝類型。 裝箱與拆箱的過程
var name = 'Tom'name.last = 'Cat'name.last // undefined
理解了為什麼是undefined,就理解了裝箱與拆箱的過程,JavaScript 引擎實際發生的過程如下
var name = 'Tom'var temp = new String(name)temp.last = 'Cat'temp = nullvar temp = new String(name)temp.last // undefinedtemp = null
函數就是值
這就是為什麼說函數是一等公民的原因,基本上只要是可以使用其他引用值的地方就可以使用函數。 this 對象
全域範圍中,this 代表全域對象;
函數使用域中,this 代表調用該函數的對象;如果是直接執行函數(不是通過對象調用),非strict 模式下 this 代表全域對象,strict 模式下 this 代表 undefined;如果使用 new,this 代表建立的對象。 改變 this
除了 call 和 apply 之外,還有第三種方法 bind,第一個參數代表新函數的 this 的值,其他所有參數代表需要被永久設定在新函數中的參數
function sayName(label) { console.log(label + ": " + this.name);}var person1 = { name: 'Tom'};var person2 = { name: 'Jerry'}var sayNameForPerson1 = sayName.bind(person1);sayNameForPerson1('person1'); // person1: Tomvar sayNameForPerson2 = sayName.bind(person2, 'person2');sayNameForPerson2(); // person2: Jerryperson2.sayName = sayNameForPerson1;person2.sayName('person2'); // person2: Tom
關鍵是最後的輸出,被綁定之後再通過其他對象調用,this 仍是原來綁定的對象。 對象的內部方法
[[Put]] 添加一個屬性時觸發[[Set]] 修改一個屬性時觸發[[Delete]] delete操作符刪除屬性時觸發
對象的內部特徵
[[Extensible]] 是否可擴充[[Prototype]] 指向其原型對象
屬性的內部特徵
[[Configurable]] 是否可以再次配置或刪除[[Enumerable]] 是否可以枚舉[[Writable]] 是否可寫[[Value]] 屬性的值[[Get]] 訪問訪問器屬性[[Set]] 設定訪問器屬性
資料屬性沒有 [[Get]] 和 [[Set]],訪問器屬性不需要儲存值,所以沒有 [[Value]] 和 [[Writable]]。 執行個體對象、函數與原型對象之關的關係
函數有一個名為 prototype 的屬性,指向一個對象,該對象有一個 constructor 屬性指向該函數。這個對象叫原型對象。
使用 new 建立的執行個體對象有一個內部屬性 [[Protorype]] 指向該原型對象。
關於執行個體對象、函數與原型對象之關的關係,就這些,沒有漏掉什麼吧。 範圍安全的建構函式
function Person(name) { if (this instanceof Person) { this.name = name; } else { return new Person(name); }}
如Object、Array、RegExp 和 Error。