詳解JavaScript中基于原型prototype的繼承特性
JavaScript 中的繼承比較奇葩,無法實(shí)現(xiàn)接口繼承,只能依靠原型繼承。
原型鏈
原型就是一個(gè)對(duì)象,通過構(gòu)造函數(shù)創(chuàng)建出來的實(shí)例會(huì)有指針指向原型得到原型的屬性和方法。這樣,實(shí)例對(duì)象就帶有構(gòu)造函數(shù)的屬性方法和原型的屬性方法,然后將需要繼承的構(gòu)造函數(shù)的原型指向這個(gè)實(shí)例,即可擁有這個(gè)實(shí)例的所有屬性方法實(shí)現(xiàn)繼承。
看下面演示代碼:
//聲明超類,通過構(gòu)造函數(shù)和原型添加有關(guān)屬性和方法 function Super(){ this.property = true; } Super.prototype.getSuperValue = function() { return this.property; }; //聲明子類的構(gòu)造函數(shù) function SubType() { this.subproperty = false; } //將子類的原型指向超類的實(shí)例,得到超類的一切 SubType.prototype = new Super(); SubType.prototype.constructor = SubType; SubType.prototype.getSubValue = function(){ return this.subproperty; }; //由子類創(chuàng)建對(duì)象,測(cè)試是否繼承超類方法和屬性 var instance = new SubType(); console.log(instance.getSuperValue());
所有函數(shù)的默認(rèn)原型都是 Object 的實(shí)例,因此默認(rèn)原型都會(huì)包含一個(gè)內(nèi)部指針,指向 Object.prototype。
使用 instanceof 和 isPrototypeOf 可以確定原型和實(shí)例的關(guān)系:
instance instanceof Object; Object.prototype.isPrototypeOf(instance);
使用原型鏈的時(shí)候,需要謹(jǐn)慎的定義方法。子類需要重寫超類型的某個(gè)方法或者擴(kuò)充,一定要放在替換原型的語句后面,這樣才能生效。此外,通過原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,這樣會(huì)重寫原型鏈:
...... SubType.prototype = new Super(); SubType.prototype = { .... };
這會(huì)更換指針指向新對(duì)象,從而重寫了原型鏈。
原型鏈的繼承方法是有缺陷的,主要有兩個(gè)問題:
1,來自包含引用類型值的原型,會(huì)被所有實(shí)例共享。
前面文章介紹過包含引用類型值的原型屬性會(huì)被所有實(shí)例共享,一個(gè)實(shí)例修改,其他實(shí)例會(huì)隨之改變,因此需要在構(gòu)造函數(shù)中定義屬性。而原型鏈繼承的時(shí)候,無論超類中屬性是在構(gòu)造函數(shù)還是原型中定義,全部都變成了實(shí)例對(duì)象被子類繼承,從而對(duì)子類的實(shí)例產(chǎn)生影響。
2,創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。
原型鏈的繼承,直接將子類原型指向超類的實(shí)例,這時(shí)候可以向超類傳遞參數(shù)。但是當(dāng)子類創(chuàng)建實(shí)例的時(shí)候,只能向子類的構(gòu)造函數(shù)傳遞參數(shù),而不能向超類的構(gòu)造函數(shù)傳遞參數(shù)。
因此實(shí)際應(yīng)用中,很少單獨(dú)使用原型鏈。
相關(guān)的一些代碼實(shí)踐
鑒別一個(gè)原型屬性
function hasPrototypeProperty(object, name) { return name in object && !object.hasOwnProperty(name); }
在構(gòu)造函數(shù)中使用原型對(duì)象
function Person(name) { this.name = name; } Person.prototype = { constructor: Person, sayName: function () { console.log(this.name); }, toString: function() { } }; var person1 = new Person('Nicholas'); var person2 = new Person('Greg); console.log(person1 instanceof Person); // true console.log(person1.constructor === Person); // true console.log(person1.constructor === Object); // false console.log(person2 instanceof Person); // true console.log(person2.constructor === Person); // true console.log(person2.constructor === Object); // false
對(duì)象繼承
var person1 = { name: 'Nicholas', sayName: function () { console.log(this.name); } }; var person2 = Object.create(person1, { name: { configurable: true, enumerable: true, value: 'Greg', writable: true } }); person1.sayName(); // Nicholas person2.sayName(); // Greg console.log(person1.hasOwnProperty('sayName')); // true console.log(person1.isPropertyOf(person2)); // true console.log(person2.hasOwnProperty('sayName')); // false
模塊模式
var person = (function () { var age = 25; function getAge() { return age; } function growOlder() { age++; } return { name: 'Nicholas', getAge: getAge, growOlder: growOlder }; }());
作用域的構(gòu)造函數(shù)
function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); }; var person1 = Person('Nicholas'); console.log(person1 instanceof Person); // false console.log(typeof person1); // undefined console.log(name); // Nicholas
相關(guān)文章
詳解js運(yùn)算符單豎杠“|”與“||”的用法和作用介紹
在js開發(fā)應(yīng)用中我們通常會(huì)碰到“|”與“||”了,那么在運(yùn)算中“|”與“||”是什么意思呢?本篇文章主要介紹了詳解js運(yùn)算符單豎杠“|”與“||”的用法,有需要的可以了解一下。2016-11-11javascript如何創(chuàng)建表格(javascript繪制表格的二種方法)
利用js來動(dòng)態(tài)創(chuàng)建表格有兩種格式,appendChild()和insertRow、insertCell()。兩種方式其實(shí)差不多,但第一種有可能在IE上有問題,所以推薦大家使用第二種方法,看下面的解決和使用方法2013-12-12JavaScript charCodeAt方法入門實(shí)例(用于取得指定位置字符的Unicode編碼)
這篇文章主要介紹了JavaScript charCodeAt方法入門實(shí)例,charCodeAt方法用于取得指定位置字符的Unicode編碼,需要的朋友可以參考下2014-10-10關(guān)于鍵盤事件中keyCode、which和charCode 的兼容性測(cè)試
關(guān)于鍵盤事件中keyCode、which和charCode 的兼容性測(cè)試...2006-12-12JavaScript中switch判斷容易犯錯(cuò)的一個(gè)細(xì)節(jié)
這篇文章主要介紹了JavaScript中switch判斷容易犯錯(cuò)的一個(gè)細(xì)節(jié),簡單說就是字符串和數(shù)字的差別,看完本文會(huì)有一個(gè)清晰的認(rèn)知,需要的朋友可以參考下2014-08-08JS中處理時(shí)間之setUTCMinutes()方法的使用
這篇文章主要介紹了JavaScript中處理時(shí)間之setUTCMinutes()方法的使用,是JavaScript入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06