Instantiate JavaScript functions with custom prototypes

北战南征 提交于 2019-12-19 03:11:34

问题


I use the following function to create instances of functions in JavaScript from an array of arguments:

var instantiate = function (instantiate) {
    return function (constructor, args, prototype) {
        "use strict";

        if (prototype) {
            var proto = constructor.prototype;
            constructor.prototype = prototype;
        }

        var instance = instantiate(constructor, args);
        if (proto) constructor.prototype = proto;
        return instance;
    };
}(Function.prototype.apply.bind(function () {
    var args = Array.prototype.slice.call(arguments);
    var constructor = Function.prototype.bind.apply(this, [null].concat(args));
    return new constructor;
}));

Using the above function you can create instances as follows (see the fiddle):

var f = instantiate(F, [], G.prototype);

alert(f instanceof F); // false
alert(f instanceof G); // true

f.alert(); // F

function F() {
    this.alert = function () {
        alert("F");
    };
}

function G() {
    this.alert = function () {
        alert("G");
    };
}

The above code works for user built constructors like F. However it doesn't work for native constructors like Array for obvious security reasons. You may always create an array and then change its __proto__ property but I am using this code in Rhino so it won't work there. Is there any other way to achieve the same result in JavaScript?


回答1:


You can't fully subclass an array.

However, you can use Object.create to remove a lot of complexity from your current code (ex).




回答2:


I don't think you are achieving what you are intending here. First in your F and G functions you are defining an alert function on the this object. This means every time you instantiate an object a new function object will be created and assigned to alert. This is not what you want, you need to define alert on the prototype of F and G.

function F() { }

F.prototype.alert = function() {
    alert("F");
};

function G() { }

G.prototype.alert = function() {
    alert("G");
};  

However you still have an issue in your instantiate function. If you call it the way you have

var f = instantiate(F, [], G.prototype);

all you are doing is setting f's prototype to G.prototype, which is not what I think you want. I'm assuming that if you instantiate an F object then you would want to be able to call all of the functions defined on F.prototype, but the way things stand this is not the case.

function F() { }

F.prototype.alert = function() {
    alert("F");
};

F.prototype.foo = function() {
    alert("F foo");
};

function G() { }

G.prototype.alert = function() {
    alert("G");
};  


var f = instantiate(F, [], G.prototype);
f.foo(); // error!

The reason for the error here is like I said you just assign f's prototype to G.prototype and G.prototype does not have a foo function defined.

If you are looking to do inheritance in this way take a look at John Resig's blog he has a nice implemantation: http://ejohn.org/blog/simple-javascript-inheritance/

Also Douglas Crockford has put together some good examples: http://www.crockford.com/javascript/inheritance.html



来源:https://stackoverflow.com/questions/11490606/instantiate-javascript-functions-with-custom-prototypes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!