当我们定义一个在对象或全局范围内的函数时,javascript函数是否存储在内存中一次。
function (){
alert("some value");
}
obj = {
m: function(){
alert('some value');
}
}
答案 0 :(得分:2)
很难说出你在问什么,但我看到两个可能的问题,因此有两个答案:
每次执行您定义的执行上下文时,都会创建一次JavaScript函数。因此,如果该上下文是全局的(在任何函数之外),是的,每个声明或表达式将只创建一个函数。如果该上下文在函数内,则每次调用函数时都会定义它们。
例如,如果这是一个全局范围:
function foo() { }
...只会创建一个。相比之下,这样的事情:
function bar() {
return {
foo: function() { }
};
}
...创建一个新函数,并在每次调用 foo
时将其分配给返回对象上的bar
属性。 (这并不意味着智能JavaScript引擎无法共享它们的底层代码 - 我告诉那些声称知道V8 [Chrome和其他地方的引擎]确实重用代码的人 - 但是他们'将是单独的函数对象。)
每个函数声明或表达式都创建自己的函数;如果你有两个等效的声明或表达式,它们会创建两个函数,即使它们是等效的。这并不意味着智能JavaScript引擎无法共享底层代码,但您仍将拥有两个独立的函数对象。
例如:
var a = function() { };
var b = function() { };
console.log(a === b); // "false"
// Adding a property to `a`, since functions are objects, demonstrates
// further that they are not the same function object
a.foo = "bar";
console.log(a.foo); // "bar"
console.log(b.foo); // "undefined"
答案 1 :(得分:2)
如果你定义了一次函数,并将该函数的引用传递给不同的变量/属性,那么是的,它存储了一次。
var one_func = function () { console.log("I'm just one function."); };
var reused = one_func;
var reuser = { func : reused };
所有这些都有指向相同功能的指针。
但如果你有这样的事情:
var Circle = function (r) {
var circle = {
radius : r,
calculate_area : function () { return 2 * Math.PI * r; }
};
return circle;
};
var circle_1 = Circle(2),
circle_2 = Circle(4);
这两个对象不共享calculate_area
您已经创建了两个不同版本的函数。
由于功能范围和封闭,它们必须保持清晰
请参阅,每个副本都知道自己的圈子r
。
如果您注意到,我不是在看circle.radius,我正在查看传递到r
函数的Circle
。
因此Circle
中 中定义的任何函数必须每次都是新的,因为这些函数保存对构造函数内部任何变量的引用,通过关闭。
拥有多个副本的记忆力与拥有完全私有属性的好处是值得的,直到你获得成千上万的副本(除非我们谈论巨大的对象或可怕的旧浏览器,或运行JavaScript在烤面包机的LED屏幕上。)
更高级的引擎可能会在这里优化内存占用,但考虑到这些功能占用的内存很少,以及智能手机拥有多少RAM(更不用说定制的游戏PC),因此很少浪费CPU。
修改强>
为了迂腐
var Wallet = function (opening_balance) {
var balance = opening_balance,
overdraft = 50,
is_sufficient_funds = function (amount) {
return balance + overdraft >= amount;
},
deposit = function (funds) {
if (amount <= 0) { return; }
balance += funds;
},
withdraw = function (amount) {
if (amount <= 0) { return; }
if (is_sufficient_funds(amount)) {
balance -= amount;
return amount;
}
},
public_interface = {
deposit : deposit,
withdraw : withdraw
};
return public_interface;
};
现在,我们不希望在balance
的任何情况下公开访问overdraft
或Wallet
,这应该是非常明显的。
即使是行人版的钱包也非常安全。
当然,它现在没有做任何授权,所以你可以扣除所有东西,或者增加一百万美元......
...但你可以将透支额定为300美元吗?
您可以手动复制balance
的价值吗?
即使您创建了var wallet = Wallet(35);
然后尝试重写deposit
方法,您对其的重写也绝对无法访问私有balance
。
现在,这种内存开销的封闭相关好处应该是显而易见的。
如果您愿意,可以在多人游戏中考虑枪的射速 或者角色的动作 或者他们的健康 或高分。
通过将所有这些东西封装在封闭物中,它们是不可靠的 这并不意味着服务器无法解决 但这确实意味着人们可以少进入一个地点,而无需从头开始重写引擎。
答案 2 :(得分:0)
没有。匿名函数
function(){
alert("some value");
}
不与对象文字obj
内的匿名函数相同。
要确保“回收”存储的对象或函数,请执行以下操作:
var f = function(){ alert('test') };
obj = {
m: f
}