本文約定:不特殊聲明的狀況下,屬性
代指屬性或方法
。segmentfault
建立對象、對象繼承其實是一回事:咱們所須要的實例對象經過構造函數得到私有屬性、經過原型鏈得到共享的屬性。什麼是好的方式?私有屬性經過構造函數的方式得到(不考慮實例中自定義私有屬性)且不須要重寫,共享屬性經過原型鏈找到且不須要重複建立。app
function HNU_student(name) { this.name = name; this.sayName = function() { return this.name; }; } HNU_student.prototype = { school: 'HNU', saySchool: function() { return this.school; } }; Object.defineProperty(HNU_student, 'constructor', {value: HNU_student}); var hiyohoo = new HNU_student('xujian');
經過字面量的方式會重寫prototype
,且原型的constructor
指向了Object
,必要的狀況下須要從新定義constructor
,使用Object.defineProperty()
方法能夠將constructor
的enumerable
等特性變爲初始默認的false
。函數
function object(o) { function F() {}; F.prototype = o; return new F(); } function inheritPrototype(child, parent) { var prototype = object(parent.prototype); prototype.constructor = child; child.prototype = prototype; } function HNU_student(name) { this.name = name; this.sayName = function() { return this.name; }; } HNU_student.prototype.school = 'HNU'; HNU_student.prototype.saySchool = function() { return this.school; }; function Student_2011(name, number) { HNU_student.call(this, name); this.number = number; this.sayNumber = function() { return this.number; } } inheritPrototype(Student_2011, HNU_student); Student_2011.prototype.graduationTime = 2015; Student_2011.prototype.sayGraduationTime = function() { return this.graduationTime; }; var hiyohoo = new Student_2011('xujian', 20110803203);
object()
的做用:將做爲參數傳入的對象變成實例的原型,該對象的屬性被全部實例共享。this
共享屬性:inheritPrototype(Student_2011, HNU_student);
,子構造函數原型成爲超構造函數原型的一個實例,超構造函數原型中的屬性共享給子構造函數。
私有屬性:HNU_student.call(this, name);
,經過子構造函數建立實例時調用超構造函數建立私有屬性。prototype
function HNU_student(name) { this.name = name; this.sayName = function() { return this.name; }; if (!HNU_student.prototype.school) { HNU_student.prototype.school = 'HNU'; HNU_student.prototype.saySchool = function() { return this.school; }; } } var hiyohoo = new HNU_student('xujian');
將定義在原型中的共享屬性放入構造函數中,使用判斷語句,在第一次調用構造函數建立實例時,初始化原型共享屬性。code
function SpecialArray() { var values = new Array(); values.push.apply(values, arguments); values.toPipedString = function() { return this.join('|'); }; return values; } var colors = new SpecialArray('red', 'black', 'white');
用於爲原生構造函數添加特殊的屬性。對象
function HNU_student(name) { this.name = name; this.sayName = function() { return this.name; }; } HNU_student.prototype.school = 'HNU'; HNU_student.prototype.saySchool = function() { return this.school; }; function Student_2011(name, number) { HNU_student.call(this, name); this.number = number; this.sayNumber = function() { return this.number; }; } Student_2011.prototype = new HNU_student(); //重寫原型必定要放在全部原型屬性定義以前 Student_2011.prototype.constructor = Student_2011; Student_2011.prototype.graduationTime = 2015; Student_2011.prototype.sayGraduationTime = function() { return this.graduationTime; } var hiyohoo = new Student_2011('xujian', 20110803203);
共享屬性:Student_2011.prototype = new HNU_student();
,子構造函數的原型就指向了超構造函數的原型,實例經過原型鏈找到全部共享的屬性。
私有屬性:HNU_student.call(this, name);
,經過子構造函數建立實例時調用超構造函數建立私有屬性。繼承
缺陷:超構造函數被調用了兩遍。Student_2011.prototype = new HNU_student();
的同時,在子構造函數原型中建立了超構造函數定義的私有屬性,這些原型中的私有屬性被實例中的同名屬性覆蓋屏蔽。ip
function object(o) { function F() {} F.prototype = o; return new F(); } var student1 = { school: 'HNU', saySchool: function() { return this.school; } }; var student2 = object(student1);
Object.creat()
是ECMAScript 5
新增的方法,接受兩個參數:一是做爲原型的原對象,二是重寫或新增屬性的對象,做用與自定義的object()
相同。ci
var student1 = { name: 'xujian', school: 'HNU' }; var student2 = Object.create(student1, { name: { value: 'huangjing' } });
寄生式繼承在原型式繼承的基礎上添加了額外的屬性用來加強對象。
function object(o) { function F() {} F.prototype = o; return new F(); } function creatAnother(original) { var clone = object(original); clone.sayHi = function() { alert('Hi!'); }; return clone; } var student1 = { school: 'HNU', saySchool: function() { return this.school; } }; var student2 = creatAnother(student1);
原型式繼承和寄生式繼承用於建立與已有對象相似的實例對象。
轉載請註明出處:http://www.javashuo.com/article/p-aleramvr-db.html
文章不按期更新完善,若是能對你有一點點啓發,我將不勝榮幸。