js oop 对象的继承

2019-12-17  本文已影响0人  柒轩轩轩轩

prototype

JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。

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

原型链

js中所有对象都有自己的prototype。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个prototype chain
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。

那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。

constructor

prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数

function P() {}
P.prototype.constructor === P // true

constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

function Constr() {}
var x = new Constr();

var y = new x.constructor();
y instanceof Constr //true

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

所以,修改原型对象时,一般要同时修改constructor属性的指向。

// 好的写法
C.prototype = {
  constructor: C,
  method1: function (...) { ... },
  // ...
};

// 更好的写法
C.prototype.method1 = function (...) { ... };

instanceof

instanceof 运算符返回一个布尔值,表示对象是否为某个构造函数的实例

var v = new Vehicle();
v instanceof Vehicle //true
// 等同于
Vehicle.prototype.isPrototypeOf(v)

由于任意对象(除了null)都是Object的实例,所以instanceof运算符可以判断一个值是否为非null的对象

var obj = {foo: 123};
obj instanceof Object //ture
null instanceof Object //false

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

var obj = Object.create(null);
typeof obj // "object"
Object.create(null) instanceof Object //false
上一篇 下一篇

猜你喜欢

热点阅读