原型
原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
// Car.prototype ==> {} 祖先
Car.prototype.name = 'GTR';
Car.prototype.color = 'silver';
// Car.prototype = {
// name = 'GTR';
// color = 'silver';
// }
function Car(owner) {
this.owner = owner;
}
var car = new Car('TT');
Dog.prototype.name = 'laifu';
function Dog() {
// var this = { __proto__ : Dog.protype }
// 准确:this = Object.create(Dog.prototype);
// return this;
}
var laifu = new Dog();
Dog.prototype = {
name : 'wangcai'
}
console.log(laifu.name); // laifu
- 利用原型特点和概念,可以提取共有属性。
- 构造函数如何查看原型 ==>
prototype
- 对象如何查看原型 ==> 隐式属性:
__proto__
- 对象如何查看对象的构造函数 ==>
constructor
function Dog(name, breed) {
this.name = name;
this.breed = breed;
}
var wangcai = new Dog('wangcai', 'ShibaInu');
var laifu = new Dog('laifu', 'TuGou');
console.log(Dog.prototype);
console.log(wangcai.__proto__);
console.log(Dog.prototype === wangcai.__proto__); // true
console.log(Dog.prototype.constructor);
console.log(wangcai.constructor);
console.log(Dog.prototype.constructor === wangcai.constructor); // true
原型链
Grand.prototype.lastName = 'Li';
function Grand() {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'bai';
this.composition = {
no1 : '侠客行'
}
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'compose';
}
var son = new Son();
console.log(son.lastName);
son.composition.no1 = '将进酒'; // 引用值修改
son.composition.no2 = '蜀道难'; // 引用值添加
console.log(son.composition);
console.log(father.composition);
绝大多数对象最终都会继承自
Object.prototype
var obj = Object.create(null);
// 以null为原型创建一个对象
console.log(obj); // 一个完全为空的对象
obj.__proto__ = { name : 'sunny' }
console.log(obj.name); // undefined
// 原型是隐式的内部属性,人为设置是不具有继承特性的。
继承
-
传统形式 ==> 原型链继承
- 过多的继承了没用的属性
-
借用构造函数
- 不能继承借用构造函数的原型
- 每次构造函数都要多走一个函数
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } function Student(name, age, gender, tel, grade) { Person.call(this, name, age, gender); // 把Person里的this指向改变为Student里的this // this.name = name; // this.age = age; // this.gender = gender; this.tel = tel; this.grade = grade; }
-
共享原型
- 不能随便改动自己的原型
Father.prototype.lastName = 'Li'; function Father() {} function Son() {} Son.prototype = Father.prototype var son = new Son(); // 抽象成函数方法 function inherit(Target, Origin) { Target.prototype = Origin.prototype; } inherit(Son, Father); var son = new Son(); // 缺点: Son.prototype.key = 'value'; // Son和Father都继承到key属性了
-
圣杯模式
Father.prototype / \ / \ Father function Fn() {} Fn.prototype = Father.prototype \ \ Son.prototype = new Fn() // 抽象成函数 function inherit(Target, Origin) { function Fn() {} Fn.prototype = Origin.prototype; Target.prototype = new Fn(); Target.prototype.constructor = Target; // 防止new Target()生成的对象的constructor指向紊乱 Target.prototype.uber = Origin.prototype; // 可以人为标记Target真正继承的是Origin,而不是中间层的Fn } Father.prototype.lastName = 'Li'; function Father() {} function Son() {} inherit(Son, Father); var son = new Son(); var father = new Father(); Son.prototype.key = 'value'; console.log(son.key); // value console.log(father.key); // undefined
var inherit = (function() { var Fn = function () {} // 形成闭包后,Fn就可以看作是一个私有变量。 return function (Target, Origin) { Fn.prototype = Origin.prototype; Target.prototype = new Fn(); Target.prototype.constructor = Target; Target.prototype.uber = Origin.prototype; } }());