`prototype` 是 `Function` 对象的一个属性,这个属性指向另一个对象。 这个对象的所有属性和方法,都会被构造函数的实例继承。
同时 `prototype` 又存在一个指向构造函数的引用 `constructor`,这样就成功的构成一个循环引用的原型链结构。
我们可以把那些不变的属性和方法,直接定义在 `prototype` 对象上, 节省内存开销。
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = 'mammal';
Cat.prototype.eat = function() { console.log('eat fish'); };
var cat1 = new Cat('Kitty', 'white');
var cat2 = new Cat('Smokey', 'black');
console.log(cat1.type); // mammal
console.log(cat1.eta === cat2.eta); // TRUE, same reference
console.log(cat1.constructor === Cat) // TRUE, from Person.prototype
之二、继承 (Inheritance)
将持有共性特点的属性或行为抽象出一个基本类, 可以按不同层次结构的业务分组抽象出多个基础类。
Cat, Bird
1. 继承 – 构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上。
function Animal() {
this.species = 'animal';
this.sleep = function() { console.log('I\'m sleep at night'); };
}
function Cat(name, color) {
this.name = name;
this.color = color;
}
让`Cat` 继承 `Animal` 的特性:
/** @class Cat */
function Cat(name, color) {
Animal.apply(this);
this.name = name;
this.color = color;
}
var cat1 = new Cat('Kitty', 'white');
cat1.sleep(); // I am sleep at night
2. 继承 – 原型链继承
如果”猫”的prototype对象,指向一个Animal的实例,那么所有”猫”的实例,就能继承Animal了。
/** @class Cat */
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype = new Animal;
Cat.prototype.eta = function() { console.log('fish is my delicious'); };
它相当于完全删除了prototype 对象原先的值,然后赋予一个新值
// 任何一个prototype对象都有一个constructor属性,指向它的构造函数
Cat.prototype.constructor = Cat; // fix prototype chains
var cat = new Cat('Kitty', 'fish');
cat.eat(); // fish is my delicious
cat.sleep(); // I'm sleep at night'
console.log(cat instanceof Cat); // TRUE
console.log(cat instanceof Animal); // TRUE
需要创建父类实列来实现 `prototype` 继承
3. 继承 (Inheritance) – 利用空对象作为中介实现原型继承
var F = function() {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
我们将上面的方法,封装成一个函数,便于使用。
function extend(ctor, superctor, px) {
if (!superctor || !ctor) throw Error('extend failed, verify dependencies');
var F = function() {};
F.prototype = superctor.prototype;
ctor.prototype = new F();
ctor.prototype.constructor = ctor;
ctor.superclass = superctor.prototype; // cache super class proto reference.
if (px) { // extend class implements
for (var k in px) {
if (px.hasOwnProperty(k)) ctor.prototype[k] = px[k];
}
}
return ctor;
}
4 继承 – 借住工具方法实现继承
/** @class Mammal */
extend(Cat, Animal, {
eat: function() {
Cat.superclass.eat.call(this); // call super method
console.log('Also i like some ofther food, such as beef and more.');
}
});
var cat = new Cat('Smokey', 'fish');
cat.sleep();
cat.eat();
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
之三、多态
1. 多态 – 通过重写原型方法来实现方法重名调用
/** @class Cat */
extend(Cat, Animal, {
eat: function() {
Cat.superclass.eat.call(this); // call super method
console.log('Also i like some ofther food, such as beef and more.');
}
});
2. 多态 (Polymorphism) – 原型继承 `prototype` 链上的方法、属性查找
【四】总结 Summary
Constructor
Prototype
同时 `prototype` 又存在一个指向构造函数的引用 `constructor`,这样就成功的构成一个循环引用的原型链结构。
我们可以把那些不变的属性和方法,直接定义在 `prototype` 对象上, 节省内存开销。
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = 'mammal';
Cat.prototype.eat = function() { console.log('eat fish'); };
var cat1 = new Cat('Kitty', 'white');
var cat2 = new Cat('Smokey', 'black');
console.log(cat1.type); // mammal
console.log(cat1.eta === cat2.eta); // TRUE, same reference
console.log(cat1.constructor === Cat) // TRUE, from Person.prototype
之二、继承 (Inheritance)
将持有共性特点的属性或行为抽象出一个基本类, 可以按不同层次结构的业务分组抽象出多个基础类。
Cat, Bird
1. 继承 – 构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上。
function Animal() {
this.species = 'animal';
this.sleep = function() { console.log('I\'m sleep at night'); };
}
function Cat(name, color) {
this.name = name;
this.color = color;
}
让`Cat` 继承 `Animal` 的特性:
/** @class Cat */
function Cat(name, color) {
Animal.apply(this);
this.name = name;
this.color = color;
}
var cat1 = new Cat('Kitty', 'white');
cat1.sleep(); // I am sleep at night
2. 继承 – 原型链继承
如果”猫”的prototype对象,指向一个Animal的实例,那么所有”猫”的实例,就能继承Animal了。
/** @class Cat */
function Cat(name, color) {
this.name = name;
this.color = color;
}
Cat.prototype = new Animal;
Cat.prototype.eta = function() { console.log('fish is my delicious'); };
它相当于完全删除了prototype 对象原先的值,然后赋予一个新值
// 任何一个prototype对象都有一个constructor属性,指向它的构造函数
Cat.prototype.constructor = Cat; // fix prototype chains
var cat = new Cat('Kitty', 'fish');
cat.eat(); // fish is my delicious
cat.sleep(); // I'm sleep at night'
console.log(cat instanceof Cat); // TRUE
console.log(cat instanceof Animal); // TRUE
需要创建父类实列来实现 `prototype` 继承
3. 继承 (Inheritance) – 利用空对象作为中介实现原型继承
var F = function() {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
我们将上面的方法,封装成一个函数,便于使用。
function extend(ctor, superctor, px) {
if (!superctor || !ctor) throw Error('extend failed, verify dependencies');
var F = function() {};
F.prototype = superctor.prototype;
ctor.prototype = new F();
ctor.prototype.constructor = ctor;
ctor.superclass = superctor.prototype; // cache super class proto reference.
if (px) { // extend class implements
for (var k in px) {
if (px.hasOwnProperty(k)) ctor.prototype[k] = px[k];
}
}
return ctor;
}
4 继承 – 借住工具方法实现继承
/** @class Mammal */
extend(Cat, Animal, {
eat: function() {
Cat.superclass.eat.call(this); // call super method
console.log('Also i like some ofther food, such as beef and more.');
}
});
var cat = new Cat('Smokey', 'fish');
cat.sleep();
cat.eat();
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
之三、多态
1. 多态 – 通过重写原型方法来实现方法重名调用
/** @class Cat */
extend(Cat, Animal, {
eat: function() {
Cat.superclass.eat.call(this); // call super method
console.log('Also i like some ofther food, such as beef and more.');
}
});
2. 多态 (Polymorphism) – 原型继承 `prototype` 链上的方法、属性查找
【四】总结 Summary
Constructor
Prototype