1

当我们在对象或全局中定义一个函数时,javascript函数是否存储在内存中。

function (){
alert("some value");
}

obj = {
 m: function(){
   alert('some value');
   }
}
4

3 回答 3

4

如果您定义一次函数,并将该函数的引用传递给不同的变量/属性,那么是的,它被存储一次。

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每次都必须是新的,因为这些函数通过闭包保存对构造函数内部任何变量​​的引用。

拥有多个副本的内存打击,与拥有完全私有属性的好处相比,这是非常值得的,直到你达到成千上万个副本(除非我们谈论的是巨大的对象或可怕的旧浏览器,或者在 LED 上运行 JavaScript烤面包机上的屏幕)。

更高级的引擎可能会在这里优化内存占用,但考虑到每个功能占用的内存很少,以及智能手机有多少 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;
};

现在,我们不希望balanceoverdraft在任何Wallet.

即使是这个行人版的钱包也相当安全。

当然,它现在没有做任何授权,所以你可以扣除一切,或者增加一百万美元......

...但是您可以将透支设置为 300 美元吗?

您可以手动复制 的值balance吗?

即使您创建var wallet = Wallet(35);然后尝试重写该deposit方法,您对它的重写也将绝对无法访问 private balance

现在,这种内存开销与闭包相关的好处应该很明显了。

If you'd prefer, you could consider the rate of fire of a gun in a multiplayer game.
Or a character's movement.
Or their health.
Or high-scores.

By keeping all of these things encapsulated in closures, they're untweakable.
That doesn't mean that the server is unhackable.
But it does mean that there's one less spot for people to get in, without rewriting your engine from the ground up.

于 2013-02-18T10:05:29.337 回答
2

很难说出你在问什么,但我看到两个可能的问题,因此有两个答案:

  1. 每次执行您定义它的执行上下文时,都会创建一次 JavaScript 函数。因此,如果该上下文是全局的(在任何函数之外),是的,每个声明或表达式将只创建一个函数。如果该上下文在函数内,则每次调用函数时都会定义它们。

    例如,如果这是一个全局范围:

    function foo() { }
    

    ...只会创建其中一个。相比之下,像这样:

    function bar() {
        return {
            foo: function() { }
        };
    }
    

    ...创建一个新函数并将其分配给每次调用foo返回对象的属性。(这并不意味着智能 JavaScript 引擎不能为他们共享底层代码——有人告诉我,他们声称知道 V8(Chrome 和其他地方的引擎)确实重用了代码——但他们将是单独的函数对象。) bar

  2. 每个函数声明或表达式都创建自己的函数;如果你有两个等价的声明或表达式,它们会创建两个函数,即使它们是等价的。这并不意味着智能 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"
    
于 2013-02-18T09:44:56.180 回答
0

不,匿名函数

function(){
    alert("some value");
}

与对象字面量obj的匿名函数不同。

为确保您“回收”存储的对象或函数,请执行以下操作:

var f = function(){ alert('test') };

obj = {
    m: f
}
于 2013-02-18T09:48:52.493 回答