文档章节

原型、原型链、继承模式

王潭不是王雨潭
 王潭不是王雨潭
发布于 2017/08/27 21:13
字数 1535
阅读 493
收藏 1

原型模式

原型模式是js对继承的一种实现

prototype:构造函数中的属性,指向该构造函数的原型对象。

constructor:原型对象中的属性,指向该原型对象的构造函数

_proto_:实例中的属性,指向new这个实例的构造函数的原型对象

例子:

//Person构造函数
function Person() {
    name = 'Person';
    this.height = '160cm';
}
//在其原型对象中添加age属性
Person.prototype.age = '18';
//Person的实例p1
var p1 = new Person();
p1.age;//18
p1.name;//undefined
p1.height;//160cm

上图中原型与构造函数与实例的关系如下:

  • Person为构造函数
  • Person prototype为原型
  • p1虽然是通过newPerson获得的,但是p1的原型却直接指向Person Prototype,并且只得到了Person中的this的属性。

** var p1 = new Person()都发生了什么?

1.var p1 = new Object(); //此时p1._proto_ = Object Prototype

2.p1._proto_ = Person.prototype;

3.Person.call(p1);//使用新对象p1调用函数Person,将this作用域给p1

 原型链

在定义构造函数的prototype属性的时候,直接吧一个对象赋值给prototype。

例子:

//Person构造函数
function Person(){
    name = 'Person';
    this.height = '160cm';
}
//原型为一个Object实例,并有age属性
Person.prototype = {
    age: '18'
}
//Person的实例p1
var p1 = new Person();
p1.age;//18
p1.name;//undefined
p1.height;//160cm
  • Person Prototype直接变成了Object的一个实例,并且其中不再有constructor参数
  • Person Prototype直接变成了Object的一个实例,也就是说Person Prototype中有一个_proto_参数,指向Object Prototype

上图中原型与构造函数与实例的关系如下:

在实例p1中想要调用一个方法或者属性的时候会沿原型链向上查找。

借用构造函数

原型链存在的问题,如下:

//父类构造函数
function Super(){
    this.color = ['red','black','blue'];
}
//子类构造函数
function Sub(){}
//子类继承父类
Sub.prototype = new Super();
//新建一个子类的实例
var ins1 = new Sub();
ins1.color.push('green');

var ins2 = new Sub();
//因为color为一个引用对象,ins1和ins2的color都指向同一个地址,修改一个就会修改所有实例的color
ins2.color;//'red,belck,blue,green'

防止在原型链模式中,所有子类的实例公用一个父类构造函数的引用对象。

使用 借用构造函数 的方式实现继承。在子类构造函数的内部,调用超类的构造函数构造。如下:

//父类构造函数
function Super(){
    this.color = ['red','black','blue'];
}
//子类构造函数
function Sub(){
    //调用父类构造函数实现继承
    Super.call(this);
}
//新建一个子类的实例
var ins1 = new Sub();
ins1.color.push('green');
ins1.color;//'red,belck,blue,green'

//在实例ins2上重新执行Super构造函数,重新初始化对象,ins2拥有自己的color属性
var ins2 = new Sub();
ins2.color;//'red,belck,blue'

继承

1.组合继承

结合 原型链+借用构造函数 方式,实现组合继承。

借用构造函数使每个实例拥有自己的属性;原型链使每个实例可以共用方法,实现方法的复用。

//Super中定义属性name
function Super(name){
    this.name = name;
    this.color = ['red','green'];
}
//Super的原型中定义方法
Super.prototype.sayname = function(){
    console.log(this.name);
}
function Sub(name, age){
    //通过构造函数的方式继承Super的属性
    Super.call(this, name);
    //定义自己的属性
    this.age = age;
}
//通过原型链的方式继承方法
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;

var ins1 = new Sub('ins1',18);

缺点:会调用两次超类的构造函数,一次在Super.call(this, name); 一次在Sub.prototype = new Super();

导致Sub原型上有属性name、age,Sub实例上也有属性name、age。

2.原型式继承

借助原型,基于已有的对象创建新对象。

object.Create(参数1,参数2); 参数1用作新对象的原型对象,参数2为新对象定义额外属性的对象。

传入一个参数的情况:

var person = {
    name: 'person'
}
//基于已有的person对象,创建一个新的anthorp对象
var anthorp = Object.create(person);
//相当于如下语句
function object(o){
    function F(){};
    F.prototype = o;
    return new F();
}
//得到一个以person为原型的构造函数的实例
var anthorp = object(person);

传入两个参数的情况:

var person = {
    name: 'person'
}
//基于已有的person对象,创建一个新的anthorp对象,覆盖之前的name,并新增age
var anthorp = Object.create(person,{
    name: {
        value: 'anthorp'
    },
    age: {
        value: 18
    }
});
anthorp.name; //anthorp

3.寄生继承

