2008-09-23 13 views
33

JavaScript permite que las funciones se traten como objetos: si primero define una variable como una función, puede agregar posteriormente propiedades a esa función. ¿Cómo se hace al revés y se agrega una función a un "objeto"?¿Cómo convertir un "objeto" en una función en JavaScript?

Esto funciona:

var foo = function() { return 1; }; 
foo.baz = "qqqq"; 

En este punto, foo() llama a la función, y foo.baz tiene el valor "qqqq".

Sin embargo, si primero hace la parte de asignación de propiedad, ¿cómo asigna una función a la variable?

var bar = { baz: "qqqq" }; 

¿Qué puede hacer ahora para arreglar para bar.baz tener el valor "qqqq" bar() y llamar a la función?

+0

No entiendo la necesidad de hacer esta. ¿Puedes dar un ejemplo concreto de lo que estás tratando de lograr? – Geoff

+1

No puedo pensar en un uso para la segunda forma en este momento. El primero es algo útil para variables estáticas (aunque los cierres también lo harán). Principalmente estoy preguntando porque no puedo pensar en una forma de lograrlo sin copiar las propiedades, lo cual es desafortunado ya que son formas paralelas. – mjs

+0

Parece que esperas que porque puedes asignar un método a un objeto Javascript, también puedes asignar una sobrecarga al operador. No sé Javascript así que no sé la respuesta, pero buena suerte ... –

Respuesta

26

Es fácil confundirse aquí, pero no se puede (fácil o claramente o en la medida en que saber) haz lo que quieras Espero que esto ayude a aclarar las cosas.

En primer lugar, todos los objetos en Javascript heredan del objeto Object.

//these do the same thing 
var foo = new Object(); 
var bar = {}; 

En segundo lugar, funciona SON objetos en Javascript. Específicamente, son un objeto Function. El objeto Function hereda del objeto Object. Partida de los Function constructor

var foo = new Function(); 
var bar = function(){}; 
function baz(){}; 

Una vez que se declara una variable a ser un "objeto" puede convertir no (fácilmente o con claridad o por lo que yo sé) en un objeto de función. Debería declarar un nuevo objeto de tipo Función (con el constructor de función, asignando a una variable una función anónima, etc.) y copiar las propiedades de los métodos de su antiguo objeto.

Finalmente, anticipándome a una posible pregunta, incluso cuando algo se declara como una función, no se puede (hasta donde yo sé) cambiar la función Cuerpo/fuente.

+2

solo una nota al margen, no puede cambiar la fuente, pero usted PUEDE redefinir la función (por ejemplo, sobrescribirla) en cualquier momento. – scunliffe

+0

Todos los objetos heredan de 'Object.prototype' (si no se establece explícitamente en otro objeto). Los objetos de función heredan de 'Function.prototype'. –

0

JavaScript permite que las funciones sean tratados como objetos - se puede añadir una propiedad a una función. ¿Cómo se hace al revés y se agrega una función a un objeto ?

Parece ser un poco confundido. Las funciones, en JavaScript, son objetos. Y variables son variable. No se podía esperar que esto funcione:

var three = 3; 
three = 4; 
assert(three === 3); 

... ¿por qué se puede esperar que la asignación de una función a la variable de alguna manera de preservar su valor anterior? Tal vez algunas anotaciones aclararán las cosas para usted:

// assigns an anonymous function to the variable "foo" 
var foo = function() { return 1; }; 
// assigns a string to the property "baz" on the object 
// referenced by "foo" (which, in this case, happens to be a function) 
foo.baz = "qqqq"; 
+0

Exactamente, veo su comentario en mi respuesta - Creo que está un poco perdido ... –

+1

La segunda tarea en la pregunta original fue confusa; He eliminado esto ahora. Después de 'bar = {baz:" qqqq "}', ¿cómo se puede organizar para que 'bar()' se pueda llamar como una función? – mjs

+0

No es así. Acabas de asignarle un objeto que * NO ES * una función: puedes volver a empezar (y asignarle una función), o puedes seguir con tu vida. – Shog9

20

No parece ser una forma estándar de hacerlo, pero esto funciona.

POR QUÉ sin embargo, es la pregunta.

function functionize(obj , func) 
{ 
    out = func; 
    for(i in obj){ out[i] = obj[i]; } ; 
    return out; 
} 

x = { a: 1, b: 2 }; 
x = functionize(x , function(){ return "hello world"; }); 
x() ==> "hello world" 

Simplemente no hay otra manera de lograr esto, haciendo

x={} 
x() 

devolverá un "error de tipo". porque "x" es un "objeto" y no puedes cambiarlo. es tan sensato como tratar de hacer

x = 1 
x[50] = 5 
print x[50] 

no funcionará. 1 es un número entero. los enteros no tienen métodos de matriz. no puedes hacerlo

+5

Por qué esto funciona no es un misterio en absoluto. Solo estás reemplazando x con la función. –

+0

Sí, pero esto también copia todas las propiedades de 'x' en la función antes de reemplazar x con la función. Aunque creo (han pasado algunos años desde que contesté esto) que el "Por qué" es más "Una función es un objeto es un poco confuso" –

1

utilizar una variable temporal:

var xxx = function()... 

luego copiar todas las propiedades del objeto original:

for (var p in bar) { xxx[p] = bar[p]; } 

finalmente volver a asignar la nueva función con las antiguas propiedades a la variable original:

bar = xxx; 
-1
var bar = { 
    baz: "qqqq", 
    runFunc: function() { 
     return 1; 
    } 
}; 

alert(bar.baz); // should produce qqqq 
alert(bar.runFunc()); // should produce 1 

Creo que usted está buscando esto.

