Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

change "var" inside constructor closure where new instance is created

I write bad English I'm so sorry...

I have some nonplus about the behavior of a var when is inside a function closure like:

var c = function(){
    var _self = this;
}

when i crate a new instance:

var A = new c();

A.logSelf = function(){
    console.log(_self);
}

inside A scope (or closure... i don't know the correct name) the _self var was undefined but, i can add a init() method to revalue _self inside all new instance, and with jQuery help extend the default behavior of the constructor (for simply):

var c = function(obj){
    var _self = this;
    this.name = "lol";
    this.init = function(){
        _self = this;
    }
    this.sayName = function(){
        console.log(_self.name);
    }
    $.extend(this,obj);
    this.init();
}

var A = new c({
    name : "A",
    init : function(){
        _self = this;
    },
    sayA : function(){
        console.log(_self.name)
    }
});

Right now if i call A.sayName() & A.sayA() in console logs A, I said: "WOW, I'm best ever!", but when i've trying to instance a B var all changed:

var B = new c({
    name : "B",
    init = function(){
        _self = this;
    }
});

... now A.sayName() logs A, but A.sayA() logs B (because _self inside all instane of c now is the last instance that I have create [B in this case])...

WHY? what's wrong in me?

Maybe the closure of A and B is the same because two all are instance of the same constructor? But why inside c method ereditend by A and B the value of _self is correct? I don't understand the sence of this! Sigh.

Working example

--> jsfiddle

WHY I need this?

Inside my A & B instance I use some $.ajax and jQuery handler, inside the anonymous function that jQuery use to callback (all know it) this is a reference of something and i can't reference to the instance that wrap the anonymous function.

I need _self to easy reference without revalue var _self every time i need to use a jQuery callback or use context property of $.ajax when I use it.

I prefer to value self one time, and inside the scope (or closure) of my instance it never change there his reference of this.

Some example...

c = function(){
    //...
    this.render = function() {
            //var __self = this; 

            if (typeof this.view.surce === "undefined") {

                //this.writeRequest();

                $.ajax({
                    url: this.config.path + "/index.shtml",
                    data: this.config.req,
                    datatype: "html",
                    success: function(ht) {
                        __self.view.elements.html = ht;
                        __self.run();
                    },
                    error: function() {
                        __static.log("Error inside ajax call for view TMPL");
                    }
                })
            } else {
                this.run();
            }
        }

    //...

    this.run = function() {
        if (this.view) this.$el = $(__static.tmpl(this.$tmpl.html(), this.view.elements));
        this.$el.appendTo(this.$place);

        if (typeof this.view.callback === "function") {
            this.view.callback.call(this, this.$el);
            delete this.view.callback;
        }

        this.cases();
        this.show();
    }

    //...
}

The real problem is inside this method of A:

    endpoint : function(){
        //var __self = this; 
        this.$el.find(".call-to").on("click", function(e) {
            e.preventDefault();
            if(typeof __static.B !== "undefined") return __static.B.show();
            //__static is the reference of the scope (all works inside a self invoked anonymous function).
            __static.B = new __static.C(Bconfig, __static); //Bconfig is an object that contain all extend and override the C constructor.
            __self.close();
            __static.B.view = new _viewConf(__static.B.config.type[__self.view.b]);
            __static.B.render();
        });
    },

In this two case I need to rivalue __selfevery time I need to use.

(I've search an answer here and in general in google... but I haven't find my specific case)

like image 425
Frogmouth Avatar asked Dec 30 '25 08:12

Frogmouth


2 Answers

var B = new c({
    name : "B",
    init = function(){
        _self = this;
    }
});

This code snippet has a function B.init that will set the global _self to B (this).

when you are defining A it is similar and is also editing the global _self

perhaps what you want is something like this

[ FIDDLE ]

There's nothing wrong with using the context feature of $.ajax. But you could have something like this:

var c = function(obj){
    var _self = this,
        data;
    ...
    this.request = function(){
            $.ajax( { 
                url : 'blah',
                // context : this,
                success : function(d){
                    data = d;   // setting a private var of A
                    _self.sayName();  // in lieu of using context to set "this".  calling A public method
                }
            });  // end ajax; 
    }  // end anon;
} // end constructor;
like image 67
gillyspy Avatar answered Jan 01 '26 22:01

gillyspy


The issue here is that the _self variable you assign to in instance A (and B) is not the same _self variable from function c scope, it is a global variable (in the window object)

var c = function(obj){
    var _self = this; // scope of function 'c'
    this.name = "lol";
    this.init = function(){
        _self = this; // still scope of function 'c'
    }
    this.sayName = function(){
        console.log(_self.name); // scope of function 'c'
    }
    $.extend(this,obj);
    this.init();
}

var A = new c({
    name : "A",
    init : function(){
        _self = this; // global scope here, _self === window._self
    },
    sayA : function(){
        console.log(_self.name) // also call to the global _self object
    }

});

This way objects A and B both use window._self in their functions, therefore making them share data. The thing to learn from here is that you cannot manipulate variables that are defined in the function scope with the 'var' declaration. The ones you can manipulate you have to assign to 'this' (in case of constructors)

like image 40
STT Avatar answered Jan 01 '26 20:01

STT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!