函数只存储在内存中一次吗?

时间:2013-02-18 09:43:20

标签: javascript function

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

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

    function foo() { }
    

    ...只会创建一个。相比之下,这样的事情:

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

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

  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"
    

答案 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的任何情况下公开访问overdraftWallet,这应该是非常明显的。

即使是行人版的钱包也非常安全。

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

...但你可以将透支额定为300美元吗?

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

即使您创建了var wallet = Wallet(35);然后尝试重写deposit方法,您对其的重写也绝对无法访问私有balance

现在,这种内存开销的封闭相关好处应该是显而易见的。

如果您愿意,可以在多人游戏中考虑枪的射速 或者角色的动作 或者他们的健康 或高分。

通过将所有这些东西封装在封闭物中,它们是不可靠的 这并不意味着服务器无法解决 但这确实意味着人们可以少进入一个地点,而无需从头开始重写引擎。

答案 2 :(得分:0)

没有。匿名函数

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

与对象文字obj内的匿名函数相同。

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

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

obj = {
    m: f
}