JavaScript是修改函数原型的更好方法
我希望创建一个构造函数的构造函数。 关于此线程:,似乎唯一的解决方案是:JavaScript是修改函数原型的更好方法,javascript,constructor,prototype,Javascript,Constructor,Prototype,我希望创建一个构造函数的构造函数。 关于此线程:,似乎唯一的解决方案是: Function.prototype.add = function(name, value) { this.prototype[name] = value; }; Function.prototype.remove = function(name) { delete this.prototype[name]; }; 但是我不想修改通用的函数原型。。。而且: var A = new ConstBuilder
Function.prototype.add = function(name, value) {
this.prototype[name] = value;
};
Function.prototype.remove = function(name) {
delete this.prototype[name];
};
但是我不想修改通用的函数
原型。。。而且:
var A = new ConstBuilder().add('test', function() {
console.log('test');
}).getConstructor();
但是我不想在构造函数本身周围有一个对象包装器
问题是,通常构造函数创建新对象,从构造函数原型继承方法。我试图做的是实例化函数而不是对象,但修改函数原型属性的唯一方法是修改其\uuuuuu proto\uuuuu
属性:
var constructorPrototype = {
add : function(name, value) {
this.prototype[name] = value ;
}
} ;
var ConstBuilder = function() {
var constructor = function() {} ;
constructor.prototype = {} ;
// The only way (?), but quite deprecated...
constructor.__proto__ = constructorPrototype ;
return constructor ;
} ;
// Not working way...
//ConstBuilder.prototype = constructorPrototype ;
var A = new ConstBuilder() ;
A.add('test', function() {
console.log('test') ;
}) ;
var a = new A() ;
a.test() ; // "test"
constructorPrototype.remove : function() {
delete this.prototype[name] ;
} ;
A.remove('test') ;
a.test() ; // Error: test is not a function.
注意A.prototype
不是A.\uuuu proto\uuuu
而是A.prototype
是(新的A)。\uu proto\uuu
通过修改\uuuu proto\uuuu
,它可以完美地工作,真是太遗憾了。
我读到Firefox集成了一个“Object.setPrototypeOf()”,但它只是实验性的
这是我想做的另一种方式吗?的确如此。要执行您希望执行的操作,唯一的方法是对要返回的函数的
\uuuu proto\uuu
属性进行变异。然而,这并不是一件坏事。事实上,ES6 Harmony将把它作为功能标准化
但是,我建议您不要对对象的[[Prototype]]
进行变异,因为这会使您的程序非常慢。有一种更快的替代方案:
不要使用原型
传统上,原型用于定义对特定类型对象进行操作的函数。这些专门处理某个参数的函数称为方法
例如,obj.func(a,b,c)
专门处理obj
和obj
的实例。另一方面,func(obj,a,b,c)
不专门处理任何参数(即,obj
可以是任何值)
按照此示例,您可以按如下方式重写添加
和删除
:
function add(func, name, value) {
func.prototype[name] = value;
}
function remove(func, name) {
delete func.prototype[name];
}
现在,您可以在任何需要的函数上使用add
和remove
。你根本不必担心继承问题
唯一的问题是名称空间冲突。假设您已经有一个名为add
的函数:您要做什么?答案很简单。您可以创建一个新的命名空间:
Function.add = function (func, name, value) {
func.prototype[name] = value;
};
Function.remove = function remove(func, name) {
delete func.prototype[name];
};
事实上,这正是本机JavaScript API通常所做的。例如:
function Shape(constructor) {
this.constructor = constructor;
}
function Circle(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
function Rectangle(x1, y1, x2, y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
Circle.prototype = new Shape(Circle);
Rectangle.prototype = new Shape(Rectangle);
对象。创建
Object.getPrototypeOf
Object.setPrototypeOf
call
和apply
这样的方法来“非专用化”专用函数function Shape(constructor) {
this.constructor = constructor;
}
function Circle(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
function Rectangle(x1, y1, x2, y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
Circle.prototype = new Shape(Circle);
Rectangle.prototype = new Shape(Rectangle);
我没有将方法添加到Circle.prototype
和Rectangle.prototype
中,而是执行以下操作:
Circle.area = function (circle) {
return Math.PI * circle.r * circle.r;
};
Rectangle.area = function (rectangle) {
return Math.abs((rectangle.x2 - rectangle.x1) * (rectangle.y2 - rectangle.y1));
};
Shape.prototype.area = function () {
return this.constructor.area(this);
};
现在您可以使用
Circle.area(notCircleInstance)
代替Circle.prototype.area.call(notCircleInstance)
。这是一个双赢的局面。泛化总是比专门化好。a.constructor.prototype==a.\u proto\u,除非你断开链接。这有助于跨浏览器实现吗?我修改的不是a.\u proto
,而是a.\u proto\u
,它是一个函数,不是ConstBuilder
的实例,asConstBuilder
直接返回它,而不是返回它的新实例;我说得很宽泛。所以,X.constructor.prototype==X.uu proto_u我试过constructor.constructor.prototype=constructorPrototype代码>但它也不起作用:\非常感谢,这正是我想要的答案。我知道变异\uuuuuuuuuuuuuuuuu
很慢,但我不知道为什么。你能告诉我为什么这么慢吗?我不想推广这些方法(add
,remove
),因为我正在创建一个模块化框架,可以添加其他函数来修改新的构造函数,我认为自由修改函数
原型不是一个好主意。我给出了这两个函数,但实际上构造函数使用了将近十个其他函数,如果对它们进行概括将是一件麻烦的事情,因为它们不必“适用于”每个函数。下面继续: