• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
从容优雅、漂亮精湛
博客园    首页    新随笔    联系   管理    订阅  订阅

对象的继承

instanceof__阴斯den斯of、prototype_泼特type、constructor_肯si爪ct

构造函数的缺点:

实例化对象不能进行,各个实例化的共享,需要依赖于,JavaScript 的原型对象(prototype)。才可以进行共享。构造函数中的this是指实例化对象。

prototype 属性的作用 :

其实也就是一个对象的原型对象,就是它的prototype属性。如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法,否则会往原型上找是否存在指定的属性。

原型链:

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。  读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。注意,一级级向上,在整个原型链上寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。

constructor 属性:

 prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。如果不能确定constructor属性是什么函数,还有一个办法:通过name属性,从实例得到构造函数的名称。

constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。

function Person(name) {
  this.name = name;
}

Person.prototype.constructor === Person // true

Person.prototype = {
  method: function () {}
};

Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true

上面代码中,构造函数Person的原型对象改掉了,但是没有修改constructor属性,导致这个属性不再指向Person。由于Person的新原型是一个普通对象,而普通对象的constructor属性指向Object构造函数,导致Person.prototype.constructor变成了Object。

instanceof 运算符:

instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。由于instanceof检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true。

var d = new Date();
d instanceof Date // true
d instanceof Object // true

注意:instanceof的原理是检查右边构造函数的prototype属性,是否在左边对象的原型链上。有一种特殊情况,就是左边对象的原型链上,只有null对象。这时唯一的,instanceof判断会失真的情况。

instanceof运算符的一个用处,判断对象的类型。只能用于对象,不适用原始类型的值。

构造函数的继承:

// 父类
functions life() {
       this.work = '编程';
       this.game = 'lol';      
}
life.prototyoe.read = '《三体》';

// 小红 继承父类生活 
function xiaohong() {
  // 第一种方式
  life.call(this);
  // 第二种方式
  this.base = life;
  this.base();
}

// 完成原型的继承
xiaohong.prototype = Object.create(life.prototype);
// prototype 原型对象继承了,相应的constructor 也需要继承
xiaohong.prototy.constructor = xiaohong;

// 验证继承是否成功
const xiaohong = new xiaohong();
xiaohong instanceof life // true
life instanceof life // true

多重继承:

JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能。

function M1() {
  this.hello = 'hello';
}

function M2() {
  this.world = 'world';
}

function S() {
  M1.call(this);
  M2.call(this);
}

// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2 assign es6中的对象合并方法,左边为目标对象,右边为数据源对象
Object.assign(S.prototype, M2.prototype);

// 指定构造函数
S.prototype.constructor = S;

var s = new S();
s.hello // 'hello'
s.world // 'world'

上面代码中,子类S同时继承了父类M1和M2。这种模式又称为 Mixin(混入)。

参考文献: Javascript 教程 网道 https://wangdoc.com/javascript/oop/prototype.html

posted @ 2021-07-08 15:28  从容优雅、美丽精湛  阅读(100)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3