对象的继承
构造函数的毛病
面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能间接领有 B 对象的所有属性和办法
function Cat(name, color) {
this.name = name;
this.color = color;
this.meow = function () {console.log('喵喵');
};
}
var cat1 = new Cat('大毛', '红色');
var cat2 = new Cat('二毛', '彩色');
cat1.meow === cat2.meow
// false
cat1
和 cat2
是同一个构造函数的两个实例,它们都具备 meow
办法。因为 meow
办法是生成在每个实例对象下面,所以两个实例就生成了两次。也就是说,每新建一个实例,就会新建一个 meow
办法。这既没有必要,又节约系统资源,因为所有 meow
办法都是同样的行为,齐全应该共享。
prototype 属性的作用
每个函数都有一个 prototype
属性,指向一个对象。
function f() {}
typeof f.prototype // "object"
原型对象的属性不是实例对象本身的属性。只有批改原型对象,变动就立即会体现在 所有 实例对象上。
Animal.prototype.color = 'yellow';
cat1.color // "yellow"
cat2.color // "yellow"
原型链
Object.prototype
的原型是 null
。null
没有任何属性和办法,也没有本人的原型。因而,原型链的止境就是null
。
Object.getPrototypeOf(Object.prototype)
// null
如果让构造函数的 prototype
属性指向一个数组,就意味着实例对象能够调用数组办法。
var MyArray = function () {};
MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;
var mine = new MyArray();
mine.push(1, 2, 3);
mine.length // 3
mine instanceof Array // true
constructor 属性
prototype
对象有一个 constructor
属性,默认指向 prototype
对象所在的构造函数。
function P() {}
P.prototype.constructor === P // true
因为 constructor
属性定义在 prototype
对象下面,意味着能够被所有实例对象继承。
function P() {}
var p = new P();
p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false
nstanceof 运算符 #
instanceof
运算符返回一个布尔值,示意对象是否为某个构造函数的实例。
var v = new Vehicle();
v instanceof Vehicle // true