function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
复制代码
但这种方式有一个缺点:没法判断某个对象是什么类型。es6
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var p1 = new Person("Nicholas", 29, "Software Engineer");
var p2 = new Person("Greg", 27, "Doctor");
复制代码
构造函数也存在问题,每一个方法都要在实例上建立一遍。也就是说p1和p2的sayName()方法虽然做用相同,但这两个方法并非同一个函数bash
解析一道题函数
new操做符作了什么:ui
(1)建立一个新对象this
(2)将构造函数的做用域赋给新对象(所以this就指向了这个新对象)spa
(3)执行构造函数中的代码prototype
(4)返回新对象设计
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
复制代码
当咱们改变 值为引用类型的对象的属性 时,这个改变的结果会被其余对象共享。3d
构造函数模式的属性没毛病。缺点是:没法共享方法code
原型模式的方法没毛病。缺点是:当原形对象的属性的值为引用类型时,对其进行修改会反映到全部实例中
那咱们就将二者的结合,对象的属性使用构造函数模式建立,方法则使用原型模式建立
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
复制代码
JavaScript中引入了原型链的概念,具体思想: 子构造函数的原型对象初始化为父构造函数的实例,孙构造函数的原型对象初始化为子构造函数的实例…… ,这样子对象就能够经过原型链一级一级向上查找,访问父构造函数中的属性以及方法。
function SuperType(){
this.property = true;
};
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = false;
};
// 继承Supertype
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());
复制代码
当咱们改变 值为引用类型的原型对象的属性 时,这个改变的结果会被全部子对象共享。这个缺点某些时候至关致命,因此咱们不多使用这种方法来继承
function SuperObject(){
this.colors = ['red','blue'];
this.sayBye= function(){
console.log('Bye')
}
}
function SubObject(){
SuperObject.call(this); // 在子类中调用父类的构造方法,实际上子类和父类已经没有上下级关系了
}
var instance1 = new SubObject();
instance1.colors.push('yellow');
var instance2 = new SubObject();
console.log(instance2.colors); //['red','blue']
console.log(instance2 instanceof SuperObject); // false
console.log(instance1.sayBye === instance2.sayBye) // false
复制代码
这个方法虽然弥补了原型链的缺点,可是又暴露出了新的缺点:
1 子类和父类没有上下级关系,instance2 instanceof SuperObject 结果是false
2 父类中的方法在每一个子类中都会生成一遍,父类中的方法没有被复用。
组合继承就是将原型链继承和借用构造方法继承组合,发挥二者之长。
function SuperType(name){
this.name = name;
this.colors = ['blue'];
}
SuperType.prototype.sayName = function(){
alert(this.name);
}
function SubType(name, age){
// 引用父类型的属性,又调用了一次父函数
SuperType.call(this,name);
this.age = age;
}
// 继承父类型的方法,调用了一次父函数
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType('zz',18);
instance1.sayName(); //zz
instance1.sayAge(); //18
instance1.colors.push('red');
console.log(instance1.colors); // ['blue','red']
var instance2 = new SubType('tt',22);
console.log(instance2.colors); // ['blue']
组合继承会调用两次父类型函数
原型式继承
代码块
function object(o){
function F(){};
F.prototype = o;
return new F();
}
var Person = {
name: 'Nicholas'
friends: ['zz','cc']
}
var anotherPerson = object(Person);
anotherPerson.friends.push('dd');
console.log(anotherPerson.friends); //['zz','cc','dd']
复制代码
function createAnother(o){
var clone = object(o);
o.sayHi = function(){
console.log('hi');
}
return clone;
}
复制代码
虽然组合继承没啥大缺点,可是爱搞事情的有强迫症的程序猿们以为,组合继承会调用两次父类型函数(在上面的代码中标注了),不够完美。因而道格拉斯就提出了寄生组合继承。
思路是构造一个中间函数,将中间函数的prototype指向父函数的原型对象,将子函数的prototype指向中间函数,并将中间函数的constructor属性指向子函数。
function object(o){
function F(){};
F.prototype = o;
return new F();
}
function inheritPrototype(subType,superType){
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name){
this.name = name;
this.colors = ['red','blue','green'];
}
SuperType.prototype.sayName = function(){
alert(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
alert(this.age)
}
var instance1 = new SubType('zz', 18);
instance1.sayName();
复制代码
MDN:developer.mozilla.org/zh-CN/docs/…
JS高级语言程序设计第六章(面向对象的程序设计)