我喜欢这个问题 - Legitimate uses of the Function constructor - 所以我想创建一个关于Array
构造函数的类似问题。
当然,数组文字表示法是创建数组的正确方法。这意味着不应使用new Array
表示法。并且“案件结案”。
然而,new Array
形式有一个特异性。如果传入自然数,则会创建一个空数组,并将其length
属性设置为该数字。
所以
arr = new Array( 7 );
相当于
arr = [];
arr.length = 7;
这可以被视为一项功能。我想知道这个“功能”是否具有实际用途。我最近偶然发现了一个这样的(简单)用法:
new Array( n + 1 ).join( '*' ) // returns string containing n stars
// e.g.
new Array( 3 ).join( '*' ) // returns '**'
new Array( 6 ).join( '*' ) // returns '*****'
这很酷,但希望有一些更高级的用途。 (使new Array
符号成为JavaScript程序中的合法工具的东西。)
更新:我注意到jQuery库在一个实例中使用new Array( len )
表示法 - 它位于when
函数内(搜索"when:"
) :
when: function( firstParam ) {
var args = sliceDeferred.call( arguments, 0 ),
i = 0,
length = args.length,
pValues = new Array( length ),
count = length,
pCount = length,
// etc.
他们使用它来初始化pValues
局部变量,该变量在代码中的本地函数中使用:
function progressFunc( i ) {
return function( value ) {
pValues[ i ] = arguments.length > 1 ?
sliceDeferred.call( arguments, 0 ) : value;
deferred.notifyWith( promise, pValues );
};
}
我很想知道是否将作业更改为
pValues = [],
会破坏程序......(new Array( length )
需要notifyWith
才能正常工作吗?)
答案 0 :(得分:3)
作为浅层克隆数组的替代方法怎么样?
var arr = [1,2,3];
var arr2 = Array.apply( null, arr );
arr === arr2; // false;
arr.length === arr2.length; // true
是的,我到达这里是因为你只是使用.slice()
,但是我真的不认为首先使用Array
是非法的,只要你知道你是什么正在做。
离开主题,但是制作利用Array
或slice
的常用功能的一种方法。需要bind
。 现在太懒了,无法更新旧浏览器。
var slicer,
apply = Function.prototype.apply;
if( apply.bind ) {
try {
(slicer = apply.bind( Array, null ))({length:0});
} catch( e ) {
slicer = apply.bind([].slice);
}
} else {
slicer = function( coll ) {
if( !coll || coll.length !== +coll.length ) return;
var res = [], i = 0, len = coll.length >>> 0;
for( ; i < len; ++i ) {
res[i] = coll[i];
}
return res;
};
}
var arr_like = {'0':true,'1':true,'2':true,length:3},
arr = slicer( arr_like );
console.log( arr ); // [true, true, true]
console.log( arr.length === arr_like.length); // true
答案 1 :(得分:3)
我不知道这是否重要,但是你使用构造函数的一种情况是你需要确保你有一个干净的,未修改的Array构造函数。您可以创建“iframe沙箱”
var iframe = document.createElement("iframe");
iframe.style.display = "none";
document.body.appendChild(iframe);
var Safe = frames[frames.length - 1];
然后创建这样的数组......
var things = new Safe.Array('x', 'y', 'z');
...知道你的数组在原型中没有任何外来东西被其他脚本放在那里。
但是,这并没有使用单参数作为数组长度的功能。唯一可能真正有用的是设置巨大的阵列来标记基准。
答案 2 :(得分:3)
你可以提出一个homebrewn地图函数(本地.map
不会迭代而且jQuery.map
只是完整的错误)
创建范围:
//1-20
map( Array( 20 ), function( v,i ){
return i+1;
});
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
//-50 - 0
map( Array( 51 ), function( v,i ){
return i-50;
});
//[-50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0]
一般而言,而不是:
var a = [],
l = 10;
while ( l-- ) {
a.unshift(
(function(l){
return function() {
alert( l );
};
})( l )
);
}
你可以这样做:
var a = map( Array( 10 ), function ( v, i ) {
return function(){
alert( i );
};
});
请注意,这仅适用于jQuery.map
或shimmed .map
,原生.map
不会对数组进行迭代。
如果你没有使用jQuery(它会使结果变平:()你可以创建 像这样的三维数组:
var xyz = map(Array(10), function (v, i) {
return map(Array(10), function (v, j) {
return map(Array(10), function (v, k) {
return i * 100 + j * 10 + k;
});
});
});
xyz[0][0][0] // 0
xyz[9][9][9] // 999
xyz[4][4][4] // 444
xyz[3][5][8] // 358
其中for循环的等价物非常可怕:P
快速实现地图功能以实现完整性:
function map( elems, callback ){
var i, length = elems.length, ret = [];
for ( i = 0; i < length; i++ ) {
value = callback( elems[ i ], i );
ret[ ret.length ] = value;
}
return ret;
}