我正在创建一个小代码插件,它允许你用数组做一些事情。我不希望使用原型构造将函数添加到数组对象,我想要的是人们可以做类似的事情:
arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();
因此保持正常的数组对象不变 所以我想出了以下构造(灵感来自jQuery源代码):
var arrayFunction = window.arrayFunction = function(array) {
return new arrayFunction.fn.init(array);
}
arrayFunction.fn = arrayFunction.prototype = {
init: function(array){
this.a = array;
//should I return something here?
},
someSpecialArrayFunction: function(){
//Super cool custom stuff here.
}
}
然而,这显然不起作用(显然)。 init函数()中应该发生什么?
现在的错误是当我尝试时:
arrayFunction(array).someSpecialArrayFunction();
它说someSpecialArrayFunction()不是函数吗?
如何做到这一点?
修改的
是的,这确实是一个简化的例子。实际的事情有更多的方法。
另外,我只是知道如果它还支持chaning会有多棒,你会怎么做?
答案 0 :(得分:2)
或者简单地说:
var arrayFunction = function(array) {
var someSpecialArrayFunction = function() {
// do something with array
};
return {
someSpecialArrayFunction: someSpecialArrayFunction
}
};
arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();
虽然要小心这一点,但如果最终的方法太多,那么使用原型可能会更好。
答案 1 :(得分:1)
我不确定这是获得你想要的最好的语法,但我想这是一个精简的例子......无论如何这里是一个快速的方法让它工作
var arrayFunction = window.arrayFunction = function(array) {
return new arrayFunction.fn.init(array);
}
arrayFunction.fn = arrayFunction.prototype = {
init: function(array){
var a = array;
return {
someSpecialArrayFunction: function(){
alert (a.join(' - ') ); //Super cool custom stuff here.
}
};
},
}
arrayFunction( [1, 2, 3] ).someSpecialArrayFunction();
答案 2 :(得分:0)
sktrdie 的answer看起来不错。
要考虑的另一件事是使用flyweight pattern而不是每次调用包装器时返回一个新的对象实例。 ExtJS函数Ext.fly执行此操作;它返回一个全局共享的实例。
答案 3 :(得分:0)
尝试这样的事情:
var mathWrapper = function(array) {
return {
mean : function(){
if (array.length == 0) return(0);
var total = 0;
for (var i = 0; i < array.length; i++) total += array[i];
return(total / array.length);
},
};
}
通过类似
的方式调用它document.write(mathWrapper([1,2,3,4,5,6]).mean());
应该返回数组元素的平均值。
答案 4 :(得分:0)
如果您不想更改Array.prototype
,唯一真正可行的解决方案是将方法添加到特定的数组对象:
function doSomething() {}
function doOther() {}
function wrap(array) {
array.doSomething = doSomething;
array.doOther = doOther;
return array;
}
请注意,我没有在doSomething()
中定义doOther()
和wrap()
- 否则,我们会在每次调用时创建新的函数对象,效率非常低。
更复杂的变体如下:
function doSomething() {}
function doOther() {}
function wrap(array) {
if(this instanceof arguments.callee) {
this.doSomething = doSomething;
this.doOther = doOther;
}
else {
arguments.callee.prototype = array;
return new arguments.callee;
}
}
在这里,我们创建一个新的包装器对象(并且不向数组本身添加属性)。包装器对象仍然可以访问所有数组的属性。但是有一点点:
var foo = wrap([1,2,3]);
document.writeln(foo.length); // writes 3
foo.push(4);
document.writeln(foo.length); // writes 4 in FF, 3 in IE
foo[4] = 5;
foo[5] = 6;
document.writeln(foo.length); // still writes 4?!
使用foo[4] =
将访问我们的包装器对象,属性4
和5
将在那里设置而不在数组中 - 因此,不会更新其length属性。在IE中,调用push()
将无法正确更新数组...
如果你的包装器对象不需要“重新路由”对数组对象的调用,那么还有其他使用闭包的解决方案 - sktrdie的第一个例子就是其中之一。我反对他们,因为他们也会在每次调用时创建新的函数对象。我会做什么:
function wrap(array) {
if(this instanceof arguments.callee)
this.array = array;
else return new arguments.callee(array);
}
wrap.prototype.doSomething = function() {};
wrap.prototype.doOther = function() {};
在这里,您可以通过doSomething()
访问doOther()
和this.array
中的数组。
答案 5 :(得分:0)
只需扩展Array对象并将您喜欢的方法添加到对象中。然后你可以创建一个桥接函数,它将一个数组作为参数并返回你的数组版本。这种方法更容易,也更有用。