سؤال

لدي بعض المشاكل مع القديم عادي جافا سكريبت (لا أطر) في الرجوع إلى بلدي الكائن في وظيفة رد الاتصال.

function foo(id) {
    this.dom = document.getElementById(id);
    this.bar = 5;
    var self = this;
    this.dom.addEventListener("click", self.onclick, false);
}

foo.prototype = {
    onclick : function() {
        this.bar = 7;
    }
};

الآن عند إنشاء كائن جديد (بعد دوم تحميل, مع span#اختبار)

var x = new foo('test');

إن 'هذا' داخل onclick النقاط الدالة على span#اختبار وليس فو الكائن.

كيف يمكنني الحصول على إشارة إلى بلدي فو الكائن داخل onclick وظيفة ؟

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

المحلول

(استخراج بعض التفسيرات التي كانت مخبأة في تصريحات ردا غيرها)

والمشكلة تكمن في السطر التالي:

this.dom.addEventListener("click", self.onclick, false);

وهنا، يمكنك تمرير كائن وظيفة لاستخدامها رد. عندما الزناد الحدث، يتم استدعاء الدالة ولكن الآن لديها أي ارتباط مع أي كائن (هذا).

ويمكن حل المشكلة عن طريق التفاف وظيفة (مع مرجع كائن انها) في الإغلاق على النحو التالي:

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);

ومنذ أن تم تعيين النفس متغير <م> هذه عندما تم إنشاء الإغلاق، فإن وظيفة الإغلاق تذكر قيمة المتغير النفس عندما يطلق عليه في وقت لاحق.

وهناك طريقة بديلة لحل هذا هي لجعل وظيفة فائدة (وتجنب استخدام المتغيرات للربط <م> هذه ):

function bind(scope, fn) {
    return function () {
        fn.apply(scope, arguments);
    };
}

وقال إن الشفرة المحدثة ثم تبدو:

this.dom.addEventListener("click", bind(this, this.onclick), false);

Function.prototype.bind هو جزء من ECMAScript 5، ونفس وظائف. بحيث يمكنك القيام به:

this.dom.addEventListener("click", this.onclick.bind(this), false);

لالمتصفحات التي لا تدعم ES5 بعد، تقدم MDN الرقائق التالية :

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 

نصائح أخرى

this.dom.addEventListener("click", function(event) {
    self.onclick(event)
}, false);

عن مسج المستخدمين يبحثون عن حل لهذه المشكلة, يجب عليك استخدام مسج.الوكيل

والتفسير هو أن self.onclick لا يعني ما هو رأيك يعنيه في جافا سكريبت. وهو ما يعني في الواقع وظيفة onclick في النموذج الأولي للself الكائن (بدون بأي شكل من الأشكال المراجع self نفسه).

وجافا سكريبت ليس لديها سوى وظائف ولا المندوبين مثل C #، لذلك فمن غير الممكن أن يمر طريقة والكائن ينبغي تطبيقه على أنه رد.

والطريقة الوحيدة لاستدعاء أسلوب في الاستدعاء هو أن نسميها نفسك داخل دالة رد. لأن وظائف جافا سكريبت هي الإغلاق، فهي قادرة على الوصول إلى المتغيرات في نطاق تم إنشاؤها في.

var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);

وثمة تفسير جيد للمشكلة (كان لي مشاكل فهم حلول وصفها حتى الآن) هو <وأ href = "http://www.mail-archive.com/jquery-en@googlegroups.com/msg82906.html" يختلط = "نوفولو noreferrer"> متوفرة هنا .

ولقد كتبت هذا البرنامج المساعد ...

وأعتقد أنه سوف يكون من المفيد

jquery.callback

وهذه هي واحدة من النقاط الأكثر إرباكا من JS: و'هذا' متغير يعني أن الكائن الأكثر المحلية ... ولكن وظائف هي كائنات أيضا، لذلك 'هذا' نقطة هناك. وهناك نقطة أخرى خفية، ولكنني لا أتذكر كل منهم.

وأنا عادة تجنب استخدام "هذا"، فقط تحديد المحلية 'لي' متغير واستخدام بدلا من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top