7

警告: 私はバックボーンの初心者です。

コレクション内のすべてのモデルを反復処理してレンダリングしています。簡単ですが、これがどのように機能するかをよく理解したいと思いました。これが私が持っているものです -

モデル:

File = Backbone.Model.extend({});

コレクション

Folder = Backbone.Collection.extend({ model: File });

モデルビュー

FileView = Backbone.View.extend({
    initialize: function() {
       _.bindAll(this, 'render');
       this.render();
    },
    render: function() {
        this.template = _.template(document.getElementById("fileTemplate").innerHTML);
        this.$el.html(this.template({ fileName: this.model.get("FileName") }));
    }   
})

コレクションビュー

FolderView = Backbone.View.extend({    
    initialize: function () {
        _.bindAll(this, 'render');
        this.render();
    },
    render: function () {
        _(this.collection.models).each(function(file) {
            var fileView = new FileView({ model: file});
            this.$el.append(fileView.el);            
        },this); <--???
    }
});

これは完全に正常に機能します。私の質問は、FolderView の _.each に関するものです。thisを each ループに戻す必要があるのはなぜですか? thisを渡さないと、コレクションではなくウィンドウ オブジェクトが参照されます。渡す必要があることはわかっていますが、理由がわかりません。

4

3 に答える 3

11

_.each(list, iterator, [context]) Alias: forEach

要素のリストを繰り返し処理し、それぞれを順番にイテ​​レータ関数に渡します。コンテキスト オブジェクトが渡された場合、反復子はコンテキスト オブジェクトにバインドされます。iterator の各呼び出しは、3 つの引数 (要素、インデックス、リスト) で呼び出されます。リストが JavaScript オブジェクトの場合、反復子の引数は (値、キー、リスト) になります。ネイティブの forEach 関数が存在する場合は、その関数に委譲します。

アンダースコア docs#each

デフォルトのコンテキストは window オブジェクトです。thisコンテキストになるように設定することで、関数が呼び出された場所にthis関数マップを作成します。this

このトピックについては、以下を参照してください。

于 2013-08-15T14:07:56.370 に答える
3

説明するには、最初に、JavaScript では関数のみが新しいスコープを作成すること (つまり、ループが実際に新しいスコープを作成するわけではない) と、他のいくつかの言語とは異なり、そのスコープのコンテキストは変更可能であることを認識する必要があります。そのスコープ内でthisと呼ばれるものは、異なるものを参照する可能性があります。

この結果、発生する一般的な問題は、内部関数と外部関数があり、内部関数内で外部関数のスコープを参照したいのに、内部関数がスコープを変更してthis参照できなくなるということです。外部関数。

これを処理するには、外側の関数のコンテキストを確実に保存する必要があります (より詳細な説明については、以下を参照してください)。

thisJavaScript で見られる一般的なパターンは、コンテキスト ( ) を変数に割り当て、それを関数内で使用することです。

たとえば、レンダリング関数は技術的に次のように書き直されている可能性があります

 render: function () {
       var self = this; 
        _(this.collection.models).each(function(file) {
            var fileView = new FileView({ model: file});
            self.$el.append(fileView.el);            
        });
    }

の基本的な理解を提供したのでthisUnderscore.jsの関数contextに目を向けることができます。_ .each は、 underscore.jsのほとんどの関数と同様に、underscore.js が使用するコンテキストを参照するオプションの 3 番目のパラメーターを取ります。そのコンテキストを簡単に参照できます。_.each

Underscore.js は 、コンテキストを関数にバインドするためのユーティリティ関数bindも提供します。

于 2013-08-15T14:09:38.423 に答える
0

元の質問は、「each(fn, this) 呼び出しで「this」をオーバーライドする必要があるのはなぜですか?」というものでした。

最初のパラメーターの無名関数を作成しています。デフォルトでは、関数内の「this」は、呼び出しが行われた関数への参照を保持するオブジェクトを参照します。匿名関数は、ブラウザーのウィンドウであるルート コンテキスト オブジェクトに対して作成されます。これは、2 番目のパラメーターにオブジェクトを指定しない場合に観察されるものです。

each() には、関数内で「this」として機能する別のオブジェクトを渡したかどうかを判断する機能があります。each() は Object.bind() または Object.call() を使用できます。どちらも、渡された最初のパラメーターを使用して「this」をオーバーライドします。

each() の 2 番目のパラメーターとして「this」を渡すと、外側の関数のコンテキスト オブジェクトが内側の関数で「this」として使用されます。

于 2014-04-16T15:22:24.813 に答える