Guillaume Fe
Guillaume Fe

Reputation: 369

Why "This" does act as a private member in a javascript function in this case?

I try to call a public member in a function, and it appears as 'undefined' however the function works...

-- EDIT --
As pointed out by @Shane Voisard this is acting as a member of the parent of my function.

Solution is to give a name to the function (as Shane underlined in answer).

... or to attach the function to a name :

MySite.Public.Logo = { 

        inject : function(target){

             this.name = 'Logo';
             ...
        }
}

In console :

MySite.Public.Modules.Logo.name; //return "Logo" 

and so on... thx SO

-- /EDIT --

My file system is like this

root folder :
-rw-r--r--  1 www-data www-data 1921 avril  3 17:31 0.js
drwxr-xr-x  9 www-data www-data 4096 avril  3 17:37 public

public folder :
-rw-r--r-- 1 www-data www-data  214 avril  3 17:37 0.js
drwxr-xr-x 2 www-data www-data 4096 avril  3 17:40 modules
drwxr-xr-x 2 www-data www-data 4096 avril  3 17:40 factories
drwxr-xr-x 2 www-data www-data 4096 avril  3 17:40 functions
drwxr-xr-x 2 www-data www-data 4096 avril  2 22:22 singleton

module folder : 
-rw-r--r-- 1 www-data www-data  28 mars  31 06:07 1.js
-rw-r--r-- 1 www-data www-data 348 avril  3 17:51 logo.js

Loading is made in this order :
root/0.js initializes MySite = {}
public/0.js initializes MySite.Public = {}
module/1.js initializes MySite.Public.Modules = {}

When all others needed files are loaded, public/0.js calls MySite.Public.Modules.Logo(), which has been initialized when logo.js has been loaded into the browser. The function works, I can get a return from logo.js. But none of the this members are publicly accessibles...

Content of logo.js :

MySite.Public.Modules.Logo = function(){

        this.name = 'Logo';

        this.build = function(){
                var logo = MySite.Public.Factories.HTML.make('logo');
                return logo;
        };  

        this.inject = function(target){
                var logo = this.build();
                var target = MySite.Public.Functions.ToolBox.getElementByName(target); //getElementByName is a custom function
                target.appendChild(logo);
        }; 

}

In the console :

MySite.Public.Modules.Logo.inject('body'); // undefined is not a function...
MySite.Public.Modules.Logo.build(); // undefined is not a function...
MySite.Public.Modules.Logo.name; // ""
typeof MySite.Public.Modules.Logo; // "function"

Content of logo.js : // to test the function I give target to the constructor

MySite.Public.Modules.Logo = function(target){

        this.name = 'Logo';

        this.build = function(){
                var logo = MySite.Public.Factories.HTML.make('logo');
                return logo;
        };  

        this.inject = function(target){
                var logo = this.build();
                var target = MySite.Public.Functions.ToolBox.getElementByName(target);
                target.appendChild(logo);
        };  

        this.inject(target);

}

In the console :

MySite.Public.Modules.Logo('body'); //works

And still...

MySite.Public.Modules.Logo.inject('body'); // undefined is not a function...
MySite.Public.Modules.Logo.build(); // undefined is not a function...
MySite.Public.Modules.Logo.name; // ""
typeof MySite.Public.Modules.Logo; // "function"

Does someone has a clue, please, on what I am doing wrong?

Upvotes: 0

Views: 52

Answers (1)

Shane Voisard
Shane Voisard

Reputation: 1145

Try:

MySite.Public.Modules.Logo()
MySite.Public.Modules.name // "Logo"

When you call Logo(), this.name refers to the MySite.Public.Modules object. When you invoke a function in a object method context, javascript implicitly assigns the object to this inside the invoked function at runtime.

If you want the methods defined on your function object, give the function a name and then refer to the name inside the function:

MySite.Public.Modules.Logo = function init(target){

        init.l_name = 'Logo';
        init.getName = function { return l_name };

        init.build = function(){
                var logo = MySite.Public.Factories.HTML.make('logo');
                return logo;
        };  

        init.inject = function(target){
                var logo = init.build();
                var target = MySite.Public.Functions.ToolBox.getElementByName(target);
                target.appendChild(logo);
        };  

        init.inject(target);

}

Edit: The name property of a function object might be read only, depending upon the javascript environment. Thus, you may need to use a different property name internally and expose a pretty accessor method. For example, in Chrome developer tools, I could not assign to init.name.

MySite is your global object, but you refer to Innov24 as if Innov24 = MySite.

I highly recommend Javascript: The Good Parts by Douglas Crockford.

Upvotes: 1

Related Questions