Does this method of defining JS objects use any purpose?

I support some legacy code, and I noticed that the following template is used to define objects:

var MyObject = {}; (function (root) { root.myFunction = function (foo) { //do something }; })(MyObject); 

Is there any purpose? Is this equivalent to just doing the following?

 var MyObject = { myFunction : function (foo) { //do something }; }; 

I am not going to enter the sacred quest to reorganize the entire code base to my liking, but I would really like to understand the reason for this workaround for defining objects.

Thank!

+86
javascript javascript-objects
Nov 06 '14 at 20:02
source share
6 answers

He called the module template http://toddmotto.com/mastering-the-module-pattern/

The main reason is to create truly private methods and variables. In your case, this does not make sense, since it does not hide any implementation details.

Here is an example when it makes sense to use a module template.

 var MyNameSpace = {}; (function(ns){ // The value variable is hidden from the outside world var value = 0; // So is this function function adder(num) { return num + 1; } ns.getNext = function () { return value = adder(value); } })(MyNameSpace); var id = MyNameSpace.getNext(); // 1 var otherId = MyNameSpace.getNext(); // 2 var otherId = MyNameSpace.getNext(); // 3 

If you just used a direct object, adder and value will become public.

 var MyNameSpace = { value: 0, adder: function(num) { return num + 1; }, getNext: function() { return this.value = this.adder(this.value); } } 

And you can break it by doing something like

 MyNameSpace.getNext(); // 1 MyNameSpace.value = 0; MyNameSpace.getNext(); // 1 again delete MyNameSpace.adder; MyNameSpace.getNext(); // error undefined is not a function 

But with the module version

 MyNameSpace.getNext(); // 1 // Is not affecting the internal value, it creating a new property MyNameSpace.value = 0; MyNameSpace.getNext(); // 2, yessss // Is not deleting anything delete MyNameSpace.adder; MyNameSpace.getNext(); // no problemo, outputs 3 
+114
Nov 06 '14 at 20:05
source share

The goal is to limit the availability of functions in closure to help other scripts execute code on it. By wrapping around a closure , you redefine the execution area for all code inside the closure and effectively create a closed scope. See this article for more information:

http://lupomontero.com/using-javascript-closures-to-create-private-scopes/

From the article:

One of the most well-known problems in JavaScript is its dependence on global reach, which basically means that any variables that you declare outside a function live in the same namespace: an ominous window object. Due to the nature of the web pages, many scripts from different sources can (and will) work on the same page, the overall global scale, and this can be really very bad, because it can lead to name conflicts (variables with the same name are overwritten) and security concerns. To minimize the problem, we can use Explicit JavaScripts scripts to create private areas where we can make sure that our variables are invisible to other scripts on the page.





The code:

 var MyObject = {}; (function (root) { function myPrivateFunction() { return "I can only be called from within the closure"; } root.myFunction = function (foo) { //do something }; myPrivateFunction(); // returns "I can only be called from within the closure" })(MyObject); myPrivateFunction(); // throws error - undefined is not a function 
+21
Nov 06 '14 at 20:05
source share

In the particular case that you are showing, there is no significant difference in terms of functionality or visibility.

The source coder probably took this approach as a kind of template, allowing it to define private variables that could be used in defining things like myFunction :

 var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; // <-- private variable root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); 

This avoids the calculation of seconds_per_day every time a function is called, and also prevents it from polluting the global area.

However, nothing is fundamentally different from this and just saying

 var MyObject = function() { var seconds_per_day = 24 * 60 * 60; return { myFunction: function(foo) { return seconds_per_day; } }; }(); 

The original encoder may have preferred to be able to add functions to the object using the declarative syntax root.myFunction = function rather than the syntax of the object / property myFunction: function . But this difference mainly depends on preferences.

However, the structure taken by the source encoder has the advantage that properties / methods can be easily added elsewhere in the code:

 var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); (function(root) { var another_private_variable = Math.pi; root.myFunction2 = function(bar) { }; })(MyObject); 

Bottom line, there is no need to apply this approach if you do not need it, but there is no need to change it, since it works great and actually has some advantages.

+5
Nov 06 '14 at 20:24
source share

Adavtages:

1 . The first template can be used as a module that takes an object and returns this object with some modification. In other words, you can define such a module as follows:

 var module = function (root) { root.myFunction = function (foo) { //do something }; } 

And use it like:

 var obj = {}; module(obj); 

Thus, an advantage may be that this module can be reused for later use.




2 . In the first template, as mentioned earlier, you can define a private area for storing your personal items, such as private properties and methods. For example, consider these fragment codes

 (function (root) { // this plays as a private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(MyObject); 



3 . Another advantage may be this template, which can be used to add a method or property to all types of objects, such as arrays, literals, functions

 function sum(a, b){ return a + b; } (function (root) { // this plays as a private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(sum); console.log(sum(1, 2)); // 3 console.log(sum.multiply(4)); // 12 

Note. In my opinion, the main advantage may be the second (creation of a private field)

+5
Nov 07 '14 at 2:56
source share

advantages:

  • supports variables in a private area.

  • You can extend the functionality of an existing object.

  • increased productivity.

I think that three simple simple points are enough to follow these rules. And keeping it simple is nothing but writing internal functions.

+5
Nov 07 '14 at 18:07
source share

This template provides an area in which you can define helper functions that are not visible in the global area:

 (function (root) { function doFoo() { ... }; root.myFunction = function (foo) { //do something doFoo(); //do something else }; })(MyObject); 

doFoo is local to an anonymous function; it cannot be referenced externally.

+4
Nov 06 '14 at 20:14
source share



All Articles