3

基本的に、私はJoose for Javascript と呼ばれるメタクラス フレームワークを使用して、より洗練されたクラス構文を利用できるようにしていますが、クラスのより深いメソッド内からオブジェクトのスコープを参照する方法がわかりません。宣言。また、依存関係管理にrequire.jsを使用しています...

クラス定義の例を次に示します。

   define([
      'jquery',
      'handlebars',
   ], function($, Handlebars){

      var MyClass = Class("MyClass", {

         //inheritance         
         isa: SuperClass,

         //instance vars
         has: {

            hello:{
               is: 'r',
               init: 'Hi There!',
            },

            someVarToBeSetUsingAjax:{
               is: 'rw',
               init: false,
            },
         },

         //methods
         methods: {

            init: function () {

               var self = this;
               self.getAjaxVar();

            },

            getAjaxVar: function() {

               var self = this;

               //HOW CAN I REFERENCE 'self' THROUGHOUT MY OBJECT?

               $.get('ajax/test.html', function(response) {
                 self.someVarToBeSetUsingAjax = response.value;
               });
            },

            //lots more methods...

         }
    });

   return MyClass;

});

わかりましたので、私の問題は - AJAX 関数で var self = this を記述して、オブジェクトを AJAX 呼び出しのスコープに入れる必要があることです - 問題ありません。しかし、クラス宣言のほぼすべてのメソッドに対してこれを行っていることに気付きました! クリーンで効率的な方法ですべてのメソッドで自己を参照するにはどうすればよいですか? パラメータを設定することでAJAXでスコープを使用できることはわかっています.AJAXだけでなく、スコープを外側に閉じる他の関数であると仮定します。

ありがとう。

4

4 に答える 4

2

関数をネストするたびに、 について考える必要がありますthis。ただし、関数をネストしない場合、またはその関数が使用しない場合thisは、それについて考える必要はありません。

        init: function () {
           var self = this;
           self.getAjaxVar();
        },

したがって、この場合は必要ありません。これはまったく同じです:

        init: function () {
           this.getAjaxVar();
        },

しかし、ここで:

        getAjaxVar: function() {
           var self = this;

           $.get('ajax/test.html', function(response) {
             self.someVarToBeSetUsingAjax = response.value;
           });
        },

内部関数を作成し、 の元の値への参照が必要なため、アクセス可能にするためthisに にエイリアスthisするself必要があります。

thisクラスのどこからでも値を修正する方法はありません。


とはいえ、いくつかのオプションがあります。

Function.prototype.bind()助けられる。

var func = function() { return this.name };
var obj = { name: 'Bob' };
var boundFunc = func.bind(obj);
boundFunc(); // 'Bob'

bindthis常に特定のオブジェクトに設定された新しい関数を返します。

そう:

        getAjaxVar: function() {
           $.get('ajax/test.html', function(response) {
             this.someVarToBeSetUsingAjax = response.value;
           }.bind(this));
        },

これはすべてのブラウザーでサポートされているわけではないことに注意してください。古いブラウザーでは shim が必要になる場合があります。

または、ただ慣れてself = thisください。


実行時にコンテキストを変更しない関数の宣言をサポートしているため、coffeescriptにも少しうなずきたいです。

obj = {
  name: "bob"
  sayHello: ->
    doSomeAjax({
      success: =>
        alert "successfully made " + this.name + " say hello!"
    })
}

obj.sayHello()

->通常の機能を果たします。ただし、太い矢印=>は代わりにthis関数の内側と外側の値を保持します。インスタンスメソッド内のコールバックで非常に便利です。JS にコンパイルすると、基本的にself = thisエイリアスを作成selfし、内部関数内で毎回参照しますthis。それはかなり滑らかです。

ただし、プレーンな JS では、最も一般的なパターンは単純self = thisに、それに固執することです。

于 2013-01-10T21:29:40.887 に答える
1

答えは、使用することthisです。クロージャを作成するだけで済みます (これはvar self = this;、オブジェクトの外部で呼び出される関数がある場合に行います (ここでは ajax 呼び出しからの戻りで行うように)。

クロージャを作成する他の方法はありません。


明確にするために (わずかな技術的な手を振るだけでジャンプする人もいるため)、クロージャを作成する必要はありません。しかし、そうすべきだと思います -- JavaScript はクロージャーと連携するように設計されており、クロージャーは適切に機能し、他の JavaScript プログラマーにもよく理解されています。

于 2013-01-10T21:25:13.123 に答える
0

クラス宣言のほぼすべてのメソッドに対してこれを行っていることに気付きました! クリーンで効率的な方法ですべてのメソッドで自己を参照するにはどうすればよいですか?

それはいけません。selfによって参照されるインスタンスであるの値は、thisメソッドの呼び出し時にのみ認識されます。

コンストラクター(メソッド?)でselfそれを宣言し、そこにすべてのコールバック関数も作成した場合にのみ、それを回避して1つの共通変数を使用できます。initただし、最もメモリ効率の高い方法ではない可能性があります。

return Class("MyClass", {
     // …

     methods: {
         init: function () {
             var self = this;
             this.ajaxVarCallback = function(response) {
                 self.someVarToBeSetUsingAjax = response.value;
             };
             // and other functions that use "self"

             this.getAjaxVar();
         },
         getAjaxVar: function() {
             $.get('ajax/test.html', this.ajaxVarCallback);
         },
         // …
     }
});
于 2013-01-10T21:26:45.427 に答える
0

MyClass のすべてのインスタンスを常にスコープ内 (またはグローバル変数として) に保持する以外に、解決策はありません。selfただし、次を使用して、どこでも宣言する必要をなくすことができますFunction.prototype.bind

$.get('ajax/test.html', function(response) {
  this.someVarToBeSetUsingAjax = response.value;
}.bind(this));

これは $.get() に限らず、コールバック関数を使用しているすべての場所で使用できます。

于 2013-01-10T21:28:24.610 に答える