How do these pieces of code function exactly?
Asked Answered
R

2

7

I was reading over how to 'Create a JavaScript Library' earlier and I came across these pieces of code that make me wanna rip my hair out.

Here is the code which got my brain in knots:

if (window === this) {
    return new _(id);
}

_(id) is just the function name in which this code is contained. Here's the rest of the code if you need to look over it yourself.

function _(id) {

// About object is returned if there is no 'id' parameter
var about = {
    Version: 0.5,
    Author: "Michael Jasper",
    Created: "Fall 2010",
    Updated: "23 November 2011"
};

if (id) {

    // Avoid clobbering the window scope:
    // return a new _ object if we're in the wrong scope
    if (window === this) {
        return new _(id);
    }

    // We're in the correct object scope:
    // Init our element object and return the object
    this.e = document.getElementById(id);
    return this;
  } else {
    // No 'id' parameter was given, return the 'about' object
    return about;
  }
};

I've never seen 'return new function' before but I would love to understand how it functions.

The other piece of code:

_.prototype = {
  hide: function () {
          this.e.style.display = 'none';
          return this;
  }

  show: function () {
           this.e.style.display = 'inherit';
           return this;
  }
};

I know that this code adds new methods to the _ object but why do they 'return this'? I tried that without and it worked just fine.

One last thing, the link to the article is http://www.mikedoesweb.com/2012/creating-your-own-javascript-library/

Ritchey answered 15/6, 2012 at 4:18 Comment(6)
Return this? So maybe you can append something more after it? Just guessingDoubs
The return this enables chaining, as in magic().do().stuff().Widower
yeah, chaining is what I meant,, it's like jquery, but jquery is a little bit more complex and returns many objectsDoubs
That would make sense. I was thinking it was for optimization purposes. I wish the developer would've took more time to explain this. @JaredFarrish Oh, I didn't know that! =)Ritchey
Take a look at the jQuery core and ctrl+f and search for return this on that page. You'll see return this is used quite often when you would might chain together several calls on the same object. It's pretty powerful, one of Javascript's nifty features.Widower
This is really awesome! I never knew you could chain together calls. Now, only if someone answers what the other piece of code does.Ritchey
B
16

The first bit of code is essentially trying to detect how the "constructor" function has been called...

in javascript, you can use a function to create an object in two ways:

function _(id) {
    this.someProperty = "stuff";
    //Do more stuff to "this"
    return this;
}

//in this scenario, the "this" object will be the window object
var myObject = _(id);
console.log(window.someProperty); //outputs "stuff";
console.log(myObject.someProperty); //outputs "stuff";

//in this scenario, the "this" object is what get's actually returned...
var myObject = new _(id);
console.log(window.someProperty); //outputs "undefined"
console.log(myObject.someProperty); //outputs "stuff"

therefore, the checking for

if (window === this) {
    return new _(id);
}

is simply there to make sure you don't accidentally call the constructor without the new keyword. this would be bad, as any property that you would assign to the object, would immediately be assigned to the window namespace... which would be bad.


as for your second question, the author is using a return this; at the end of each method as a fluent interface design pattern

this allows for convenient and nice looking object manipulation. a common example of this is jQuery, where you can chain methods onto one single object...

$(".some-css-selector").click(function() { 
    ... do something to the selected objects during the "click" event
}).keyup(function() {
    ... do something to the same objects during the "keyup" event
});

EDIT: a little more additional information in response to W3Geek's comments below:

from Douglas Crockford's book "Javascript: The Good Parts" (totally a good read if you are getting into JS... only like 70 pages but every one of them is worth reading).


Javascript's new operator creates a new object that inherits from the operand's prototype member, and then calls the operand, binding the new object to this. This gives the operand (which had better be a constructor function) a chance to customize the new object before it is returned to the requestor.

If you forget to use the `new operator, you instead get an ordinary function call, and this is bound to the global object instead of to a new object. That means that your function will be clobbering global variables when it attempts to initialize the new members. That is a very bad thing.

...

Constructors are functions that are designed to be used with the new prefix. The new prefix creates a new object based on the function's prototype and binds that object to the functions implied this parameter. If you neglect to use the new prefix, no new object will be made, and this will be bound to the global object. This is a serious mistake.


Bonine answered 15/6, 2012 at 4:38 Comment(6)
So basically 'this' would pollute the global scope if we it used incorrectly and that 'check' is placed there to prevent that from happening, correct? My question is, what is wrong with the window namespace? I see so much about how this bad but never why.Ritchey
correct. adding properties to the "window" object is bad because there are lots of other frameworks that have access to it (and USE IT) as well... for example, people modify the window.location.href object (the current url of your browser) all the time to "navigate" to a new page... if you all of a sudden added a location property to your _ object, it would completely clobber the window.location property... generally you should just put things that you are controlling in your own namespace to be sure that it doesn't have any side-effectsBonine
Note: there seem to be some decent answers here on "leaking" variables into the global namespace. There is generally lot's of discussion on it that wouldn't be fit for a comment :)Bonine
This is some good reading material. Thank you. One last question, the 'new' keyword, does this create an instance of the function so that it isn't accessible by the Window object?Ritchey
@W3Geek yes that is essentially correct. not sure what you mean by "accessible by the window object" - but you will have access to the window object inside of the function's constructor, but it wont be bound to the this object... and elsewhere in the program you will have access to the instance, but not to any variables created inside the constructor function. does that make sense? (note - i added some stuff in my answer to address this more clearly)Bonine
As the author of the code in question, I approve of your answer and award you one upvote.Alleviative
L
6

return this gives you the ability to chain method calls. You can do some really cool and useful things like, _.show().hide(). :)

Lovash answered 15/6, 2012 at 4:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.