本文对比了JavaScript中定义类的两种常见方式。第一种直接重写prototype对象会导致内置方法丢失;第二种通过内部函数返回类的方式实现了私有变量封装,同时避免了原型链被完全覆盖的问题,有助于理解JavaScript的面向对象编程机制。
JavaScript定义类的常见写法
以往在JavaScript中定义类时,我通常采用如下写法:
function Dog(){
this.name = 'hachi';
}
Dog.prototype = {
makeNoise:function(){
alert('wangwangwang');
}
};
复杂封装写法示例
随后,我又接触到另一种更为复杂、看似多余的实现方式:
function Dog(){
var privateVariable = 'secret';
var fn = function(){
//...
}
fn.prototype = {
makeNoise:function(){
alert('wangwangwang');
}
}
return fn;
}
私有变量与封装优势
这里的Dog函数实际上是一个用于生成类的工厂函数,它返回了真正的Dog类。这种写法的好处在于能够更好地实现封装。例如,这里的privateVariable就是一个私有变量:
var d = new Dog;
d.privateVariable //undefined
直接重写prototype的风险
此外,如果在第一种例子的最后添加如下代码:
Dog.prototype = {
//e...WTF??
}
这会导致Dog类的原型被意外覆盖,从而破坏原有功能。
原型链保留与改进方案
经过进一步理解发现:上述第一种新建类的方法直接重写了prototype对象,导致arguments、call、apply等内置属性丢失。相比之下,第二种新建类的方法似乎更为合理:
var Dog = function(name){
this.name = name;
var privateVariable = 'you cannot see me.';
this.getPrivate = function(){return privateVariable;};
}