11

有关完整的故事,请查看我的另一个问题

基本上,我问过在套接字处理程序中为以下代码使用命名函数是否更有效:

var app = require('express').createServer()
var io = require('socket.io').listen(app);

app.listen(8080);

// Some unrelated stuff

io.sockets.on('connection', function (socket) {
    socket.on('action1', function (data) {
        // logic for action1
    });

    socket.on('action2', function (data) {
        // logic for action2
    });

    socket.on('disconnect', function(){
        // logic for disconnect
    });
});

总体答案是肯定的(有关更多详细信息,请参见上面的链接),但ThiefMaster发表了以下评论:

我不熟悉 V8 内部结构,但它可能足够聪明,可以编译一次函数并每次都重新使用它,只是附加了不同的范围。

所以现在这是我的问题。V8 是否足够聪明,可以编译一次匿名函数,并在匿名函数通常会导致创建多个函数实例的情况下以不同的范围重用它们?例如,上面我希望connection事件的处理程序只创建一次,但为每个连接创建action1action2和的处理程序。disconnect在另一个问题中,这是通过命名函数解决的,但我更感兴趣的是在 V8 中是否需要这样做,或者它是否会进行一些优化。

4

1 回答 1

9

是的。我在 V8 邮件列表上问了一个非常相似的问题(在我的例子中与从构造函数中创建函数有关)。我得到的答复是函数的代码是“......通常重用......”,即使每次都有一个单独的函数对象(根据规范的要求)。


但请注意,您的问题与函数是命名还是匿名无关。您示例中的函数可能有一个名称:

io.sockets.on('connection', function handleConnection(socket) {
    socket.on('action1', function (data) {
        // logic for action1
    });

    socket.on('action2', function (data) {
        // logic for action2
    });

    socket.on('disconnect', function(){
        // logic for disconnect
    });
});

这使用了一个命名函数表达式,它完全有效并且由 V8 正确处理。(遗憾的是,IE8 和更早版本没有正确处理它,它们在完全不同的时间创建了两个完全不同的功能。但是当您使用 V8 时,您不必担心这一点。)

于 2012-04-15T07:41:49.123 回答