كيف يمكنني الرجوع إلى كائن داخل أحد وظائف الأعضاء؟

StackOverflow https://stackoverflow.com/questions/569654

  •  05-09-2019
  •  | 
  •  

سؤال

لدي ما يلي:

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) المكالمات fn أين this لا بد أن o.

في هنا، أريد أن أستخدم this للوصول إلى 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. تعريف صف دراسي Ob استخدام function ليس بديهية (على الأقل في البداية).

لهذا السبب أحاول تحديد ob مع كائن حرفي. ولكن لا يمكنني العثور على طريقة للإشارة إلى الكائن ob في وظيفة تستخدم طريقة استدعاء تلك مجموعات this كائن آخر من ob.

يمكنني أن أفعل شيئا مثل ما يلي:

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 يمكن ربط أي شيء اعتمادا على السياق)؟

هل كانت مفيدة؟

المحلول

بعد Douglas Crockfords نمط منشئ بسيط، سأجعل وظيفة منشئ تستخدم الكائن حرفيا بدلا من جديد. مثله:

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

نصائح أخرى

في جافا سكريبت، وظائف هي كائنات، وجود طريقتين لاستدعاء الوظيفة:

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

الحجة الأولى، "النطاق"، هي الكائن الذي لا بد أن "هذا" ضمن الوظيفة. لذلك، تعادل الأمثلة التالية:

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

في مثالك الأول، تقوم بتوصيل الوظيفة التي تم تمريرها إلى () باستخدام "O" النطاق:

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;
    });
}};

في الخط "هنا"، "هذا" هو في الواقع "O".

يمكنك تجربة ما يلي:

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

أو يمكنك تعديل وظيفة "" لاتخاذ معلمة النطاق:

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

ثم يمكنك تمرير "هذا" في "OB":

var ob = {f: function() {
    o.f(function() {
        this.x = 2; // 'this' will be the 'outer' this
    }, this); // Here: this as scope
}};

يمكنك القيام بذلك دون وظائف مساعدة، فقط باستخدام الحرفيين:

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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top