javascript – What is the difference between these two implementations?

Question:

I was reading some articles about patterns and I got a question in the two examples below. Suppose I have a single function that returns me an element via the ID sent as an argument. The first:

var utils = (function(){
    var self = {};

    self.by = function(id){
        return document.getElementById(id);
    };

    return {
        by: self.by
    };
})();

Where could I call the by function like this:

utils.by("campoTexto").innerHTML = "Algum Texto";

Now for a second example:

var utils2 = (function(){
    return {
      by: function(id){
          return document.getElementById(id);
      }
    };
})();

Where could I call the by function like this:

utils2.by("campoTexto").innerHTML = "Algum Texto";

My question is: What is the difference between these two implementations? In the first one, the function is implemented outside the return while in the second one it is implemented inside the return , what does that change in the code?

var utils = (function(){
    var self = {};
    
    self.by = function(id){
        return document.getElementById(id);
    };
    
    return {
        by: self.by
    };
})();


var utils2 = (function(){
    return {
      by: function(id){
          return document.getElementById(id);
      }
    };
})();

utils.by("a").innerHTML = "Usando 'utils'...";
utils2.by("b").innerHTML = "Usando 'utils2'...";
<p id='a'></p>
<p id='b'></p>

Answer:

It doesn't change anything in the example you gave… but it can be useful in other situations.

When does it matter?

This may be necessary if you want to reference the self object from within the by function, without relying on this … or else bind this more permanently using bind (eg by.bind(self) ).

The reason for this advantage is that this can change. But if the intention is to use something that doesn't change, then it will be necessary:

  • use self inside by :

     by: function() { self.qualquerCoisa... ; }

    In this case, even using call or apply to call the by method, self would still not be changed, whereas using this would change the result.

  • or else by.bind(self) :

     by: (function() { this.qualquerCoisa... ; }).bind(self)

    In this case, this will always be equal to self , not even using call / apply is possible to change the behavior.

Note that this also changes when you copy a reference to a function from one place to another, not just when using call / apply :

var utils2 = ...;
myUtils.by = utils2.by;
// o `this` passado para o `by` abaixo, será `myUtils` e não `utils2`
myUtils.by("campoTexto").innerHTML = "Algum Texto";

Why doesn't it change anything in the question example?

As I said, in your example, there is no difference between them. This is because nothing will take a self reference outside of this function.

  • self is not enclosed in the by function (not used in a closure)
  • self is not copied to the returned object

This means that there will be nothing left of self , as no reference will be left for it.

Snippets to test the possibilities

 // self original será enclausurado e retornado var modulo = (function() { var self = {}; self.by = function(id) { return this === self; }; return self; })(); escrever(modulo.by()); // true var outro = { by: modulo.by }; escrever(outro.by()); // false escrever(modulo.by.call(outro)); // false // self original será enclausurado, mas não retornado var modulo = (function() { var self = {}; self.by = function(id) { return this === self; }; return { by: self.by }; })(); escrever(modulo.by()); // false var outro = { by: modulo.by }; escrever(outro.by()); // false escrever(modulo.by.call(outro)); // false // self original será enclausurado, alterado e depois retornado var modulo = (function() { var self = {}; self.by = function(id) { return this === self; }; self = { by: self.by }; return self; })(); escrever(modulo.by()); // true var outro = { by: modulo.by }; escrever(outro.by()); // false escrever(modulo.by.call(outro)); // false // self original será enclausurado em função com bind e retornado var modulo = (function() { var self = {}; self.by = (function(id) { return this === self; }).bind(self); return self; })(); escrever(modulo.by()); // true var outro = { by: modulo.by }; escrever(outro.by()); // true escrever(modulo.by.call(outro)); // true // self original será enclausurado em função com bind, mas não retornado var modulo = (function() { var self = {}; self.by = (function(id) { return this === self; }).bind(self); return { by: self.by }; })(); escrever(modulo.by()); // true var outro = { by: modulo.by }; escrever(outro.by()); // true escrever(modulo.by.call(outro)); // true // self original será enclausurado em função com bind, alterado e depois retornado var modulo = (function() { var self = {}; self.by = (function(id) { return this === self; }).bind(self); self = { by: self.by }; return self; })(); escrever(modulo.by()); // false var outro = { by: modulo.by }; escrever(outro.by()); // false escrever(modulo.by.call(outro)); // false function escrever(valor) { document.write(valor+"<br/>"); }
Scroll to Top