How to convert an “object” into a function in JavaScript?

前端 未结 8 493
Happy的楠姐
Happy的楠姐 2020-12-01 08:53

JavaScript allows functions to be treated as objects--if you first define a variable as a function, you can subsequently add properties to that function. How do you do the

相关标签:
8条回答
  • 2020-12-01 09:38
    var bar = { 
        baz: "qqqq",
        runFunc: function() {
            return 1;
        }
    };
    
    alert(bar.baz); // should produce qqqq
    alert(bar.runFunc()); // should produce 1
    

    I think you're looking for this.

    can also be written like this:

    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 讨论(0)
  • 2020-12-01 09:39

    Use a temporary variable:

    var xxx = function()...
    

    then copy all the properties from the original object:

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

    finally reassign the new function with the old properties to the original variable:

    bar = xxx;
    
    0 讨论(0)
  • 2020-12-01 09:40

    NB: Post written in the style of how I solved the issue. I'm not 100% sure it is usable in the OP's case.

    I found this post while looking for a way to convert objects created on the server and delivered to the client by JSON / ajax.

    Which effectively left me in the same situation as the OP, an object that I wanted to be convert into a function so as to be able to create instances of it on the client.

    In the end I came up with this, which is working (so far at least):

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

    Which can then be used like:

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

    In my case I actually wanted to have functions associated with the resulting object instances, and also be able to pass in parameters at the time of instantiating it.

    So my code was:

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

    And was called thus:

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

    And then they can be used:

    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
    
    0 讨论(0)
  • 2020-12-01 09:41

    JavaScript allows functions to be treated as objects--you can add a property to a function. How do you do the reverse, and add a function to an object?

    You appear to be a bit confused. Functions, in JavaScript, are objects. And variables are variable. You wouldn't expect this to work:

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

    ...so why would you expect that assigning a function to your variable would somehow preserve its previous value? Perhaps some annotations will clarify things for you:

    // 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 讨论(0)
  • 2020-12-01 09:42

    Object types are functions and an object itself is a function instantiation.

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

    displays (in 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]
    }
    

    In particular, note a Function object, function Function() { [native code] }, is defined as a recurrence relation (a recursive definition using itself).

    Also, note that the answer 124402#124402 is incomplete regarding 1[50]=5. This DOES assign a property to a Number object and IS valid Javascript. Observe,

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

    displays

    a   fu  fu  bar 4   2   life    ghi
    

    interpreting and executing correctly according to Javascript's "Rules of Engagement".

    Of course there is always a wrinkle and manifest by =. An object is often "short-circuited" to its value instead of a full fledged entity when assigned to a variable. This is an issue with Boolean objects and boolean values.

    Explicit object identification resolves this issue.

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

    "Overloading" is quite a legitimate Javascript exercise and explicitly endorsed with mechanisms like prototyping though code obfuscation can be a hazard.

    Final note:

    alert(  123 . x = "not"  );
    
    alert( (123). x = "Yes!" );  /* ()'s elevate to full object status */
    
    0 讨论(0)
  • 2020-12-01 09:43
    var A = function(foo) {                                                                                                      
      var B = function() {                                                                                                       
        return A.prototype.constructor.apply(B, arguments);
      };
      B.prototype = A.prototype;                                                                                                 
      return B;                                                                                                                  
    }; 
    
    0 讨论(0)
提交回复
热议问题