JavaScript允许将函数视为对象 - 如果首先将变量定义为函数,则可以随后向该函数添加属性。你如何反过来,并向“对象”添加一个函数?
这有效:
var foo = function() { return 1; };
foo.baz = "qqqq";
此时,foo()
调用该函数,foo.baz
的值为“qqqq”。
但是,如果首先执行属性赋值部分,那么如何随后将函数赋值给变量?
var bar = { baz: "qqqq" };
我现在可以做些什么来安排bar.baz
使用值“qqqq”和 bar()
来调用该函数?
答案 0 :(得分:27)
这里很容易混淆,但你不能(轻松或清楚地或据我所知)做你想做的事。希望这有助于澄清事情。
首先,Javascript中的每个对象都继承自Object对象。
//these do the same thing
var foo = new Object();
var bar = {};
其次,Javascript中的函数 ARE 对象。具体来说,它们是一个Function对象。 Function对象继承自Object对象。查看Function constructor
var foo = new Function();
var bar = function(){};
function baz(){};
一旦将变量声明为“对象”,就不能(轻松地或清楚地或据我所知)将其转换为Function对象。您需要声明一个类型为Function的新Object(使用函数构造函数,赋值变量和匿名函数等),并复制旧对象的方法属性。
最后,预测一个可能的问题,即使某事被宣布为函数,你也不能(据我所知)改变functionBody / source。
答案 1 :(得分:23)
似乎没有一种标准的方法可以做到这一点,但这很有效。
为什么这是个问题。
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是整数。整数没有数组方法。你不能成功。
答案 2 :(得分:2)
对象类型是函数,对象本身是函数实例化。
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 Function() { [native code] }
被定义为递归关系(使用自身的递归定义)。
另请注意,1[50]=5
与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"))
不完整。这个DOES将属性分配给Number对象和IS有效的Javascript。观察,
a fu fu bar 4 2 life ghi
显示器
=
根据Javascript的“参与规则”正确解释和执行。
当然javascript: x=new Number(1); x[50]=5; alert(x[50]);
总会出现皱纹和表现。当分配给变量时,对象通常会“短路”到其值而不是完整的实体。这是布尔对象和布尔值的问题。
显式对象识别解决了这个问题。
prototyping
“重载”是一个非常合法的Javascript练习,并且使用javascript: alert( 123 . x = "not" );
javascript: alert( (123). x = "Yes!" ); /* ()'s elevate to full object status */
等机制明确认可,但代码混淆可能是一种危险。
最后的说明:
{{1}}
答案 3 :(得分:1)
使用临时变量:
var xxx = function()...
然后从原始对象复制所有属性:
for (var p in bar) { xxx[p] = bar[p]; }
最后将新函数与旧属性重新分配给原始变量:
bar = xxx;
答案 4 :(得分:1)
var A = function(foo) {
var B = function() {
return A.prototype.constructor.apply(B, arguments);
};
B.prototype = A.prototype;
return B;
};
答案 5 :(得分:0)
你似乎有点困惑。函数,在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";
答案 6 :(得分:0)
注意:帖子以我如何解决问题的方式写成。我并非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
答案 7 :(得分:-1)
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