本文适合有C++面向对象编程经验的人。
声明:本文整理自JS高级编程,我本人没有任何原创性。
JS用蹩脚的方式实现了面向对象的特性,虽然不喜欢,然而不得不用JS,只好也就接受这种方式。(JS面向对象像XX,既然无力反抗,就尽情享受吧)
JS的继承有多种方式,不同方式解决了不同的问题。
JS有一个核心原则,保证函数在实例(instance)中共享,而数据不共享。要做到这一点,则函数需要添加到prototype上,而数据则应在构造函数内部。
(为什么函数要在实例中共享?而为什么数据不要共享?
1.函数在JS中是对象,是占用内存空间的,最好只有一份。这一点和C语系的语言不同。C语系的函数随便定义,不占内存,反正只是执行过程。
2.数据如果共享了,则在实例中数据就会互相影响,这是我们不想看到的,C++类的数据都是一个实例保存一份,所以JS中也需要做出这种效果。
)
1.原型链继承
这是最原始的方式,没有做一点优化。
function SuperType(){}
function SubType(){}
SubType.prototype = new SuperType();
这里使得父类的实例成为子类的原型,子类的实例则都可以访问到父类定义的函数。
然而这样是会产生问题的。根据上边所说的核心原则,应该函数共享,数据不共享,而原型链继承这种原始的继承方式会导致父类数据也变成共享的了。(思考:数据怎么成共享的了?)
而且这种继承还有一个缺点,子类无法向父类构造函数传参(向父类传参还是很有必要的,想想C++就知道)。
2.借用构造函数法
function SuperType(name){
this.name = name;
this.func = function(){}
}
function SubType(name){
SuperType.call(this,name);
}
var instance = new SubType();
缺点:函数无法复用。
3.组合继承
将原型链法和借用构造函数法组合起来。采二者之长,规避二者之短。
function SuperType(name){
this.name = name;
this.func = function(){}
}
function SubType(name){
SuperType.call(this,name);
}
SubType.prototype = new SuperType();
var instance = new SubType();
而JS精粹作者提出的两种方式我觉得都不好,增加记忆负担和思维负担。
感觉他本人比较喜欢奇技淫巧,换句话说就是不朴实,虽然书写的不错,但是好多东西都增加思维负担。我一直觉得编程应该是自由的,少点条条框框反而会提升更快。我比较喜欢原理性文章,却讨厌一直被人教导你应该这样做那样做,然而并没有本质上的区别和性能上的提升。
网友评论