Array构造函数的合法使用

时间:2011-12-09 23:34:27

标签: javascript arrays constructor

我喜欢这个问题 - 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才能正常工作吗?)

3 个答案:

答案 0 :(得分:3)

作为浅层克隆数组的替代方法怎么样?

var arr = [1,2,3];

var arr2 = Array.apply( null, arr );

arr === arr2; // false;

arr.length === arr2.length; // true

是的,我到达这里是因为你只是使用.slice(),但是我真的不认为首先使用Array是非法的,只要你知道你是什么正在做。


离开主题,但是制作利用Arrayslice的常用功能的一种方法。需要bind现在太懒了,无法更新旧浏览器。

http://jsfiddle.net/fdgBU/1/

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;
}