1

私は次のものを持っています:

var o = {f: function(fn) {
    fn.call(o);
}};
var ob = {f: function() {
    o.f(function() {
        this.x = 2; //HERE: how can this reference ob?
        //ob.x = 2;
    });
}};
ob.f();
ob.x; // undefined

o.f(fn)o にバインドされているfnwhereを呼び出します。this

thisHERE では、 ob にアクセスするために使用したいと思います。ただし、ob.fが呼び出されると、thisにバインドされoます。JQueryはこのように機能すると思います。例えば:

$(...).blah(function() {
    this // this is bound to $(...) jquery object.
    ...
};

私が今していることは次のとおりです。

var Ob = function() {
    var self = this;
    self.f = function() {
        o.f(function() { self.x = 2; };
    };
};
var ob = new Ob();
ob.f();
ob.x; // 2

しかし、文体上の理由から、上記は好きではありません。

  1. 演算子を使用すると、newあまりにも古典的な OOP のように聞こえます。
  2. class Obusingの定義functionは直感的ではありません (少なくとも最初は)。

obそのため、オブジェクト リテラルで定義しようとしています。しかし、 以外のオブジェクトobに設定するメソッド呼び出しを使用する関数でオブジェクトを参照する方法が見つかりません。thisob

次のようなことができます:

var ob = {f: function() {
    o.f(function() {
        self.x = 2;
    });
}};
var self = ob;
ob.f();
ob.x;

しかし、上記の因数分解の方法がわかりません。私は試した:

function obj(o) {
    return function() {
        var self = o;
        return o;
    }();
}
var ob = obj({f: function() {
    o.f(function() {
        self.x = 2;
    });
}});
ob.f();
ob.x;// ReferenceError: self is not defined

それで、オブジェクト内の関数でオブジェクトを確実に参照する方法はありますか(thisコンテキストに応じて何にでもバインドできます)?

4

3 に答える 3

3

JavaScript では、関数はオブジェクトであり、関数を呼び出すための 2 つのメソッドがあります。

call(scope, arg1, arg2, ...);
apply(scope, args);  // args is an array of arguments to call the function with

最初の引数 'scope' は、関数内で 'this' にバインドされるオブジェクトです。したがって、次の例は同等です。

obj.method(1, 2, 3);
obj.method.call(obj, 1, 2, 3);
obj.method.apply(obj, [1, 2, 3]);

最初の例では、「o」をスコープとして使用して of() に渡された関数を呼び出しています。

var o = {f: function(fn) {
    fn.call(o);
}};

したがって、「ob」で渡された関数は「o」を次のように参照します。

var ob = {f: function() {
    o.f(function() {
        this.x = 2; //HERE: how can this reference ob?
        //ob.x = 2;
    });
}};

'HERE' の行で、'this' は実際には 'o' です。

次のことを試すことができます。

var ob = {f: function() {
    var self = this;
    o.f(function() {
        self.x = 2; // self is ob now
    });
}};

または、関数 'of' を変更して、スコープ パラメーターを取得することもできます。

var o = {f: function(fn, scope) {
    fn.call(scope || this); // Uses the given scope or this (= 'o') if no scope is provided
}};

次に、「ob」に「this」を渡すことができます。

var ob = {f: function() {
    o.f(function() {
        this.x = 2; // 'this' will be the 'outer' this
    }, this); // Here: this as scope
}};
于 2009-02-20T14:16:52.243 に答える
1

Douglas Crockford の単純なコンストラクター パターンに従って、new の代わりにオブジェクト リテラルを使用するコンストラクター関数を作成します。このような:

var o = {f: function(fn) {
    fn.call(o);
}};

function obj() {
    var me = {};
    me.f = function () {
        o.f(function() {
            me.x = 2;
        });
    };
    return me;
}

var ob = obj();
ob.f();
ob.x; // 2
于 2009-02-20T14:13:44.107 に答える
0

リテラルを使用するだけで、補助関数なしでそれを行うことができます。

var o = {f: function(fn) {
    fn.call(o);
}};
var ob = {f: function() {
    var self = this; // this == ob
    o.f(function() {
        self.x = 2; // self == enclosing function's this == ob
    });
}};
ob.f();
assert(ob.x == 2);
于 2009-02-20T15:37:54.653 に答える