function Father (name) {
this.name = name
this.hobby = ['挣钱','打小孩']
}
Father.prototype.sayName = function () {
return this.name
}
function Son (name) {
this.name = name
this.age = 8
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
var test1 = new Son();
test1.hobby.push('打牌')
test1.hobby // ["挣钱", "打小孩", "打牌"]
var test2 = new Son();
test2.hobby // ["挣钱", "打小孩", "打牌"]
在创建子类型的实例时,没有办法再不影响所有对象实例的情况下,改变属性
function Father (name) {
this.name = name
this.hobby = ['挣钱','打小孩']
}
Father.prototype.sayName = function () {
return this.name
}
function Son (name) {
Father.call(this, name)
}
var test1 = new Son('儿子')
test1.hobby.push('打牌')
test1.hobby // ["挣钱", "打小孩", "打牌"]
var test2 = new Son();
test2.hobby // ["挣钱", "打小孩"]
优点:解决了属性值被所有实例共享的缺点
缺点:父方法里面的原型方法,对于子是不可见的
function Father (name) {
this.name = name
this.hobby = ['挣钱','打小孩']
}
Father.prototype.sayName = function () {
return this.name
}
function Son (name) {
Father.call(this, name)
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
var test1 = new Son('儿子')
test1.hobby.push('打牌')
test1.hobby // ["挣钱", "打小孩", "打牌"]
var test2 = new Son();
test2.hobby // ["挣钱", "打小孩"]
优点:上面两个优点结合
缺点:无论是什么情况,都会调用两次父函数,一次是在创建子类原型,一次是在子类构造函数内部
function object (target) {
function Fn () {};
Fn.prototype = target;
return new Fn();
}
在 object 函数内部,先传入一个临时的构造函数,然后将这个传入的对象作为整个构造函数的原型,最后返回这个临时类型的新实例,本质上是对传入的对象的浅拷贝
es5 种有个Object.create()方法 ,这个方法接受两个参数,第一个参数是作为新对象原型的的对象 和 第二个(可选)为新对象定义额外属性的对象(可以覆盖原型对象上的同名属性)
Object.create 与 上面的object 方法原理相同
var person = {
name: 'son',
hobbies: ['学习', '打球']
}
var person1 = Object.create(person)
person1.name = 'person1';
person1.hobbies.push('花钱')
var person2 = Object.create(person)
person2.name = 'person2';
person2.hobbies.push('打架')
person1.hobbies // ["学习", "打球", "花钱", "打架"]
person2.hobbies // ["学习", "打球", "花钱", "打架"]
person1.name // person1
person2.name // person2
优点:在没有必要创建构造函数,只是想让一个对象与另外一个对象保持相似的情况,原型式继承可以胜任
缺点:与原型链实现继承一样,引用类型的值会被所有实例共享
function createAnother(original) {
var clone = Object.create(original) // 通过调用函数创建一个新对象
clone.sayName = function () {
console.log(this.name);
console.log(this.hobbies);
}
return clone;
}
var person = {
name: '儿子',
hobbies: ['打牌', '逃课']
}
var person1 = createAnother(person)
person1.hobbies.push('花钱')
person1.sayName(); // 儿子 ["打牌", "逃课", "花钱"]
var person2 = createAnother(person)
person2.sayName(); // 儿子 ["打牌", "逃课", "花钱"]
优点:在考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的方式
缺点:同原型链继承一样,包含了引用类型的属性,会被所有实例共享
通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
function inheritPrototype (Son, Father) {
var prototype = Object.create(Father.prototype); // 创建对象
prototype.constructor = Son; // 继承原型方法
Son.prototype = prototype;
}
function Father () {
this.name = '爸爸'
this.hobbies = ['喝酒']
}
Father.prototype.say = function () {
console.log(this.name)
}
function Son () {
Father.call(this) // 继承父类属性
this.age = 15
}
// 继承父类原型方法
inheritPrototype (Son, Father);
Son.prototype.work= function () {
console.log('上学')
}
Son.prototype.say = function () {
console.log('儿子')
}
var son = new Son();
son.hobbies.push('两都有')
son.hobbies // ["喝酒", "两都有"]
son.say(); // 儿子
var father = new Father();
father.say(); //爸爸
father.hobbies // ['喝酒']
优点:与上面第 3 方法相比, 父类只在子类构造函数中调用一次,实现属性,方法继承