下面我在JavaScript中有一个简单的小继承链:
var Base =(function(){
function Base(config){
this.name = function(){
return config.name;
}
this.department = function(){
return config.department;
}
}
Base.prototype.calculate = function(){
return this.name().length + this.department().length;
}
return Base;
})();
var base = new Base({
name: 'me',
department: 'this one'
});
console.log(base.calculate());
//inheritance
var Concrete = (function(){
Concrete.prototype = Base.prototype;
function Concrete(config){
Base.apply(this,arguments);
this.number = function(){
return config.number;
}
}
return Concrete;
})();
var concrete = new Concrete({
name: 'concrete',
department: 'the best',
number: 3
});
console.log(concrete.number()); //3
console.log(concrete.name()); //concrete
它按预期工作。我很好奇,但是在对象的原型上放置方法属性是多么正确。通常我知道实例数据应该与类的实例一起使用,对象实际使用的方法应该在原型上,但是属性本身是方法的情况如何(比如本例中的Base中的名称和部门)?为了保持不变,我宁愿不让用户在初始化之后更改其中一个对象的属性。在这种情况下,使用原型而不是构造函数向对象添加功能是否有意义?
或者只在构造函数中放置属性是正确的,这样当你执行Base.prototype.whatever之类的操作时就可以访问它们了吗?
答案 0 :(得分:1)
属性本身是方法的情况怎么样?为了保持不可变性,我不应该让用户在初始化之后更改其中一个对象的属性。
我不打电话给这些"属性"更多,但"访问者"或者" getter"方法
在这种情况下,使用原型而不是构造函数向对象添加功能是否有意义?
是的,如果您的意思是calculate
这样的功能。如果您指的是name
,department
或number
之类的getter,则需要将它们放置在构造函数中,因为它们需要对config
的特权访问权限。
通常我知道实例数据应该与类的实例一起使用,对象实际使用的方法应该在原型上
实际上有点不同:
Concrete.prototype = Base.prototype;
No!请改用Concrete.prototype = Object.create(Base.prototype);
。
答案 1 :(得分:1)
你问题的标题有点误导。
直接回答您的标题 - 是的,鼓励原型属性。他们在编写代码和代码的使用方面可能没有太大区别,但在内部,JS如何管理事物,如内存,访问闭包内的变量等,通过原型属性完成后更好。
现在您的实际问题是,使用闭包和私有范围变量隐藏不可变配置是唯一的方法吗?
现在 - 我想是的,因为ES6仍然不是每个浏览器都完全支持。
但很快,支持将在所有发布版本的浏览器中展开,然后您可以使用这个漂亮的ES6数据类型WeakMap
。就像Map
一样,但这里的键是对象。所以您的Base定义可以写成:
var Base = (function() {
var properties = new WeakMap(); // You have to keep variable private
function Base(config) {
properties.set(this, config);
}
Base.prototype = {
name: function() {
return properties.get(this).name;
},
department: function() {
return properties.get(this).department;
},
calculate: function() {
return this.name().length + this.department().length;
}
};
return Base;
})();
是的,您仍然需要保持变量属性不可及,因此外部封闭。但在这种情况下,关闭的数量减少了1个。
类似的方法可以用于ES6 Symbol,但外部闭包仍然是必需的。
我们真正需要的是真正解决问题的课程,正如这篇写得非常好的blog
所解释的那样。