سؤال

هذا الشيء يعمل تقريبا:

function myClass(url) {

this.source = url;
this.rq = null;
this.someOtherProperty = "hello";

// open connection to the ajax server
this.start = function() {
    if (window.XMLHttpRequest) {
        this.rq = new XMLHttpRequest();
        if (this.rq.overrideMimeType)
        this.rq.overrideMimeType("text/xml"); 
    } else
        this.rq = new ActiveXObject("Microsoft.XMLHTTP");

    try {
        this.rq.onreadystatechange = connectionEvent;
        this.rq.open("GET", this.source, true);
        this.rq.send(null);
        this.state = 1;
    } catch (err) {
        // some error handler here
    }

}

function connectionEvent() {
    alert("i'm here");
    alert("this doesnt work: " + this.someOtherProperty);
}

} // صفي

لذلك ليس أكثر من مجرد كائن XMLHTTPrequest كعضو في صفي ، بدلاً من تعريفه عالميًا ، واستدعاءه بالطريقة التقليدية. ومع ذلك ، داخل وظيفة رد الاتصال الخاصة بي ، يتم فقد معنى "هذا" ، على الرغم من أن الوظيفة نفسها يتم تحديدها داخل MyClass. لقد تأكدت أيضًا من أن الكائن الذي أقوم بتثبيته من MyClass قد أبقى على قيد الحياة لفترة كافية (أعلن عالمي في البرنامج النصي).

في جميع الأمثلة على استخدام فصول JavaScript التي رأيتها ، كان "هذا" لا يزال متاحًا داخل الوظائف الداخلية. بالنسبة لي ، ليس الأمر كذلك ، حتى لو أخذت وظيفتي في الخارج وجعلها myclass.prototype.connectionevent. ما الخطأ الذي افعله؟ شكرا.

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

المحلول

السبب في عدم عمله هو أنه في JavaScript ، this يتم تعريفه بالكامل من خلال كيفية الوظيفة اتصل, ، ليس حيث يتم تعريفه. هذا يختلف عن بعض اللغات الأخرى.

امتلاك this يعني ما تتوقعه ، يجب عليك التأكد من ذلك بشكل صريح عن طريق "ربطه":

this.start = function() {
    var self = this; // Set up something that survives into the closure

    /* ...lots of stuff omitted... */

    this.rq.onreadystatechange = function() {
        // Call `connectionEvent`, setting `self` as `this` within the call
        connnectionEvent.call(self);
    };

هناك المزيد من المعلومات حول this الإدارة في منشور المدونة هذا, ، ولكن في الأساس: عندما يتم استدعاء وظيفة دون أي جهد معين تم تعيينه this, this ضمن الوظيفة سيكون دائمًا الكائن العالمي (window, ، على المتصفحات). هناك طريقتان لتعيين this عند إجراء مكالمة:

  1. استخدام Function#call (أو Function#apply) كما فعلت أعلاه ، تمرير مرجع الكائن لاستخدامه this كمعلمة الأولى. الذي يدعو الوظيفة ويحدد this إلى كل ما مررت به. الفرق بين #call و #apply هي الطريقة التي تقدم بها المزيد من الحجج لتمرير الوظيفة. مع #call أنت تزودهم كحجيلات أخرى إلى #call استدعاء (على سبيل المثال func.call(thisArg, arg0, arg1, arg2)) ، مع مع #apply يمكنك تزويدهم كصفيف في الحجة الثانية (func.apply(thisArg, [arg0, arg1, arg2])).
  2. باستخدام تدوين منقط: إذا كان لديك كائن يحتوي على خاصية مع وظيفة مخصصة لها (مثل الخاص بك start خاصية) ، ودعاها باستخدام مثيل الكائن ، ونقطة ، واسم الخاصية (this.start() أو foo.start(), ، وما إلى ذلك) سوف يتصل بالوظيفة وتعيين this إلى مثيل الكائن داخل المكالمة. لذا فإن التدوين المنقط يفعلان مميزة تماما الأشياء: تبحث عن العقار ويجد وظيفة كقيمة لها ، وتدعو الوظيفة من هذا القبيل this تم تعيينه على الكائن أثناء المكالمة. حرفيا مثل: var f = obj.func; f.call(obj).

خارج الموضوع قليلاً ، ولكن: باستثناء سبب وجيه حقًا ، لن أعيد اختراع هذه العجلة. هناك الكثير من المكتبات لمكالمات XHR ببساطة. jQuery, النموذج المبدئي, إنهاء, ، وكل ما يقرب من الباقي.

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