资讯专栏INFORMATION COLUMN

JavaScript继承的六种方式

wujl596 / 2900人阅读

这是 最近在学习js继承时看了多篇文章以及自我总结的学习笔记。

目录:
一:原型链
二:构造函数
三:原型链和构造函数组合继承
四:原型式
五:寄生式
六:寄生组合式

1、原型链
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一起变化

2,构造函数
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

优点: 解决了子类实例共享父类引用属性的问题 可传参
缺点:方法都在构造函数中定义,浪费内存还不能复用。在超类型的原型中定义的方法对子类型而言不可见:

Super.prototype.sayName = function(){
  l(this.name)
}
l(l1.sayName)//undefined
3,组合式(最常用)
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

优点:从已有对象衍生新对象,不需要创建自定义类型(更像是对象复制,而不是继承)
缺点:原型引用属性会被所有实例共享,因为是用整个父类对象来充当了子类原型对象,所以这个缺陷无可避免;无法实现代码复用

4,原型式
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]

优点:从已有对象衍生新对象,不需要创建自定义类型(更像是对象复制,而不是继承)
缺点:原型引用属性会被所有实例共享,因为是用整个父类对象来充当了子类原型对象,所以这个缺陷无可避免;无法实现代码复用

5,寄生式
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)
6,寄生组合式
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);切掉了原型对象上多余的那份父类实例属性

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86624.html

相关文章

  • JavaScript常见六种继承方式

    摘要:组合继承也是需要修复构造函数指向的这种方式融合原型链继承和构造函数的优点,是中最常用的继承模式。的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到上面所以必须先调用方法,然后再用子类的构造函数修改。 前言 面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。 大部分面向对象的编程语言,...

    silvertheo 评论0 收藏0
  • JavaScript常见六种继承方式

    摘要:组合继承也是需要修复构造函数指向的这种方式融合原型链继承和构造函数的优点,是中最常用的继承模式。的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到上面所以必须先调用方法,然后再用子类的构造函数修改。 前言 面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。 大部分面向对象的编程语言,...

    wyk1184 评论0 收藏0
  • JavaScript常见六种继承方式

    摘要:组合继承也是需要修复构造函数指向的这种方式融合原型链继承和构造函数的优点,是中最常用的继承模式。的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到上面所以必须先调用方法,然后再用子类的构造函数修改。 前言 面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。 大部分面向对象的编程语言,...

    anyway 评论0 收藏0
  • JavaScript常见六种继承方式

    摘要:组合继承也是需要修复构造函数指向的这种方式融合原型链继承和构造函数的优点,是中最常用的继承模式。的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到上面所以必须先调用方法,然后再用子类的构造函数修改。 前言 面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。 大部分面向对象的编程语言,...

    helloworldcoding 评论0 收藏0
  • JavaScript六种基本数据类型

    摘要:数据类型数据类型指的就是字面量类型在中一共有六种数据类型字符串数值布尔值空值未定义对象其中属于基本数据类型而属于引用数据类型字符串在中使用字符串需要使用引号括起来使用双引号或单引号都可以不能混合使用引号不能嵌套数值型在中所有数值类型都                                    数据类型 数据类型指的就是字面量类型 在JS中一共有六种数据类型 ...

    CollinPeng 评论0 收藏0

发表评论

0条评论

wujl596

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<