Pergunta

JavaScript permite que as funções a serem tratados como objetos - se você primeiro definir uma variável como uma função, você pode posteriormente adicionar propriedades a essa função. Como você faz o inverso, e adicionar uma função para um "objeto"?

Isso funciona:

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

Neste ponto, foo() chama a função, e foo.baz tem o valor "qqqq".

No entanto, se você faz parte atribuição de propriedade em primeiro lugar, como você, posteriormente, atribuir uma função à variável?

var bar = { baz: "qqqq" };

O que posso fazer agora para mandar para bar.baz ter o valor "qqqq" e bar() para chamar a função?

Foi útil?

Solução

É fácil ser confundido aqui, mas você não pode (facilmente ou claramente ou tanto quanto eu sei) fazer o que quiser. Esperemos que isto irá ajudar a esclarecer as coisas.

Em primeiro lugar, cada objeto herda Javascript do objeto Object.

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

Em segundo lugar, as funções SÃO objetos em Javascript. Especificamente, eles são um objeto Function. Os herda Função objecto a partir do objecto objecto. Checkout da função de construtor

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

Uma vez que você declarar uma variável a ser um "objeto" você não pode (facilmente ou claramente ou tanto quanto eu sei) convertê-lo para um objeto Function. Você precisaria declarar um novo objecto do tipo de função (com o construtor função, atribuindo uma variável uma função anônima etc.), e copiar todas as propriedades dos métodos do seu objeto antigo.

Finalmente, antecipando uma possível questão, mesmo quando algo é declarado como uma função, você pode não (tanto quanto eu sei) mudar o functionBody / fonte.

Outras dicas

Não parece ser uma maneira padrão de fazer isso, mas isso funciona.

Por entanto, é a questão.

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" 

Simplesmente não há outra maneira de conseguir isso, fazendo

x={}
x() 

retornará um "erro de tipo". porque "x" é um "objeto" e você não pode mudá-lo. sua sobre tão sensível quanto tentando fazer

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

não vai funcionar. 1 é um número inteiro. inteiros não têm métodos de array. você não pode fazer isso.

tipos de objetos são funções e um objeto em si é uma instanciação função.

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

monitores (no 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]
}

Em particular, note um objeto Function, function Function() { [native code] }, é definido como uma relação de recorrência (uma definição recursiva utilizando-se).

Além disso, nota que a responder 124402 # 124402 está incompleta sobre 1[50]=5. Isso não atribuir uma propriedade a um objeto Number e é válido Javascript. Observe,

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"))

exibe

a   fu  fu  bar 4   2   life    ghi

interpretar e executar corretamente de acordo com Javascript de "Rules of Engagement".

Claro que há sempre uma ruga e manifesta por =. Um objeto é muitas vezes "curto-circuito" para o seu valor, em vez de uma entidade de pleno direito quando atribuído a uma variável. Este é um problema com booleana objetos e valores booleanos.

identificação explícita objeto resolve este problema.

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

"Sobrecarga" é bastante um exercício Javascript legítimo e explicitamente conter mecanismos como prototyping embora ofuscação de código pode ser um perigo.

Nota final:

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

javascript: alert( (123). x = "Yes!" );  /* ()'s elevate to full object status */

Use uma variável temporária:

var xxx = function()...

, em seguida, copiar todas as propriedades do objeto original:

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

finalmente transferir a nova função com as antigas propriedades para a variável original:

bar = xxx;
var A = function(foo) {                                                                                                      
  var B = function() {                                                                                                       
    return A.prototype.constructor.apply(B, arguments);
  };
  B.prototype = A.prototype;                                                                                                 
  return B;                                                                                                                  
}; 

JavaScript permite que as funções a ser tratadas como objetos - você pode adicionar um propriedade para uma função. Como vai o reverso, e adiciona uma função para uma objeto?

Você parece estar um pouco confuso. Funções, em JavaScript, são objetos. E variáveis ?? são variável . Você não esperaria que isso funcione:

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

... então por que seria de esperar que a atribuição de uma função para a variável, de alguma forma preservar o seu valor anterior? Talvez algumas anotações irá esclarecer as coisas para você:

// 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";

NB: Pós-escrito no estilo de como eu resolvi o problema. Eu não estou 100% de certeza que é utilizável no caso do OP.

Eu encontrei este post, enquanto procura uma maneira de converter objetos criados no servidor e entregue ao cliente por JSON / ajax.

O que efetivamente me deixou na mesma situação que o OP, um objeto que eu queria ser convertido em uma função, de modo a ser capaz de criar instâncias dele no cliente.

No final, eu vim com isso, o que está funcionando (pelo menos até agora):

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);
    }
}

O que pode então ser usada como:

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

No meu caso eu realmente queria ter funções associadas com as instâncias de objetos resultantes e também ser capaz de passar parâmetros no momento da instanciação-lo.

Então, o meu código foi:

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);
    }
}

E foi chamado assim:

// 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]);
}

E, em seguida, eles podem ser usados:

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
var bar = { 
    baz: "qqqq",
    runFunc: function() {
        return 1;
    }
};

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

Eu acho que você está procurando isso.

também pode ser escrito assim:

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top