JavaScript 繼承機(jī)制的設(shè)計(jì)思想?
- 原型對(duì)象的所有屬性和方法,都能被實(shí)例對(duì)象共享。也就是說,如果屬性和方法定義在原型上,那么所有實(shí)例對(duì)象就能共享
prototype 屬性有什么作用?
- 構(gòu)造函數(shù)生成實(shí)例的時(shí)候,prototype 屬性會(huì)自動(dòng)成為實(shí)例對(duì)象的原型;
- 在構(gòu)造函數(shù)的原型對(duì)象上添加一個(gè)屬性,則這個(gè)構(gòu)造函數(shù)生成的實(shí)例都會(huì)共享這個(gè)屬性;
- 實(shí)例對(duì)象本身沒有某個(gè)屬性或方法的時(shí)候,它會(huì)到原型中去找這個(gè)屬性或方法
so,總結(jié)一下,原型對(duì)象的作用,就是定義所有實(shí)例對(duì)象共享的屬性和方法。
什么是原型鏈?
- 每個(gè)對(duì)象擁有一個(gè)原型對(duì)象,通過 proto指針指向上一個(gè)原型 ,并從中繼承方法和屬性,同時(shí)原型對(duì)象也可能擁有原型,這樣一層一層,最終指向 null。
- 這種關(guān)系被稱為原型鏈 (prototype chain),通過原型鏈一個(gè)對(duì)象會(huì)擁有定義在其他對(duì)象中的屬性和方法。
原型鏈的盡頭是什么?
- null, 沒有任何屬性和方法,也沒有自己的原型
原型鏈中對(duì)象屬性的查找規(guī)則是什么?
- 先尋找對(duì)象本身的屬性
- 如果找不到,就到它的原型去找
- 如果還是找不到,就到原型的原型去找
- 直到最頂層的Object.prototype還是找不到,則返回undefined
constructor的屬性有什么作用?
- 可以得知某個(gè)實(shí)例對(duì)象,到底是哪一個(gè)構(gòu)造函數(shù)產(chǎn)生的
- 有了constructor屬性,就可以從一個(gè)實(shí)例對(duì)象新建另一個(gè)實(shí)例
為什么修改原型對(duì)象時(shí),一般要同時(shí)修改constructor屬性的指向?
function A() {}
function B() {}
A.prototype.constructor === A; // true
A.prototype = B;
A.prototype.constructor === A; // false
A.prototype.constructor === Function; // true
如上,修改了A.prototype以后,constructor屬性的指向就變了,因?yàn)锳的新原型B是一個(gè)函數(shù),而函數(shù)的constructor屬性指向Function構(gòu)造函數(shù),所以,修改原型對(duì)象時(shí),一般要同時(shí)修改constructor屬性的指向。
一般可以像下面這么寫:
C.prototype = {
constructor: C,
method1: function (...) { ... },
// ...
};
// 或更好的寫法
C.prototype.method1 = function (...) { ... };
tips:
- 可以通過name屬性,從實(shí)例得到構(gòu)造函數(shù)的名稱
A.prototype.constructor = A;
var a = new A();
a.constructor.name // "A"
instanceof 和 typeof 判斷類型有什么區(qū)別?
- instanceof表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例
- instanceof運(yùn)算符只能用于對(duì)象,不適用原始類型的值; 而typeof適用于判斷原始類型
- 結(jié)合instanceof和typeof運(yùn)算符可以判斷一個(gè)值是否為非null的對(duì)象
null instanceof Object
// false
typeof null
// "object"
如何實(shí)現(xiàn)構(gòu)造函數(shù)的繼承?
- 在子類的構(gòu)造函數(shù)中,調(diào)用父類的構(gòu)造函數(shù)
- 讓子類的原型指向父類的原型,或者讓子類的原型等于一個(gè)父類的實(shí)例
例如下面是實(shí)現(xiàn)Sub繼承父類Super的過程:
function Super() {};
function Sub(value) {
Super.call(this); // 子類內(nèi)部調(diào)用父類的構(gòu)造函數(shù)
this.prop = value;
}
Sub.prototype = Object.create(Super.prototype); // 讓子類的原型指向父類的原型
Sub.prototype.constructor = Sub; // 別忘了同時(shí)修改constructor屬性
Sub.prototype.method = '...';
立即執(zhí)行函數(shù)的作用?
- 封裝私有變量,創(chuàng)建一個(gè)獨(dú)立的作用域,避免變量污染
怎么獲取實(shí)例對(duì)象obj的原型對(duì)象?
- obj.proto
- obj.constructor.prototype
- Object.getPrototypeOf(obj)
嚴(yán)格模式下有哪些規(guī)則?
- 不可以設(shè)置字符串的length屬性,會(huì)報(bào)錯(cuò)
- 對(duì)只讀屬性賦值,或者刪除不可配置(non-configurable)屬性都會(huì)報(bào)錯(cuò)
- 對(duì)一個(gè)只有取值器(getter)、沒有存值器(setter)的屬性賦值,會(huì)報(bào)錯(cuò)
- 對(duì)禁止擴(kuò)展的對(duì)象添加新屬性,會(huì)報(bào)錯(cuò)
- 使用eval或者arguments作為標(biāo)識(shí)名,將會(huì)報(bào)錯(cuò)
- 函數(shù)不能有重名的參數(shù)
- 禁止八進(jìn)制的前綴0表示法,整數(shù)第一位為0,將報(bào)錯(cuò)
- 全局變量必須顯式聲明
- 禁止 this 關(guān)鍵字指向全局對(duì)象
- 函數(shù)內(nèi)部不得使用fn.caller、fn.arguments,否則會(huì)報(bào)錯(cuò)
- 函數(shù)內(nèi)部使用arguments.callee、arguments.caller將會(huì)報(bào)錯(cuò)
- 嚴(yán)格模式下無法刪除變量,如果使用delete命令刪除一個(gè)變量,會(huì)報(bào)錯(cuò)。只有對(duì)象的屬性,且屬性的描述對(duì)象的configurable屬性設(shè)置為true,才能被delete命令刪除
- 禁止使用 with 語句
- eval所生成的變量只能用于eval內(nèi)部
- arguments 不再追蹤參數(shù)的變化
- 不允許在非函數(shù)的代碼塊內(nèi)聲明函數(shù)
- 新增了一些保留字(implements、interface、let、package、private、protected、public、static、yield等)。使用這些詞作為變量名將會(huì)報(bào)錯(cuò)