这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要为大家详细介绍了 JS 继承之借用构造函数继承和组合继承,感兴趣的小伙伴们可以参考一下
借用构造函数继承
在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数 (constructor stealing)的技术(有时候也叫做伪造对象或经典继承)。这种技术的基本思想相当简单,即在子类型构造函数的内部调用超类型构造函数。
基本模式
- function SuperType(){
- this.colors = ["red", "blue", "green"];
- }
- function SubType(){
- //继承了SuperType
- SuperType.call(this);
- }
- var instance1 = new SubType();
- instance1.colors.push("black");
- alert(instance1.colors); //"red,blue,green,black"
- var instance2 = new SubType();
- alert(instance2.colors); //"red,blue,green"
基本思想
借用构造函数的基本思想就是利用 call 或者 apply 把父类中通过 this 指定的属性和方法复制(借用)到子类创建的实例中。因为 this 对象是在运行时基于函数的执行环境绑定的。也就是说,在全局中,this 等于 window,而当函数被作为某个对象的方法调用时,this 等于那个对象。call 、apply 方法可以用来代替另一个对象调用一个方法。call、apply 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
所以,这个借用构造函数就是,new 对象的时候 (注意,new 操作符与直接调用是不同的,以函数的方式直接调用的时候,this 指向 window,new 创建的时候,this 指向创建的这个实例),创建了一个新的实例对象,并且执行 SubType 里面的代码,而 SubType 里面用 call 调用了 SuperTyep,也就是说把 this 指向改成了指向新的实例,所以就会把 SuperType 里面的 this 相关属性和方法赋值到新的实例上,而不是赋值到 SupType 上面。所有实例中就拥有了父类定义的这些 this 的属性和方法。
优势
相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数。因为属性是绑定到 this 上面的,所以调用的时候才赋到相应的实例中,各个实例的值就不会互相影响了。
例如:
- function SuperType(name){
- this.name = name;
- }
- function SubType(){
- //继承了SuperType,同时还传递了参数
- SuperType.call(this, "Nicholas");
- //实例属性
- this.age = 29;
- }
- var instance = new SubType();
- alert(instance.name); //"Nicholas";
- alert(instance.age); //29
劣势
如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。
组合继承
组合继承(combination inheritance),有时候也叫做伪经典继承。是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
基本思想
思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。
基本模型
- 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.constructor = SubType;
- SubType.prototype.sayAge = function(){
- alert(this.age);
- };
- var instance1 = new SubType("Nicholas", 29);
- instance1.colors.push("black");
- alert(instance1.colors); //"red,blue,green,black"
- instance1.sayName(); //"Nicholas";
- instance1.sayAge(); //29
- var instance2 = new SubType("Greg", 27);
- alert(instance2.colors); //"red,blue,green"
- instance2.sayName(); //"Greg";
- instance2.sayAge(); //27
优势
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继承模式。
劣势
组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。虽然子类型最终会包含超类型对象的全部实例属性,但我们不得不在调用子类型构造函数时重写这些属性。
来源: http://www.phperz.com/article/17/0629/332036.html