Javascript:对象复制、全局变量和性能

发布于 2024-12-08 15:42:16 字数 926 浏览 0 评论 0原文

我有一个非常复杂的问题要问:)

我目前正在开发 html5 画布游戏。特定于游戏地图的变量位于与游戏引擎分开的单独文件(我们称之为 game.js)中(我们称之为 engine.js)。

我读到在 JS 中使用全局变量比局部变量慢。因此,在 game.js 中,我创建了一个全局变量,其中包含所有特定于游戏的变量。在engine.js中,我将这个全局对象复制到局部变量,然后删除这个全局对象。

这是有效的。但我知道分配对象仅传递对这些对象的引用。

因此我的问题是:当我在初始化结束时删除全局对象时,它的性能是否会像我直接将所有变量声明为 engine.js 中的局部变量一样,还是会变慢,就像我的engine.js 中的局部变量只是对全局对象的引用?

我可以在 engine.js 中将所有变量声明为本地变量,但如果以后我想制作其他地图/游戏,那么分离特定于地图的内容对我来说会很有用。

例如:

game.js:

Game = function() {
this.x = 16;
this.y = 16;
this.myObject = {"test": "hello", "action": "none"};
}
game = new Game();

engine.js: //...

var x = game.x;
var y = game.y;
var obj = {"test": game.myObject.test, "action": game.myObject.action};

//...

在这个例子中,x、y 和 obj 的性能会与局部变量一样快,还是更慢?

注意:我并没有真正检查全局变量和局部变量之间的性能差异,但我认为我读到的内容是正确的。

希望我的问题足够清楚而不是愚蠢:)如果您有任何想法......谢谢!

I have a quite complicated question to ask :)

I am currently working on a html5 canvas game. The variables which are specific to a map of the game are in a separate file (let's call it game.js), separated from the game engine (let's call it engine.js).

I have read that global variables are slower to use in JS than local variables. Therefore, in game.js, I create a global variable which contains all the game-specific variables. In engine.js, I copy this global object to local variables, there I delete this global object.

This is working. But I know that assigning objects only pass a reference to these objects.

Therefore my question is: will the performance of that be as if I had declared all the variables directly as local variables in engine.js, as I delete the global object at the end of the initialisation, or will it be slower, as if my local variables in engine.js were just references to a global object?

I could declare all the variables as local in engine.js, but it would be useful for me to separate what is specific to the map, if later I want to make other maps/games.

For example:

game.js:

Game = function() {
this.x = 16;
this.y = 16;
this.myObject = {"test": "hello", "action": "none"};
}
game = new Game();

engine.js:
//...

var x = game.x;
var y = game.y;
var obj = {"test": game.myObject.test, "action": game.myObject.action};

//...

In this example, will the performance of x, y and obj be as fast as local variables, or slower?

Note: I didn't really check the difference between performances of global vars, and local vars, but I assume what I read about it is right.

Hope my question was clear enough and not silly :) If you have any ideas... Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春花秋月 2024-12-15 15:42:16

在现代浏览器中,局部变量和全局变量之间可能没有太大的性能差异。

但是,存在内存消耗问题 - 只要页面保持打开状态,全局变量就会持续存在,而局部变量则 控制离开其范围后收集的垃圾。使用局部变量可以减少内存泄漏的可能性。

更新

评论线程中的冗长讨论促使我编写一个测试脚本来测量对比全局和本地范围访问的执行速度差异。

最初似乎没有什么区别,结果也各不相同,对其中之一没有特定的偏好。然而@DaveNewton 提供了一个反例,它始终显示局部变量的性能提高了一个数量级。


火狐7

20000 次全局访问所用的毫秒数:132

20000次本地访问所用的毫秒数:159

Internet Explorer 9

20000 次全局访问所用的毫秒数:1750

20000次本地访问所用的毫秒数:1699

Google Chrome 14

20000 次全局访问所用的毫秒数:46

20000次本地访问所用的毫秒数:55

测试脚本本身

<html>
<head>
<script type="text/javascript">

function t() {

var test = function () {}
test.issue = new String("hello");

var start = new Date().getTime();
(function() {
    (function() {
        (function() {
            (function() {
                (function() {
                    (function() {
                        (function() {
                            var a = document.getElementById("a");
                            for (var i = 0; i < 20000; i++) {
                                a.innerHTML = test.issue.toString();
                            }
                            a = null;
                        })();
                    })();
                })();
            })();
        })();
    })();
})();
var stop = new Date().getTime();
document.getElementById("a").innerHTML = "Milliseconds used for 20000 global accesses: " + (stop - start);


var start = new Date().getTime();
(function() {
    (function() {
        (function() {
            (function() {
                (function() {
                    (function() {
                        (function() {
                            var c = document.getElementById("c");
                            var testx = {};
                            testx.issue = new String("hello");
                            for (var i = 0; i < 20000; i++) {
                                c.innerHTML = testx.issue.toString();
                            }
                            c = null;
                        })();
                    })();
                })();
            })();
        })();
    })();
})();
var stop = new Date().getTime();
document.getElementById("c").innerHTML = "Milliseconds used for 20000 local accesses: " + (stop - start);

}

window.onload = function () {
    document.getElementById('b').onclick = t;
}

