【问题标题】:How to convert an "object" into a function in JavaScript?如何在 JavaScript 中将“对象”转换为函数?
【发布时间】:2023-04-09 18:48:01
【问题描述】:

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

这行得通:

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

此时foo()调用函数,foo.baz的值为“qqqq”。

但是,如果你先做属性赋值部分,那么接下来如何给变量赋值呢?

var bar = { baz: "qqqq" };

我现在可以做些什么来安排bar.baz 具有值“qqqq” bar() 调用函数?

【问题讨论】:

  • 我不明白这样做的必要性。你能举一个具体的例子来说明你想要达到的目标吗?
  • 我现在想不出第二种形式的用途。第一个对于静态变量有些用处(尽管闭包也可以)。我主要是问,因为我想不出不复制属性的方法来实现它,这是不幸的,因为它们是并行形式。
  • 听起来您希望因为您可以将方法分配给 Javascript 对象,因此您也可以分配运算符重载。我不懂 Javascript,所以我不知道答案,但祝你好运......
  • 这似乎是一个合理的问题,我发现自己想要多次这样做。大概需要将对象的原型从Object.prototype 更改为Function.prototype。或许先创建函数然后传递对象的属性会更容易。
  • 我用它从服务器端生成的json对象继承了ko viewmodel ctr函数

标签: javascript function properties


【解决方案1】:

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

【讨论】:

  • 原题中的第二个作业让人困惑;我现在已经删除了这个。在bar = { baz: "qqqq" } 之后,如何安排bar() 作为函数调用?
  • 你没有。您刚刚为其分配了一个不是函数的对象 - 您可以重新开始(并为其分配一个函数),或者您可以继续您的生活。
  • 让我试着换一种说法:你没有将函数命名为“bar”,就像我将 3 命名为“three”一样。您只是将文字分配给变量,并且该变量可以随时重新分配给其他任何东西。也许你的困惑来自对 .运营商?
  • 这个问题对我来说似乎很有意义。尽管他说“为变量分配一个函数”,但他似乎在问(我将使用一些 C++ 术语)如何将方法 operator() 分配给他的对象。在我看来,这不是一个坏问题,即使答案是“不”。
【解决方案2】:

似乎没有标准的方法来做到这一点,但这是可行的。

为什么,这是个问题。

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 是整数。整数没有数组方法。你做不到。

【讨论】:

  • 为什么这样有效一点也不神秘。您只是将 x 替换为函数。
  • 是的,但这也会在将 x 替换为函数之前将 x 的所有属性复制到函数中。虽然我认为(我回答这个问题已经有几年了)“为什么”更像是“一个函数是一个对象有点令人困惑”
【解决方案3】:

使用临时变量:

var xxx = function()...

然后复制原始对象的所有属性:

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

最终将具有旧属性的新函数重新分配给原始变量:

bar = xxx;

【讨论】:

    【解决方案4】:

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

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

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

    其次,函数 ARE Javascript 中的对象。具体来说,它们是一个 Function 对象。 Function 对象继承自 Object 对象。查看Function constructor

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

    一旦将变量声明为“对象”,就不能(容易或清楚地或据我所知)将其转换为函数对象。您需要声明一个 Function 类型的新对象(使用函数构造函数,为变量分配匿名函数等),并从旧对象复制方法的任何属性。

    最后,预料到一个可能的问题,即使将某些东西声明为函数,您也不能(据我所知)更改 functionBody/source。

    【讨论】:

    • 只是附注,您无法更改源,但您可以随时重新定义功能(例如覆盖它)。
    • 所有对象都继承自Object.prototype(如果没有明确设置为另一个对象)。函数对象继承自Function.prototype
    【解决方案5】:
    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
    

    【讨论】:

    • 这根本不涉及原始问题,即如何将普通对象转换为可运行函数。您的答案只是将函数分配为对象的属性。
    【解决方案6】:

    对象类型是函数,对象本身是函数实例化。

    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#1244021[50]=5 不完整。这确实为 Number 对象分配了一个属性,并且是有效的 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 的“参与规则”正确解释和执行。

    当然,= 总是有皱纹和表现。分配给变量时,对象通常与其值“短路”,而不是完整的实体。这是布尔对象和布尔值的问题。

    显式对象识别解决了这个问题。

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

    “重载”是一种相当合法的 Javascript 练习,并得到了 prototyping 等机制的明确认可,尽管代码混淆可能是一种危险。

    最后说明:

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

    【讨论】:

      【解决方案7】:
      var A = function(foo) {                                                                                                      
        var B = function() {                                                                                                       
          return A.prototype.constructor.apply(B, arguments);
        };
        B.prototype = A.prototype;                                                                                                 
        return B;                                                                                                                  
      }; 
      

      【讨论】:

      • 这到底是做什么的?
      【解决方案8】:

      注意:帖子以我如何解决问题的方式编写。我不是 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-20
        • 1970-01-01
        • 2015-01-13
        • 2011-04-21
        • 2013-11-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多