también se puede escribir así:

function Bar() { 
    this.baz = "qqqq"; 
    this.runFunc = function() { 
     return 1; 
    } 
} 

nBar = new Bar(); 

alert(nBar.baz); // should produce qqqq 
alert(nBar.runFunc()); // should produce 1 
+0

Esto no toca en absoluto la pregunta original, que era cómo convertir un objeto simple en una función ejecutable. Su respuesta simplemente asigna una función como propiedad de un objeto. – krb686

2

tipos de objetos son funciones y un objeto en sí es una ejemplificación función.

javascript:alert([Array, Boolean, Date, Function, 
         Number, Object, RegExp, String].join('\n\n')) 

displays (en Firefox):

function Array() { 
    [native code] 
} 

function Boolean() { 
    [native code] 
} 

function Date() { 
    [native code] 
} 

function Function() { 
    [native code] 
} 

function Number() { 
    [native code] 
} 

function Object() { 
    [native code] 
} 

function RegExp() { 
    [native code] 
} 

function String() { 
    [native code] 
} 

En particular, tenga en cuenta un objeto Function, function Function() { [native code] }, se define como una relación de recurrencia (una definición recursiva usando sí mismo).

Además, tenga en cuenta que el answer 124402#124402 está incompleto con respecto a 1[50]=5. Esto SÍ asigna una propiedad a un objeto Number y ES un Javascript válido. Observar,

javascript: 
    alert([ [].prop="a", true.sna="fu", (new Date()).tar="fu", 
        function(){}.fu="bar", 123[40]=4, {}.forty=2, 
         /(?:)/.forty2="life", "abc".def="ghi" ].join("\t")) 

pantallas

a fu fu bar 4 2 life ghi 

interpretar y ejecutar correctamente de acuerdo con Javascript de "Reglas de compromiso".

Por supuesto, siempre hay una arruga y se manifiesta por =. Un objeto a menudo se "cortocircuita" a su valor en lugar de una entidad de pleno derecho cuando se asigna a una variable.Este es un problema con los objetos booleanos y los valores booleanos.

La identificación explícita de objetos resuelve este problema.

javascript: x=new Number(1); x[50]=5; alert(x[50]); 

"sobrecarga" es un buen ejercicio legítimo Javascript y apoyado explícitamente con mecanismos como prototyping pesar de ofuscación de código puede ser un peligro.

Nota final:

javascript: alert( 123 . x = "not" ); 

javascript: alert((123). x = "Yes!"); /*()'s elevate to full object status */ 
1
var A = function(foo) {                          
    var B = function() {                          
    return A.prototype.constructor.apply(B, arguments); 
    }; 
    B.prototype = A.prototype;                         
    return B;                             
}; 
+7

¿Qué está haciendo exactamente esto? – netpoetica

0

NB: Mensaje escrito en el estilo de cómo he resuelto el problema. No estoy 100% seguro de que sea utilizable en el caso del OP.

Encontré esta publicación mientras buscaba una forma de convertir objetos creados en el servidor y entregados al cliente por JSON/ajax.

Lo que efectivamente me dejó en la misma situación que el OP, un objeto que quería convertir en una función para poder crear instancias de él en el cliente.

Al final se me ocurrió esto, que está trabajando (al menos hasta ahora):

var parentObj = {} 

parentObj.createFunc = function (model) 
{ 
    // allow it to be instantiated 
    parentObj[model._type] = function() 
    { 
     return (function (model) 
     { 
      // jQuery used to clone the model 
      var that = $.extend(true, null, model); 
      return that; 
     })(model); 
    } 
} 

que luego puede ser utilizado como:

var data = { _type: "Example", foo: "bar" }; 
parentObject.createFunc(data); 
var instance = new parentObject.Example(); 

En mi caso, en realidad quería tener funciones asociadas con las instancias de objetos resultantes, y también poder pasar parámetros en el momento de instanciarlo.

Así que mi código era:

var parentObj = {}; 
// base model contains client only stuff 
parentObj.baseModel = 
{ 
    parameter1: null, 
    parameter2: null, 
    parameterN: null, 
    func1: function() 
    { 
     return this.parameter2; 
    }, 
    func2: function (inParams) 
    { 
     return this._variable2; 
    } 
} 

// create a troop type 
parentObj.createModel = function (data) 
{ 
    var model = $.extend({}, parentObj.baseModel, data); 
    // allow it to be instantiated 
    parentObj[model._type] = function(parameter1, parameter2, parameterN) 
    { 
     return (function (model) 
     { 
      var that = $.extend(true, null, model); 
      that.parameter1 = parameter1; 
      that.parameter2 = parameter2; 
      that.parameterN = parameterN; 
      return that; 
     })(model); 
    } 
} 

y fue llamado así:

// models received from an AJAX call 
var models = [ 
{ _type="Foo", _variable1: "FooVal", _variable2: "FooVal" }, 
{ _type="Bar", _variable1: "BarVal", _variable2: "BarVal" }, 
{ _type="FooBar", _variable1: "FooBarVal", _variable2: "FooBarVal" } 
]; 

for(var i = 0; i < models.length; i++) 
{ 
    parentObj.createFunc(models[i]); 
} 

Y luego se puede utilizar:

var test1 = new parentObj.Foo(1,2,3); 
var test2 = new parentObj.Bar("a","b","c"); 
var test3 = new parentObj.FooBar("x","y","z"); 

// test1.parameter1 == 1 
// test1._variable1 == "FooVal" 
// test1.func1() == 2 

// test2.parameter2 == "a" 
// test2._variable2 == "BarVal" 
// test2.func2() == "BarVal" 

// etc 
Cuestiones relacionadas