javascript - metodos - ¿Esta forma de definir objetos JS tiene algún propósito?
recorrer array de objetos javascript (6)
El primer patrón se puede usar como un módulo que toma un objeto y lo devuelve con algunas modificaciones. En otras palabras, puede definir dichos módulos de la siguiente manera.
var module = function (root) { root.myFunction = function (foo) { //do something }; }
Y úsalo como:
var obj = {}; module(obj);
Entonces, una ventaja podría ser la reutilización de este módulo para usos posteriores.
En el primer patrón, puede definir un ámbito privado para almacenar sus cosas privadas, como propiedades privadas y métodos. Por ejemplo, considere este fragmento:
(function (root) { // A private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(MyObject);
Este patrón se puede usar para agregar un método o propiedad a todos los tipos de objetos, tales como matrices, literales de objetos, funciones.
function sum(a, b) { return a + b; } (function (root) { // 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
En mi opinión, la principal ventaja podría ser la segunda (creando un ámbito privado)
Estoy manteniendo un código heredado y me he dado cuenta de que se usa el siguiente patrón para definir objetos:
var MyObject = {};
(function (root) {
root.myFunction = function (foo) {
//do something
};
})(MyObject);
¿Hay algún propósito para esto? ¿Es equivalente a simplemente hacer lo siguiente?
var MyObject = {
myFunction : function (foo) {
//do something
};
};
No estoy dispuesto a embarcarme en una santa misión para refactorizar toda la base de código a mis gustos, pero realmente me gustaría entender la razón detrás de esa forma indirecta de definir objetos.
¡Gracias!
El objetivo es limitar la accesibilidad de las funciones dentro del cierre para ayudar a evitar que otros scripts ejecuten código en él. Al envolverlo en un cierre , está redefiniendo el alcance de la ejecución de todo el código dentro del cierre y creando efectivamente un ámbito privado. Vea este artículo para más información:
http://lupomontero.com/using-javascript-closures-to-create-private-scopes/
Del artículo:
Uno de los problemas más conocidos en JavaScript es su dependencia de un alcance global, lo que básicamente significa que cualquier variable que declare fuera de una función vive en el mismo espacio de nombre: el ominoso objeto de ventana. Debido a la naturaleza de las páginas web, muchos scripts de diferentes fuentes pueden (y se ejecutarán) en la misma página compartir un alcance global común y esto puede ser realmente algo malo ya que puede llevar a colisiones de nombres (variables con los mismos nombres sobreescrito) y problemas de seguridad. Para minimizar el problema, podemos utilizar los cierres potentes de JavaScript para crear ámbitos privados donde podemos estar seguros de que nuestras variables son invisibles para otras secuencias de comandos en la página.
Código:
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
En el caso particular que muestra, no hay una diferencia significativa en términos de funcionalidad o visibilidad.
Es probable que el codificador original haya adoptado este enfoque como una especie de plantilla que le permita definir variables privadas que podrían usarse en la definición de cosas como myFunction
:
var MyObject = {};
(function(root) {
var seconds_per_day = 24 * 60 * 60; // <-- private variable
root.myFunction = function(foo) {
return seconds_per_day;
};
})(MyObject);
Esto evita calcular seconds_per_day
cada vez que se llama a la función, al tiempo que evita que se contamine el alcance global.
Sin embargo, no hay nada esencialmente diferente de eso y solo digo
var MyObject = function() {
var seconds_per_day = 24 * 60 * 60;
return {
myFunction: function(foo) {
return seconds_per_day;
}
};
}();
El codificador original puede haber preferido poder agregar funciones al objeto utilizando la sintaxis declarativa de la root.myFunction = function
, en lugar de la sintaxis de objeto / propiedad de la myFunction: function
. Pero esa diferencia es principalmente una cuestión de preferencia.
Sin embargo, la estructura tomada por el codificador original tiene la ventaja de que las propiedades / métodos se pueden agregar fácilmente en cualquier parte del código:
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);
En pocas palabras, no es necesario adoptar este enfoque si no es necesario, pero tampoco hay necesidad de cambiarlo, ya que funciona perfectamente y tiene algunas ventajas.
Este patrón proporciona un ámbito en el que puede definir funciones auxiliares que no son visibles en el ámbito global:
(function (root) {
function doFoo() { ... };
root.myFunction = function (foo) {
//do something
doFoo();
//do something else
};
})(MyObject);
doFoo
es local para la función anónima, no se puede hacer referencia desde el exterior.
Se llama el patrón del módulo http://toddmotto.com/mastering-the-module-pattern/
La razón principal es que crees métodos y variables verdaderamente privados. En su caso, no es significativo porque no está ocultando ningún detalle de implementación.
Aquí hay un ejemplo donde tiene sentido usar el patrón del módulo.
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
Mientras que si acaba de usar un objeto directo, el adder
y el value
se volverían públicos
var MyNameSpace = {
value: 0,
adder: function(num) {
return num + 1;
},
getNext: function() {
return this.value = this.adder(this.value);
}
}
Y podrías romperlo haciendo cosas como
MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function
Pero con la versión del módulo
MyNameSpace.getNext(); // 1
// Is not affecting the internal value, it''s creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3
ventajas:
mantiene variables en ámbito privado.
puede extender la funcionalidad del objeto existente.
el rendimiento aumenta
Creo que los tres puntos simples anteriores son suficientes para seguir esas reglas. Y para mantenerlo simple, no es más que escribir funciones internas.