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イベントのハンドラーは1回作成されますが、、、およびのハンドラーは接続ごとに作成されるaction1と思います。他の質問では、これは名前付き関数で解決されましたが、これがV8で必要かどうか、またはいくつかの最適化を行うかどうかに興味があります。action2disconnect

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 によって完全に有効で正しく処理される、名前付きの関数式を使用します。(残念ながら、まったく異なるタイミングで 2 つのまったく異なる関数を作成するIE8 以前では正しく処理されません。しかし、V8 を使用しているので、そのことを心配する必要はありません。)

于 2012-04-15T07:41:49.123 に答える