列出类似问题清单:
我得出结论,在JS中实现类和实例有两种可能的方法:使用内部函数或使用原型。
因此,我们假设我们在命名空间 BOX_LOGIC 中有一个 Box 类,其中包含一个简单的代码。我可以编写以下代码:
BOX_LOGIC.Box = (function() {
// private static
var boxCount = 0;
var classDefinition = function(x) {
x = x || 0;
var capacity = x;
var id = ++boxCount;
// public methods
this.getCapacity = function() { return capacity; };
this.getId = function() { return id; };
this.add = function(weight) {
weight = weight || 0;
if (capacity >= weight) {
capacity -= weight;
}
return capacity;
};
};
return classDefinition;
})();
我能够编码:
BOX_LOGIC.Box = (function () {
var boxCount;
var Box= function (x) {
x = x || 0;
this.capacity = x;
this.id = ++boxCount;
};
Box.prototype = {
Constructor: Box,
add: function (weight) {
weight = weight || 0;
if (this.capacity >= weight) {
this.capacity -= weight;
}
return this.capacity;
}
};
return Box;
})();
Mi问题是:使用 Box原型的不同之处是什么?是出于任何原因(成本,易读性,标准......)更好的方法吗?
在第二种方法中是否有任何方式来模拟static id
变量? THX!
答案 0 :(得分:1)
Mi问题是:使用Box原型的不同之处是什么?
是出于任何原因(成本,易读性,标准......)更好的方法吗?
原型上的函数(和其他属性)在实例之间是共享;如果你在构造函数中创建它们,每个实例都会获得所有这些函数的自己的副本。
主要的好处是你可以添加到原型,甚至已经存在的实例看到添加,因为他们动态地使用原型。特别是,这可以帮助进行面向方面的编程和各种调试和日志记录技术,因为您可以动态地将函数包装在原型上以捕获调用。当每个实例都有自己的实例时,你不能这样做(除非你有一个对每个实例的引用,这是不可能的)。
理论上,使用原型还意味着更低的内存消耗。在实践中,你必须有数百万个实例需要关注,现代引擎擅长重用函数的底层代码,即使涉及的函数对象是不同的。
因此,除非您要动态扩充原型,否则其中一个主要是一种风格问题。
第二种方法是否可以模拟静态
id
变量?
我不会把它称为静电;"它是每个实例的私有。使用原型方法(即几乎私有的信息原型函数可以访问),有多种方法可以关闭私有信息,但是真正无法实现获取私有信息的原型函数可以访问。 ES7中可能会有(不是ES6,目前正在最终确定; ES7)。我解决了其中一个近私人机制in this blog post。该帖子中的ES6信息现已过期;隐私的东西被推回到ES7,并且"私人Name
"对象变为Symbol
,根本不提供真正的隐私。
我应该标记你的第三个选项,你现在可以使用ES6转换器:ES6' class
:
// This is similar to the prototype version; `getCapacity` and
// `add` end up on `Box.prototype`
BOX_LOGIC.Box = (function () {
class Box {
constructor() {
x = x || 0;
this.capacity = x;
}
getCapacity() {
return this.capacity;
}
add(weight) {
weight = weight || 0;
if (this.capacity >= weight) {
this.capacity -= weight;
}
return this.capacity;
}
}
return Box;
})();
旁注:因为您正确地使用了""在你的标题中,我会在你的原型示例中标出一个非常小的东西:你正在弄乱constructor
属性。默认情况下,Box.prototype
有一个属性constructor
,它返回Box
。但是,通过使用完全不同的对象替换 Box.prototype
上的对象,您可以删除它。为了与标准功能保持一致,我将对其进行修改:
Box.prototype = {
constructor: Box,
//...the existing stuff goes here...
};
重要吗?只有当您最终得到依赖于constructor
属性的代码(以及某些库可能)时。尽管JavaScript规范定义了属性,但JavaScript本身没有任何功能。