4

I'm trying to wrap my head around building a custom JavaScript library. I've read a lot about the module pattern, and also read Crockford's articles on private and public members. I know what is an immediately invoked function expression and why we do stuff like

var myLib = (function() {
}())

However, I'm still a little lost in some cases regarding scope and closures in general. The concrete problem I have is:

Why does the following example alert DOMWindow, rather than the myLib object? http://jsfiddle.net/slavo/xNJtW/1/

It would be great if you can explain what "this" refers to in all of the methods in that example and why.

2
  • 2
    FYI: this has nothing to do with variable scope. It has only to do with the calling context of the function. Its value depends on how the function is called. Commented Mar 7, 2012 at 16:20
  • 3
    BTW, you can "use strict" in order to make the "this" in this kind of situation be undefined instead of being the window. It can help a lot to have this kind of error show up more explicitly. Commented Mar 7, 2012 at 18:27

4 Answers 4

4

Inside any function declared (anywhere) and invoked as follows this will be window object

function anyFunc(){
    alert(this);  // window object
}

anyFunc();


var anyFunc2 = function(){
    alert(this);  // window object
}

anyFunc2();

If you want to create private functions and access the instance of 'myObject' you can follow either of the following methods

One

module = (function () {

    var privateFunc = function() {
        alert(this);
    }

    var myObject = {
        publicMethod: function() {
            privateFunc.apply(this); // or privateFunc.call(this);
        }
    };

    return myObject;
}());


module.publicMethod();

Two

module = (function () {

    var _this; // proxy variable for instance

    var privateFunc = function() {
        alert(_this);
    }

    var myObject = {
        publicMethod: function() {
            privateFunc();
        }
    };
    _this = myObject;
    return myObject;
}());


module.publicMethod();

These are solutions to your issue. I would recommend using prototype based objects.

EDIT:

You can use the first method.

In fact here myObject is in the same scope as privateFunc and you can directly use it inside the function

 var privateFunc = function() {
     alert(myObject);
 }

The real scenario were you can use a proxy for this is shown below. You can use call also.

Module = function () {

    var _this; // proxy variable for instance

    var privateFunc = function() {
        alert(this + "," + _this);
    }

    this.publicMethod = function() {
        privateFunc(); // alerts [object Window],[object Object]
        privateFunc.call(this); // alerts [object Object],[object Object]
    }

    _this = this;
    return this;
};

var module = new Module();
module.publicMethod();
Sign up to request clarification or add additional context in comments.

5 Comments

Why create _this? Inside an object, this should refer to that object when called like obj.foo()
Answer is in your question - "inside object" . Here you can see that privateFunc is not inside myObject, means not defined as a function of myObject. So we have to use a proxy variable.
In all functions of myObject, this will be myObject when invoked using dot operator - e.g: myObject.publicMethod();
Great. I also saw Crockford was using a proxy, he just called it "that". Didn't quite understand the concept. Which method of the two would you recommend personally, and which one is more widely used?
You can also now use arrow functions to achieve the same thing () => this
0

You need to explicitly state that myPrivateMethod is a member of myLib:

function MyLib ()
{
    this._myPrivateField = "private";
    this._myPrivateMEthod = function ()
    { 
         alert(this); // Alerts MyLib function;
    }
}

var libObject = new MyLib();

Just remember that without using enclosure techniques, nothing in JavaScript is ever truly private!

A better way to do the above is like so:

function MyLib(instanceName)
{
    this.name = instanceName;
}

MyLib.prototype.myPrivateFunction()
{
    alert(this);
}

To call your method after that:

var libObject = new MyLib();
libObject.myPrivateMethod(); // Alerts info about libObject.

4 Comments

In this case, how can I call the private method from the public methods (members of the returned object in my sample)?
Why is it better to use the latter?
Sorry. Editing the above to include!
@tandu: check out this thread. It's a pretty well done guide: stackoverflow.com/questions/310870/…
-1

The thing to remember about the module pattern is that it runs once and completes. The methods that are still available to be called are the closures. At the time of creating module, "this" refered to the window and was replaced by its value.

Comments

-2

In your linked fiddle, the "this" keyword is never changed by a "new" keyword or other context change, so it still refers to the global window object.

edit: clarification

5 Comments

'"this" is never changed by a "new" keyword ... so it refers to the global window object.' Completely wrong.
@amnotiam can you explain how/why it is wrong? i would like to learn something instead of just being insulted :P
"the "this" is never changed by a "new" keyword..." Remove the word "never" and replace it with "always". "...or other scope change..." new doesn't cause a scope change. It causes a calling context (this) change. "...so it refers to the global window object." When does this refer to the global window object? When using new? In that case it will never refer to the global. Other than that, it will depend on how the function is invoked. Sorry if you felt insulted.
I think I see where the confusion is coming from... I meant that in the fiddle he posted the "this" is still referring to the window object because he did not invoke his function as a constructor (via new). I think we are saying the same thing, I just worded it poorly.
Update your answer, and I'll remove the DV.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.