回味JS(六)對(duì)象的繼承

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ī)則是什么?

  1. 先尋找對(duì)象本身的屬性
  2. 如果找不到,就到它的原型去找
  3. 如果還是找不到,就到原型的原型去找
  4. 直到最頂層的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ù)的繼承?

  1. 在子類的構(gòu)造函數(shù)中,調(diào)用父類的構(gòu)造函數(shù)
  2. 讓子類的原型指向父類的原型,或者讓子類的原型等于一個(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ò)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容