recorrer objetos objeto metodos eliminar elemento crear buscar array agregar javascript oop google-chrome joose

metodos - recorrer array de objetos javascript



Cómo establecer dinámicamente un nombre de función/objeto en Javascript tal como se muestra en Chrome (7)

Creo que esta es la mejor manera de establecer dinámicamente el nombre de una función:

Function.prototype.setName = function (newName) { Object.defineProperty(this,''name'', { get : function () { return newName; } }); }

Ahora solo necesita llamar al método setName

function foo () { } foo.name; // returns ''foo'' foo.setName(''bar''); foo.name; // returns ''bar'' foo.name = ''something else''; foo.name; // returns ''bar'' foo.setName({bar : 123}); foo.name; // returns {bar : 123}

Esto es algo que me ha estado molestando con el depurador de Google Chrome y me preguntaba si habría alguna forma de solucionarlo.

Estoy trabajando en una gran aplicación de Javascript, usando muchos JS orientados a objetos (usando el framework Joose ), y cuando depuro mi código, todas mis clases reciben un valor de visualización inicial no sensitivo. Para ver lo que quiero decir, prueba esto en la consola de Chrome:

var F = function () {}; var myObj = new F(); console.log(myObj);

La salida debe ser una sola línea que puedes expandir para ver todas las propiedades de myObj , pero lo primero que ves es solo ▶ F

Mi problema es que debido a mi marco OO, cada objeto instanciado recibe el mismo ''nombre'' . El código que se ve responsable de esto es así:

getMutableCopy : function (object) { var f = function () {}; f.prototype = object; return new f(); }

Lo que significa que en el depurador, la vista inicial siempre es ▶ f .

Ahora, realmente no quiero cambiar nada acerca de cómo Joose instancia objetos (getMutableCopy ...?) , Pero si hubiera algo que pudiera agregar a esto para poder proporcionar mi propio nombre, sería genial.

Algunas cosas que he visto, pero que no he podido conseguir con:

> function foo {} > foo.name "foo" > foo.name = "bar" "bar" > foo.name "foo" // <-- looks like it is read only


normalmente usas window[name] como

var name ="bar"; window["foo"+name] = "bam!"; foobar; // "bam!"

que te llevaría a una función como:

function getmc (object, name) { window[name] = function () {}; window[name].prototype = object; return new window[name](); }

pero entonces

foo = function(){}; foobar = getmc(foo, "bar"); foobar; // ▶ window foobar.name; // foo x = new bar; x.name; // foo .. not even nija''ing the parameter works

y dado que no puede evaluar una declaración de devolución ( eval("return new name()"); ), creo que está atrapado


Esto no resolverá totalmente su problema, pero sugeriría anular el método toString en el prototipo de la clase. Por ejemplo:

my_class = function () {} my_class.prototype.toString = function () { return ''Name of Class''; }

Todavía verá el nombre de clase original si ingresa una instancia de my_class directamente en la consola (no creo que sea posible hacer algo al respecto), pero obtendrá el buen nombre en los mensajes de error, que encuentro muy útil. Por ejemplo:

a = new my_class() a.does_not_exist()

Aparecerá el mensaje de error: "TypeError: el nombre del objeto de clase no tiene el método ''does_not_exist''"


He estado jugando con esto durante las últimas 3 horas y finalmente lo he conseguido al menos un poco elegante usando la nueva función como se sugiere en otros hilos:

/** * JavaScript Rename Function * @author Nate Ferrero * @license Public Domain * @date Apr 5th, 2014 */ var renameFunction = function (name, fn) { return (new Function("return function (call) { return function " + name + " () { return call(this, arguments) }; };")())(Function.apply.bind(fn)); }; /** * Test Code */ var cls = renameFunction(''Book'', function (title) { this.title = title; }); new cls(''One Flew to Kill a Mockingbird'');

Si ejecuta el código anterior, debería ver el siguiente resultado en su consola:

Book {title: "One Flew to Kill a Mockingbird"}


Aunque es feo, puedes hacer trampa a través de eval ():

function copy(parent, name){ name = typeof name===''undefined''?''Foobar'':name; var f = eval(''function ''+name+''(){};''+name); f.prototype = parent; return new f(); } var parent = {a:50}; var child = copy(parent, ''MyName''); console.log(child); // Shows ''MyName'' in Chrome console.

Cuidado: ¡solo puedes usar nombres que serían válidos como nombres de funciones!

Adición: Para evitar la eval en cada instanciación de objetos, use un caché:

function Cache(fallback){ var cache = {}; this.get = function(id){ if (!cache.hasOwnProperty(id)){ cache[id] = fallback.apply(null, Array.prototype.slice.call(arguments, 1)); } return cache[id]; } } var copy = (function(){ var cache = new Cache(createPrototypedFunction); function createPrototypedFunction(parent, name){ var f = eval(''function ''+name+''(){};''+name); f.prototype = parent; return f; } return function(parent, name){ return new (cache.get(name, parent, typeof name===''undefined''?''Foobar'':name)); }; })();


Object.defineProperty(fn, "name", { value: "New Name" });

Hará el truco y es la solución más eficiente. No eval tampoco.


Similar a la respuesta @ Piercey4, pero también tuve que establecer el name para la instancia:

function generateConstructor(newName) { function F() { // This is important: this.name = newName; }; Object.defineProperty(F, ''name'', { value: newName, writable: false }); return F; } const MyFunc = generateConstructor(''MyFunc''); const instance = new MyFunc(); console.log(MyFunc.name); // prints ''MyFunc'' console.log(instance.name); // prints ''MyFunc''