规范化Array方法和返回值 [英] Normalize Array methods and return values
问题描述
有没有标准化的数组返回值和突变任何JavaScript库阵?我认为JavaScript的数组API很不一致。
Is there any JavaScript Array library that normalizes the Array return values and mutations? I think the JavaScript Array API is very inconsistent.
一些方法变异数组:
var A = [0,1,2];
A.splice(0,1); // reduces A and returns a new array containing the deleted elements
有些则没有
A.slice(0,1); // leaves A untouched and returns a new array
有的返回突变数组的引用:
Some return a reference to the mutated array:
A = A.reverse().reverse(); // reverses and then reverses back
有的只是返回未定义的:
Some just return undefined:
B = A.forEach(function(){});
我想是要始终变异阵列和永远返回相同的阵列,这样我就可以有某种一致性,也能链。例如:
What I would like is to always mutate the array and always return the same array, so I can have some kind of consistency and also be able to chain. For example:
A.slice(0,1).reverse().forEach(function(){}).concat(['a','b']);
我尝试了一些简单的代码片段,如:
I tried some simple snippets like:
var superArray = function() {
this.length = 0;
}
superArray.prototype = {
constructor: superArray,
// custom mass-push method
add: function(arr) {
return this.push.apply(this, arr);
}
}
// native mutations
'join pop push reverse shift sort splice unshift map forEach'.split(' ').forEach(function(name) {
superArray.prototype[name] = (function(name) {
return function() {
Array.prototype[name].apply(this, arguments);
// always return this for chaining
return this;
};
}(name));
});
// try it
var a = new superArray();
a.push(3).push(4).reverse();
这适用于大多数基因突变的方法,但也存在问题。比如我需要编写自定义的原型各不变异原数组方法。
This works fine for most mutation methods, but there are problems. For example I need to write custom prototypes for each method that does not mutate the original array.
所以,一如既往我这样做的同时,我在想,也许这之前已经做了什么?有没有已经这样做了的轻量级阵列库?这将是很好,如果库还增加了新的JavaScript 1.6垫片的方法对旧版浏览器。
So as always while I was doing this, I was thinking that maybe this has been done before? Are there any lightweight array libraries that do this already? It would be nice if the library also adds shims for new JavaScript 1.6 methods for older browsers.
推荐答案
我不认为这真的是不一致的。是的,他们可能会有点混乱,如JavaScript数组做所有这些其他语言有不同的结构(列表,队列,栈,...),但他们的定义是不同的语言相当一致的东西。您可以轻松地将它们分组在你已经描述的那些类:
I don't think it is really inconsistent. Yes, they might be a little confusing as JavaScript arrays do all the things for which other languages have separate structures (list, queue, stack, …), but their definition is quite consistent across languages. You can easily group them in those categories you already described:
- 列表的方法:
-
推
/不印字
添加元素后返回长度 -
弹出
/移
返回请求的元素 - 您可以定义其他方法获取第一和最后一个元素,但他们很少需要
- list methods:
push
/unshift
return the length after adding elementspop
/shift
return the requested element- you could define additional methods for getting first and last element, but they're seldom needed
所有其他方法不修改原来的数组:
All the other methods do not modify the original array:
-
片
按位置来获得子阵列,过滤器
根据条件和CONCAT让他们
结合与他人创建并返回新阵列 -
的forEach
只是遍历数组,并没有返回值 -
每个
/部分
测试条件的项目,的indexOf
和lastIndexOf
搜索项目(平等) - 无论是返回结果 -
减少
/reduceRight
减少数组项目为单个值并返回。特殊情况是:-
地图
降低到一个新的数组 - 它像的forEach
,但返回的结果 -
加入
和的toString
减少字符串
slice
to get subarrays by position,filter
to get them by condition andconcat
to combine with others create and return new arraysforEach
just iterates the array and returns nothingevery
/some
test the items for a condition,indexOf
andlastIndexOf
search for items (by equality) - both return their resultsreduce
/reduceRight
reduce the array items to a single value and return that. Special cases are:map
reduces to a new array - it is likeforEach
but returning the resultsjoin
andtoString
reduce to a string
这些方法是不够的我们大部分的需求。我们可以做的相当一切与他们,我不知道添加类似于任何库,但在内部,或导致明智不同的方法给他们。大多数数据处理库(如下划线)只会让他们跨浏览器的安全(的 ES5-垫片),并提供额外的实用方法。
These methods are enough for the most of our needs. We can do quite everything with them, and I don't know any libraries that add similar, but internally or result-wise different methods to them. Most data-handling libs (like Underscore) only make them cross-browser-safe (es5-shim) and provide additional utility methods.
我想是要始终变异阵列和永远返回相同的阵列,这样我就可以有某种一致性,也能链。
What I would like is to always mutate the array and always return the same array, so I can have some kind of consistency and also be able to chain.
我想说的的JavaScript一致性是送花儿给人返回一个新的数组元素时,或长度被修改。我想这是因为对象是参考值,并改变它们会经常导致引用同一阵列其他范围的副作用。
I'd say the JavaScript consistency is to alway return a new array when elements or length are modified. I guess this is because objects are reference values, and changing them would too often cause side effects in other scopes that reference the same array.
链接仍然是可能的,你可以使用
片
,CONCAT
,排序
,逆转
,过滤
和地图
共同开创只有一步一个新的数组。如果你想只有数组修改,你可以将其重新分配给数组变量:Chaining is still possible with that, you can use
slice
,concat
,sort
,reverse
,filter
andmap
together to create a new array in only one step. If you want to "modify" the array only, you can just reassign it to the array variable:A = A.slice(0,1).reverse().concat(['a','b']);
突变的方法只有一个优势,对我说:他们是更快,因为它们可能是更多的内存效率(依赖于执行和垃圾收集,当然)。所以,让我们实现这些的一些方法。由于阵列子类既不是可能也没有什么用处,我会定义它们在本地原型一>:
Mutation methods have only one advantage to me: they are faster because they might be more memory-efficient (depends on the implementation and its garbage collection, of course). So lets implement some methods for those. As Array subclassing is neither possible nor useful, I will define them on the native prototype:
var ap = Array.prototype; // the simple ones: ap.each = function(){ ap.forEach.apply(this, arguments); return this; }; ap.prepend = function() { ap.unshift.apply(this, arguments); return this; }; ap.append = function() { ap.push.apply(this, arguments; return this; }; ap.reversed = function() { return ap.reverse.call(ap.slice.call(this)); }; ap.sorted = function() { return ap.sort.apply(ap.slice.call(this), arguments); }; // more complex: ap.shorten = function(start, end) { // in-place slice if (Object(this) !== this) throw new TypeError(); var len = this.length >>> 0; start = start >>> 0; // actually should do isFinite, then floor towards 0 end = typeof end === 'undefined' ? len : end >>> 0; // again start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len); ap.splice.call(this, end, len); ap.splice.call(this, 0, start); return this; }; ap.restrict = function(fun) { // in-place filter // while applying fun the array stays unmodified var res = ap.filter.apply(this, arguments); res.unshift(0, this.length >>> 0); ap.splice.apply(this, res); return this; }; ap.transform = function(fun) { // in-place map if (Object(this) !== this || typeof fun !== 'function') throw new TypeError(); var len = this.length >>> 0, thisArg = arguments[1]; for (var i=0; i<len; i++) if (i in this) this[i] = fun.call(thisArg, this[i], i, this) return this; }; // possibly more
现在,你可以做
A.shorten(0, 1).reverse().append('a', 'b');
这篇关于规范化Array方法和返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-
-