如何将“对象”转换为JavaScript中的函数?

问题描述:

JavaScript允许将函数视为对象 - 如果您首先将变量定义为函数,则可以随后向该函数添加属性。你如何做相反的事情,并添加一个函数到一个“对象”?如何将“对象”转换为JavaScript中的函数?

这工作:

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

在这一点上,foo()调用函数,并foo.baz的值为 “QQQQ”。

但是,如果您先执行属性赋值部分,那么您如何随后为该变量分配一个函数?

var bar = { baz: "qqqq" }; 

现在我该怎么做才能为bar.baz安排有值“QQQQ” bar()调用函数?

+0

我不明白需要做这个。你能举一个你想要实现的具体例子吗? – Geoff 2008-09-23 22:40:38

+1

我现在无法想象第二种形式的用途。第一个对静态变量有些用处(尽管闭包也会这样做)。我主要是问,因为我想不到在不复制属性的情况下实现它的方式,这是不幸的,因为它们是平行的形式。 – mjs 2008-09-23 22:55:16

+0

听起来像你希望的那样,因为你可以将一个方法分配给一个Javascript对象,你也可以分配一个操作符重载。我不知道Javascript,所以我不知道答案,但祝你好运... – 2008-09-23 23:28:02

在这里很容易混淆,但你不能(容易或清楚地或只要我知道)做你想做的。希望这将有助于解决问题。

首先,Javascript中的每个对象都从Object对象继承。

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

其次,职能在使用Javascript对象。具体来说,它们是一个Function对象。 Function对象从Object对象继承。检出Function constructor

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

一旦你声明一个变量是一个“对象”,则不能(容易或清晰或如此据我所知),将其转换为一个函数对象。你需要声明一个类型为Function的新对象(使用函数构造函数,为变量赋一个匿名函数等),然后复制旧对象的方法的任何属性。

最后,预测一个可能的问题,即使一些东西被声明为一个函数,你也不能(据我所知)改变函数体/源。

JavaScript允许将函数作为对象处理为 - 您可以将 属性添加到函数中。你如何做 反过来,并添加一个函数到一个 对象?

您似乎有点困惑。在JavaScript中,函数对象。并且变量变量。你不会想到这个工作:

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

...所以你为什么会想到给你的变量分配功能会以某种方式保留其以前的值?也许有些注释会澄清你的东西:

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

准确地说,请参阅他对我的回答的评论 - 我认为他有点失落了... – 2008-09-23 22:40:44

似乎没有要做到这一点的标准方式,但这个工程。

但是,为什么是这个问题。

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" 

我们根本没有其他办法可以达致这, 做

x={} 
x() 

将返回 “类型的错误”。因为“x”是一个“对象”,你不能改变它。它与试图做的一样明智

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

它不起作用。 1是一个整数。整数没有数组方法。你不能做到。

使用一个临时变量:

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

终于与老性质为原始变量重新分配新功能:

var xxx = function()... 

,那么所有的特性从原来的对象复制

bar = xxx; 

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

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

我想你正在寻找这个。

也可以写成这样:

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 

对象类型是函数和对象本身是一个功能实例。

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

显示器(在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] 
} 

特别要注意的一个功能对象,function Function() { [native code] },被定义为递归关系(使用自身的递归定义)。

此外,请注意answer 124402#124402关于1[50]=5是不完整的。这样做可以将一个属性赋值给一个Number对象并且是有效的Javascript。注意,

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

显示

a fu fu bar 4 2 life ghi 

解释,并根据JavaScript的 “参与规则” 执行正确。

当然,总是有一个皱纹和清单=。当一个对象被赋值给一个变量时,它的值通常会“短路”,而不是一个完整的实体。这是布尔对象和布尔值的问题。

明确的对象标识可解决此问题。

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

“重载”是一个相当合理的Javascript锻炼和与像prototyping机制明确认可,虽然代码混淆是危险之源。

最后一点:

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

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

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

注:后写的我是如何解决这个问题的风格。我不是100%确定它在OP的情况下可用。

我发现这篇文章,同时寻找一种方法来转换在服务器上创建的对象并通过JSON/ajax交付给客户端。

这有效地使我处于与OP相同的情况,我希望将其转换为函数,以便能够在客户端上创建实例。

最后我想出了这个,这是工作(至少到目前为止):

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

然后可以像使用:

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

在我来说,我其实是想具有与结果对象实例相关联的功能,并且还能够在实例化参数时传入参数。

所以我的代码是:

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

并由此被称为:

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

,然后他们可以使用:

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