欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实例:原型链继承及问题

程序员文章站 2022-04-26 23:30:13
...

实现原理:

让父类的实例作为子类的原型对象

存在的问题:

如果单独只使用原型链继承会存在以下两个问题:

1)包含引用类型值的原型属性会被所有实例所共享:基本数据类型不受影响

2)无法在不影响其他实例的情况下向父类传递参数:不能实现子类向父类传参

举例说明:

//父类:构造函数
function Parent(name){
    this.name = name;
    this.color = ["green","blue"];
}

Parent.prototype = {
    constructor : Parent,
    sing : function(){
        console.log(this.name + "唱歌很好听");
    }
}

//子类
function Child(){

}

//注意:修改子类c1引用数据类型color的值,实例对象c2也被修改了
c1.color.push("yellow");
console.log(c1.color);
console.log(c2.color);

关键一步:让父类的实例作为子类的原型对象,问题一

//将父类的实例作为子类的原型对象
//这种方式没有办法做到给每个子类的实例单独设置各自的属性即问题一
Child.prototype = new Parent("Tom");

实例声明两个对象:

//声明一个子类的实例 c1
var c1 = new Child();

//声明一个子类的实例 c2
var c2 = new Child();

console.log(c1.name);
console.log(c1.color);

console.log(c2.name);
console.log(c2.color);

控制台的输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mCx3vjEu-1604910940649)(C:\Users\yingl\AppData\Roaming\Typora\typora-user-images\image-20201105151052986.png)]

修改构造函数的的数值为基本数据类型时,实例之间不互相影响

//修改子类C1基本数据类型name的值,c2不受影响
c1.name = "Jack";
console.log(c1.name);
console.log(c2.name);

控制台输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLbr8aQu-1604910940651)(C:\Users\yingl\AppData\Roaming\Typora\typora-user-images\image-20201105151305362.png)]

问题二:修改构造函数的数值为引用类型数据时,实例对象之间共享,数据相互影响

//注意:修改子类c1引用数据类型color的值,实例对象c2也被修改了
c1.color.push("yellow");
console.log(c1.color);
console.log(c2.color);

控制台输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Q7dcZDd-1604910940653)(C:\Users\yingl\AppData\Roaming\Typora\typora-user-images\image-20201105152110899.png)]

原型链解构:

  1. 每个对象都是由构造函数创建出来的,因为每个对象都有构造函数
  2. 每个构造函数都有一个与之对应的原型对象
  3. 原型对象本身也是对象
  4. 因此,原型对象也有自己的构造函数
  5. 原型对象的构造函数也有自己的原型对象
  6. 原型对象的构造函数的原型对象也是对象,所以它也有自己的构造函数
  7. 原型对象的构造函数的原型对象的构造函数也有自己的原型对象…

以上,形成一个链式结构,就称为原型链

原型链的顶端时 Object.prototype , Object.prototype 本身也是一个对象,因此也有原型对象.

Object.prototype.proto 是 null

原型链中对象属性的搜索规则—就近原则

  1. 对象属性的方法去访问属性的时候,先查找有没有对象的实例属性,如果有那么就之直接使用
  2. 如果没有,那么就去对象的原型对象上去找,如果有那么就直接使用
  3. 如果没有,那么就接着查找原型对象的原型对象,如果有,那么就直接使用
  4. 如果没有,那么就继续上面的搜索过程
  5. 直到搜索到 Object.prototype 为止,如果还是没有找到就返回 undefined 或者报错

注意:原型链搜索的路径越长,查询属性所花费的时间就越多

原型链继承的步骤:

  1. 提供一个父构造函数
  2. 提供一个子构造函数
  3. 设置子构造函数的原型对象为父构造函数的一个实例对象
  4. 在实例对象上面设置属性和方法

原型链使用时的注意事项

  1. 在设置完原型链之后需要修正构造器属性的指向
  2. 要在设置完原型继承之后再来为原型对象添加属性和方法
  3. 要在设置完原型继承之后只能通过对象的动态特性来设置原型对象的属性和方法,不要使用字面量的方式

原型链继承的问题:

  1. 参数传递问题:无法对父类构造函数传递参数
  2. 原型共享问题:继承过来的实例属性会成为当前对象的原型属性,会被创建出来的多个对象所共享

要在设置完原型继承之后只能通过对象的动态特性来设置原型对象的属性和方法,不要使用字面量的方式

原型链继承的问题:

  1. 参数传递问题:无法对父类构造函数传递参数
  2. 原型共享问题:继承过来的实例属性会成为当前对象的原型属性,会被创建出来的多个对象所共享
相关标签: 实现继承的方式