提高JavaScript中工厂模式的存储效率
JavaScript“对象”(实际上是一个映射)概念的简单性和灵活性一直吸引着我。因此,我宁愿完全避免“对象原型”(以及“类”,它们只是对象原型的语法糖)的概念,而选择工厂模式 我偶然看到这篇文章,指出与工厂模式相比,对象原型可以节省内存: “所有方法将在prototype对象中仅创建一次,并由所有实例共享” 假设我有一个网页,它多次调用以下函数来“实例化”许多AnglePointer对象:提高JavaScript中工厂模式的存储效率,javascript,performance,memory,prototype,factory,Javascript,Performance,Memory,Prototype,Factory,JavaScript“对象”(实际上是一个映射)概念的简单性和灵活性一直吸引着我。因此,我宁愿完全避免“对象原型”(以及“类”,它们只是对象原型的语法糖)的概念,而选择工厂模式 我偶然看到这篇文章,指出与工厂模式相比,对象原型可以节省内存: “所有方法将在prototype对象中仅创建一次,并由所有实例共享” 假设我有一个网页,它多次调用以下函数来“实例化”许多AnglePointer对象: var AnglePointer = function() { var privateMembe
var AnglePointer = function() {
var privateMembers = {};
privateMembers.angle = 0;
var self = {};
self.turn = function(degrees) {
privateMembers.angle += degrees;
while (privateMembers.angle > 359) {
privateMembers.angle -= 360;
}
while (privateMembers.angle < 0) {
privateMembers.angle += 360;
}
};
return self;
};
var AnglePointer=function(){
var privateMembers={};
privateMembers.angle=0;
var self={};
自转=功能(度){
privateMembers.angle+=度;
while(privatembers.angle>359){
privateMembers.angle-=360;
}
while(privatembers.angle<0){
privateMembers.angle+=360;
}
};
回归自我;
};
我是否可以通过引入如下“共享”对象来提高内存效率
var AnglePointer = (function() {
var sharedMembers = {};
sharedMembers.turn = function(self, privateMembers, degrees) {
privateMembers.angle += degrees;
while (privateMembers.angle > 359) {
privateMembers.angle -= 360;
}
while (privateMembers.angle < 0) {
privateMembers.angle += 360;
}
};
return function() {
var privateMembers = {};
privateMembers.angle = 0;
var self = {};
self.turn = function(degrees) {
shared.turn(self, privateMembers, degrees);
};
return self;
};
})();
var AnglePointer=(函数(){
var sharedMembers={};
sharedMembers.turn=函数(自身、私有成员、度){
privateMembers.angle+=度;
while(privatembers.angle>359){
privateMembers.angle-=360;
}
while(privatembers.angle<0){
privateMembers.angle+=360;
}
};
返回函数(){
var privateMembers={};
privateMembers.angle=0;
var self={};
自转=功能(度){
共享。旋转(自身、私人成员、学位);
};
回归自我;
};
})();
在第二个版本中,turn
函数的实现在sharedMembers
对象中,AnglePointer的每个“实例”只剩下一个调用共享函数的小单行函数。这将实现类似于对象原型的内存效率吗?或者每个实例的turn
函数是否会像以前一样占用大量内存(尽管是单行函数)?如果是后者,对象原型如何避免这个问题
只有一个小的单行函数调用共享函数
这是基于一种错误的信念,即将为每个对象创建一个新函数。这是错误的。代码中的所有函数只解析一次,并且只存在一次。每次创建时都会创建一个新的闭包(规范称之为EnvironmentRecord)。如果函数不访问任何外部变量,则可以优化此闭包,使其内存效率更高(可能更快)
因此,你的“新模式”实际上让事情变得更糟(但只是一点点)。主要问题在于:
self.turn = function(degrees) {
shared.turn(self, privateMembers, degrees);
};
这是无法优化的,因为函数使用来自其父范围的变量,因此必须创建一个闭包。因此,每个turn
方法都必须有一个闭包,每个对象都必须保留一个对自己的closuredturn
的引用
私有成员可以通过符号非常准确地实现:
const angle = Symbol.for("angle");
function AnglePointer() {
return {
[angle]: 0,
turn(degrees) {
this[angle] = (this[angle] + degrees) % 360;
},
};
}
这里的
turn
可以共享,因为它不访问任何外部变量。您对如何在对象原型中避免这个问题有什么见解吗?给定一个对象原型的实例,该实例如何调用共享函数并传递其自身的内部状态,而不将其包装到另一个函数中?@circuitsolar使用原型时,只有一个闭包(或者根本没有闭包)。把this
想象成一个隐式参数,你可以只做function-turn(this,degrees){/*…*/}
并把它称为turn(someInstance,90)
这很有趣,人们经常会问这个新关键字在JavaScript中到底做了什么,我从未见过这样的例子——将其作为隐式参数传递给对象中定义的任何函数。所以有趣的是,解决这个问题的一个(乏味的)方法是将这个责任明确地写进代码中。AnglePointer可以将其turn函数定义为turn(anglePointerInstance,degrees)
,任何时候外部代码实例化AnglePointer并需要转动它时,它都类似于myInstance=AnglePointer();myInstance.turn(myInstance,45)代码>