</script>
</head>
<body>
<div align="center"><button id="b">Run Test</button></div>
<div id="a"></div>
<div id="c"></div>
</body>

</html>

一个反例,演示对局部变量的更快访问。

var t0 = new Date();
var i; 
for (i=0; i<10000000; i++); 
var t1 = new Date(); 
function count() { for (var i=0; i<10000000; i++); } 
var t2 = new Date(); 
count(); 
var t3 = new Date(); 
d = document; 
d.write('Without local variables = ', t1-t0, '<br />'); 
d.write('With local variables = ', t3-t2, '<br />');

In modern browsers, there probably isn't much performance difference between local and global variables.

However there is an issue with memory consumption - global variables persist as long as the page stays open whereas local variables are garbage collected after control leaves their scope. Using local variables reduces the chance of having a memory leak.

Update

The long-winded discussion in the comment thread prompted me to write a test script to measure execution speed differences contrasting global and local scope access.

Initially there seemed to be no difference and results vary with no specific preference towards one or the other. However @DaveNewton provided a counterexample which consistently shows better performance for local variables by an order of magnitude.


Firefox 7

Milliseconds used for 20000 global accesses: 132

Milliseconds used for 20000 local accesses: 159

Internet Explorer 9

Milliseconds used for 20000 global accesses: 1750

Milliseconds used for 20000 local accesses: 1699

Google Chrome 14

Milliseconds used for 20000 global accesses: 46

Milliseconds used for 20000 local accesses: 55

Test script itself

<html>
<head>
<script type="text/javascript">

function t() {

var test = function () {}
test.issue = new String("hello");

var start = new Date().getTime();
(function() {
    (function() {
        (function() {
            (function() {
                (function() {
                    (function() {
                        (function() {
                            var a = document.getElementById("a");
                            for (var i = 0; i < 20000; i++) {
                                a.innerHTML = test.issue.toString();
                            }
                            a = null;
                        })();
                    })();
                })();
            })();
        })();
    })();
})();
var stop = new Date().getTime();
document.getElementById("a").innerHTML = "Milliseconds used for 20000 global accesses: " + (stop - start);


var start = new Date().getTime();
(function() {
    (function() {
        (function() {
            (function() {
                (function() {
                    (function() {
                        (function() {
                            var c = document.getElementById("c");
                            var testx = {};
                            testx.issue = new String("hello");
                            for (var i = 0; i < 20000; i++) {
                                c.innerHTML = testx.issue.toString();
                            }
                            c = null;
                        })();
                    })();
                })();
            })();
        })();
    })();
})();
var stop = new Date().getTime();
document.getElementById("c").innerHTML = "Milliseconds used for 20000 local accesses: " + (stop - start);

}

window.onload = function () {
    document.getElementById('b').onclick = t;
}

</script>
</head>
<body>
<div align="center"><button id="b">Run Test</button></div>
<div id="a"></div>
<div id="c"></div>
</body>

</html>

A counter-example, demonstrating faster access to local variables.

var t0 = new Date();
var i; 
for (i=0; i<10000000; i++); 
var t1 = new Date(); 
function count() { for (var i=0; i<10000000; i++); } 
var t2 = new Date(); 
count(); 
var t3 = new Date(); 
d = document; 
d.write('Without local variables = ', t1-t0, '<br />'); 
d.write('With local variables = ', t3-t2, '<br />');
我要还你自由 2024-12-15 15:42:16

您所谈论的性能差异的原因在于 javascript 将变量名称解析为其引用的值的方式。因此(可忽略不计的)时间延迟是 JavaScript 查找变量的结果。当通过引用某物来分配某物时,它是指内存中的实际值而不是名称。

例如,假设您有一个名为 info 的 javascript 变量,其值为 { Question: null,answer: 42 }。如果您要进行分配,

info2 = info;

您将告诉 javascript 立即查找该值,并在引用 info2 时使用它。现在 infoinfo2 都指向相同的值(相同的内存地址)。您没有告诉javascript查找引用info并在每次使用info2时获取该值。这意味着您这样做的方式很好,因为您只需查找全局变量引用一次。

请注意,javascript 只会通过引用来分配非常量,因此:

var a = 1;
var b = a;
var a = 2;
var b === 1; // => true

var z = { a: 1 };
var y = z;
z.a = 2;
y.a === 2; // => true

原始值是常量,对象不是。

The reason for the performance difference you are talking about lies in the way javascript resolves the name of a variable to the value it refers to. So the (negligible) time lag is the result of javascript looking up the variable. When something is assigned by reference to something, it is in reference to the actual value in memory rather than the name.

For example, imagine you have a javascript variable called info with the value of { question: null, answer: 42 }. If you were to make the assignment

info2 = info;

You are telling javascript to find that value right now and use it when referring to info2. Now both info and info2 are pointing to the same value (the same memory address). You are not telling javascript to look up the reference info and get that value every time you use info2. This means that the way you are doing it is fine, since you are only looking up the global variable references once.

Note that javascript will only assign by reference for non-constants, so:

var a = 1;
var b = a;
var a = 2;
var b === 1; // => true

var z = { a: 1 };
var y = z;
z.a = 2;
y.a === 2; // => true

Primitive values are constants, objects are not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文