创建一个用于封装继承过程的函数,在函数内部增强对象。并返回对象。

talk is cheap, show me code。

//创建一个用于封装继承过程的函数,传入obj
function create(obj){
    //通过调用object方法以obj为基础创建一个新对象。此处object表示任何能够返回新对象的函数
    var clone = object(obj);
    //以为对象新增方法的方式增强对象
    clone.sayHi = function(){
        console.log('hi');
    };
    //返回对象
    return clone;
}

//使用create函数
//一个基础对象person
var person = {
        name: 'person'
};
//基于基础对象使用寄生模式生成的新对象
var anthorp = create(person);
anthorp.sayHi();

4.寄生组合式继承

上面讲到组合继承的缺点:会调用两次超类的构造函数。

寄生组合式继承:借用构造函数来继承属性,通过原型链混成来继承方法。不必在子类原型中调用超类的构造函数。使用寄生继承来继承超类的原型,再将结果制定给子类的原型。

//寄生组合式继承
function inheritProto(Sub, Super){
    //根据Super的原型创建一个新的对象proto
    var proto = object(Super.prototype);
    //增强新对象,为其赋construtor值
    proto.constructor = Sub;
    //将新对象赋值给子类的原型。
    Sub.prototype = proto;
}
//使用
//Super中定义属性name
function Super(name){
    this.name = name;
    this.color = ['red','green'];
}
//Super的原型中定义方法
Super.prototype.sayname = function(){
    console.log(this.name);
}
function Sub(name, age){
    //通过构造函数的方式继承Super的属性,只在此处调用一次Super构造函数
    Super.call(this, name);
    //定义自己的属性
    this.age = age;
}
//调用函数,实现继承。代替之前的Sub.prototype = new Super();语句,防止Super构造函数调用两次
inheritProto(Sub,Super);

 

© 著作权归作者所有

王潭不是王雨潭
粉丝 8
博文 19
码字总数 19745
作品 0
杭州
私信 提问
加载中

评论(3)

竹山小道
竹山小道
有用 非常感谢
王潭不是王雨潭
王潭不是王雨潭

引用来自“马寂寞”的评论

学完之后受益匪浅,感谢您。
不用谢~我也是学习的时候随手记了笔记
马寂寞
马寂寞
学完之后受益匪浅,感谢您。
JavaScript高级程序设计02

面向对象 重点:原型 创建对象 Javascript中没有类的概念,对象是属性的集合,可以想象成成散列表。 对象实例 创建object实例,为它添加方法 对象字面量 其实就是创建object实例的简写形式 ...

白发道长
2018/01/02
0
0
史上最为详细的javascript继承

前言 为大家分享js中最常见最详细的继承方式,接下来将一下面的几个维度进行展示说明 文章有点长,请耐心阅读😁,有什么错误理解的地方希望留言指出来 产生原因 代码实现 基本原理 语言实现...

zhangfaliang
05/16
0
0
JavaScript中的3种继承方式

JavaScript中继承的方式主要有3种; 第一种:原型链继承,通过将子元素的原型指向父元素的实例对象来实现继承 ; 缺点:字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超...

YJ_
2017/07/27
0
0
JavaScript继承(三)——组合继承

借用构造函数继承解决了原型链数据共享和无法向超类型传递参数的问题,但自身的缺陷是不能使用超类型原型中定义的方法。组合继承是将原型链继承和借用构造函数继承组合到一起,从而发挥二者之...

Bob2100
01/26
0
0
《javascript高级程序设计》学习记录(四)

js继承,对这一块原本想自己记录一下,但是发现有一个仁兄的博客记录得比我更好,然后就直接借鉴过来了 由于不像那样是真正面向对象的语言,是基于对象的,它没有类的概念。所以,要想实现继...

sunshinewyf
2015/11/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Jenkins系列_插件安装及报错处理

进入Jenkins之后我们可以进行插件的安装,插件管理位于以下模块: 发现上面报了一堆错误,是因为插件的依赖没有安装好,那么这一节,就先把这些错误解决掉吧。解决完成后,也就基本会使用插件...

shzwork
今天
2
0
mysql mysql的所有查询语句和聚合函数(整理一下,忘记了可以随时看看)

查询所有字段 select * from 表名; 查询自定字段 select 字段名 from 表名; 查询指定数据 select * from 表名 where 条件; 带关键字IN的查询 select * from 表名 where 条件 [not] in(元素...

edison_kwok
昨天
9
0
多线程同时加载缓存实现

import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorServi......

暗中观察
昨天
3
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
昨天
2
0
组装一台工作游戏两用机

一、配置清单如下: 分类 项目 价格(元) 主板 华硕(ASUS)TUF Z370-PLUS GAMING II 电竞特工 Z370二代 支持9代CPU 1049 CPU 英特尔(Intel) i7 8700K 酷睿六核 盒装CPU处理器 2640 风扇 九...

mbzhong
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部