最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Instantiate JavaScript functions with custom prototypes - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question asked Jul 15, 2012 at 8:45 Aadit M ShahAadit M Shah 74.3k31 gold badges175 silver badges307 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7 +50

You can't fully subclass an array.

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

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/blog/simple-javascript-inheritance/

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

发布评论

评论列表(0)

  1. 暂无评论