我使用以下函数从一组参数中创建JavaScript函数的实例:
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;
}));
使用上述功能,您可以按如下方式创建实例(请参阅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");
};
}
以上代码适用于F
等用户构建的构造函数。但是出于明显的安全原因,它不适用于像Array
这样的本机构造函数。您可能总是创建一个数组,然后更改其__proto__
属性,但我在Rhino中使用此代码,因此它不会在那里工作。有没有其他方法可以在JavaScript中实现相同的结果?
答案 0 :(得分:6)
但是,您可以使用Object.create
从当前代码中删除大量复杂性(ex)。
答案 1 :(得分:3)
我认为你没有达到你想要的目标。首先在你的F和G中起作用 正在定义此对象的警报功能。这意味着每一次 实例化一个对象,将创建一个新的函数对象并将其分配给alert。 这不是你想要的,你需要在F和G的原型上定义警报。
function F() { }
F.prototype.alert = function() {
alert("F");
};
function G() { }
G.prototype.alert = function() {
alert("G");
};
但是,实例化函数中仍然存在问题。如果你按照你的方式打电话
var f = instantiate(F, [], G.prototype);
你所做的就是将f的原型设置为G.prototype,这不是我想你想要的。 我假设如果你实例化一个F对象,那么你希望能够调用所有函数 在F.prototype上定义,但事情并非如此。
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!
这里出错的原因就像我说你只是将f的原型分配给G.prototype而G.prototype没有 定义了foo函数。
如果您希望以这种方式继承,请查看John Resig的博客,他有一个很好的实现:http://ejohn.org/blog/simple-javascript-inheritance/
Douglas Crockford也提出了一些很好的例子:http://www.crockford.com/javascript/inheritance.html