javascript面向对象总结
关于创建对象:
?
?
1:构造函数的方式
?
/** * 构造函数的方式 *//** *构造方法 的缺点是,构造出的实例都会有一份方法(对象)。这是没必要的 */function Person(name,age){this.name=name;this.age=age;this.sayHello=function(){alert(this.name);}}var p=new Person("n",1);
?
?
2:构造与原型混合的方式
/** * 构造与原型混合的方式 *//** *构造与原型混全合的方式实现了实例共用一份方法(对象)的功能。 */function Person(name,age){this.name=name;this.age=age;}Persona.prototype={sayHello:function(){alert(this.name);}}var p1=new Person("x",1);var p2=new Person("y",2);alert(p1.sayHello===p2.sayHello);//true;
?
?
3:动态原型模式
/** * 动态原型模式 *//** *动态原型模式将构造与原型混合的模式做了调整,组合到了一起,更优雅一些。 * @param {Object} name * @param {Object} age */function Person(name,age){//属性this.name=name;this.age=age;//方法if(typeof this.sayHello != "function"){Person.prototype=function(){alert(this.name);}}}
?
?
?
?
关于继承
1:原型链实现继承
?
/** *原型链实现继承 * 1:原型链虽然很强大,可以用它来实现继承,但它也存在一些问题。其中,最主要的问题来自包含 * 引用类型值的原型。 * 引用类型值的属性会被所有的实例共享,所以一般会将它放在构造函数中,而不是放在原型对象中。但 * 通过原型来实现继承时,原型实现上会变成另一个类型的实例。原先的实例属性也就顺理成章地变成了现在的原型属性 * 2:在创建子类型的实例时,没有办法在不影响所有对象实例的 * 情况下,给超类型的构造函数传递参数。 * 所以,实践中很少会单独使用原型链 */function SuperType(){this.colors=["red","blue","green"];}function SubType(){}SubType.prototype=new SuperType();var s1=new SubType();s1.colors.push("black"); //red,blue,green,blackalert(s1.colors);var s2=new SubType();alert(s2.colors);//red,blue,green,black
?
?
2:借用构造函数
?
/** *借用构造函数 *//** *构造函数刚好可以解决原型链继承所面临的两个问题。但是构造函数也有缺点。 * 方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法, * 对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑这些问题,构造函数实现继承也是很少单独使用的。 * */function SuperType(){this.colors=["red","blue","green"];}function SubType(){SuperType.call(this);}var s1=new SubType();s1.colors.push("black");alert(s1.colors); //"red,blue,green,black"var s2=new SubType();alert(s2.colors); "red,blue,green";
?
?
3:组合继承
?
/** *组合继承 * 将原型链和借用构造函数组合到一块。使用原型链实现对原型属性和方法的继承, * 而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数利用, * 又能够保证每个实例都有它自己的属性。 * * 组合继承的缺点: * 无论什么情况下,都会调用两次超类型的构造函数:一次是在创建类型原型的时候,另一个次是在子类型的构造函数内部。 * 不仅如此,超类型的属性会在子类型和原型里同时存在,这是没有必要的。 */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;}//继承方法SubType.prototype=new SuperType();SubType.prototype.sayAge=function(){alert(this.age);}var s1=new SubType("n",1);s1.colors.push("black");alert(s1.colors);//red,blue,green,blacks1.sayName();s1.sayAge();var s2=new SubType("Greg",2);alert(s2.colors);//red,blue,green,blacks2.sayName();s2.sayAge();
?
?
?
4:寄生组合式继承
?
/** *寄生组合式继承 * * 解决了组合继承的缺点,它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype * 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变; */function object(o){function F(){}Function.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);}
?
?
?
?
摘自《javascript?高级程序设计》
?
PS:关于寄生组合式继承,让我不自觉想到了甘露模型,因为太像勒。大概Nicholas C.Zakas写《javascript高级程序设计》前也像李战一样得到了观音的指点。