这是 最近在学习js继承时看了多篇文章以及自我总结的学习笔记。数组
目录:
一:原型链
二:构造函数
三:原型链和构造函数组合继承
四:原型式
五:寄生式
六:寄生组合式函数
function Super(){ this.name = 'lily'; this.age = 21; this.arr = [1,2,3] } function Sub(){} Sub.prototype = new Super();//核心 拿父类实例来充当子类原型对象 var l1 = new Sub(); var l2 = new Sub(); l1.name = 'gan'; l1.arr.push(4) l(l1.name)//'gan' l(l2.name)//'lily' l(l1.arr)//[1, 2, 3, 4] l(l2.arr)//[1, 2, 3, 4]
优势:easy
缺点: 1,原型对象的引用属性是全部实例共享的, l2.arr跟着 l1.arr一块儿变化学习
function Super(name,age){ this.name = name; this.age = age; this.arr = [1,2,3]; this.foo = function(){ //.. } } function Sub(name,age){ Super.call(this,[name,age])//核心 在子类型构造函数中调用超类型构造函数 } var l1 = new Sub('lily',21); var l2 = new Sub('gan',22); l1.arr.push(4) l(l1.name)//["lily", 21] l(l2.name)//["gan", 22] l(l1.arr)//[1, 2, 3, 4] l(l2.arr)//[1, 2, 3] l(l1.foo === l2.foo)//false
优势: 解决了子类实例共享父类引用属性的问题 可传参
缺点:方法都在构造函数中定义,浪费内存还不能复用。在超类型的原型中定义的方法对子类型而言不可见:this
Super.prototype.sayName = function(){ l(this.name) } l(l1.sayName)//undefined
function Super(name){ this.name = name; this.age = 21; this.arr = [1,2,3]; } Super.prototype.sayName = function(){ return this.name } function Sub(name){ Super.call(this,name)//核心 } Sub.prototype = new Super();//核心 Sub.prototype.constructor = Sub; var l1 = new Sub('lily'); l(l1.sayName())//lily
优势:从已有对象衍生新对象,不须要建立自定义类型(更像是对象复制,而不是继承)
缺点:原型引用属性会被全部实例共享,由于是用整个父类对象来充当了子类原型对象,因此这个缺陷无可避免;没法实现代码复用prototype
function object(o){ function F(){} F.prototype = o; return new F(); } function Super(){ this.name = 'lily'; this.age = 21; this.arr = [1,2,3,4] } Super.prototype.sayName = function(){ return this.name } var Sub = new Super(); l(Sub)//Super {name: "lily", age: 21} var sup = object(Sub) l(sup)//F {__proto__: Super}获得一个“纯洁”的新对象(“纯洁”是由于没有实例属性),再逐步加强之(填充实例属性) sup.sex = 'girl' l(sup)//F {sex: "girl",__proto__: Super} l(sup.arr) //[1,2,3,4] l(sup1.arr)//[1,2,3,4]
优势:从已有对象衍生新对象,不须要建立自定义类型(更像是对象复制,而不是继承)
缺点:原型引用属性会被全部实例共享,由于是用整个父类对象来充当了子类原型对象,因此这个缺陷无可避免;没法实现代码复用code
function object(o){ function F(){} F.prototype = o; return new F(); } function Super(){ this.name = 'lily'; this.age = 21; this.arr = [1,2,3,4] } Super.prototype.sayName = function(){ return this.name } function getSubObject(obj){ // 建立新对象 var clone = object(obj); // 核心 // 加强 clone.attr1 = 1; clone.attr2 = 2; //clone.attr3... return clone; } var Sub = getSubObject(new Super()); l(Sub)//Super {name: "lily", age: 21} var sup = object(Sub) var sup1 = object(Sub) l(sup)//F {__proto__: Super}获得一个“纯洁”的新对象(“纯洁”是由于没有实例属性),再逐步加强之(填充实例属性) l(sup.arr) l(sup1.arr)
function object(o){ function F(){} F.prototype = o; return new F(); } function Super(){ this.name = 'lily'; this.age = 21; this.arr = [1,2,3,4] } Super.prototype.sayName = function(){ return this.name } function Sub(){ Super.call(this) } var proto = object(Super.prototype); // 核心 proto.constructor = Sub; // 核心 Sub.prototype = proto; // 核心 var sub = new Sub(); l(sub.name); l(sub.arr);
用object(Super.prototype);切掉了原型对象上多余的那份父类实例属性对象