Ext原码学习之lang-Array.js
阅读原文时间:2023年07月10日阅读:2

// JavaScript Document
//Array 方法
(function(){
var arrayPrototype = Array.prototype,
slice = arrayPrototype.slice,
supportsSplice = (function(){

        var array = \[\],lengthBefore,j = 20;

        if(!array.splice)  
        {  
            return false;  
        }

        while(j--)  
        {  
            array.push("A");  
        }

        array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");

        //console.log(array);

        lengthBefore = array.length;

        array.splice(13,0,'XXX');

        if(lengthBefore +1 !=array.length)  
        {  
            return false;  
        }

        return true;

    }()),

    supportsForEach='forEach' in arrayPrototype,  
    supportsMap='map' in arrayPrototype,  
    supportsIndexOf = 'indexOf' in arrayPrototype,  
    supportsEvery = 'every' in arrayPrototype,  
    supportsSome = 'some' in arrayPrototype,  
    supportsFilter = 'filter' in arrayPrototype,  
    supportsSort = (function(){  
        var a = \[1,2,3,4,5\].sort(function(){return 0;});  
        return a\[0\] ===1 && a\[1\]===2 && a\[2\]===3 && a\[3\]===4 && a\[4\]===5;  
    }()),  
    supportsSliceOnNodeList =true,  
    ExtArray,erase,replace,splice;

    try  
    {  
        if(typeof document !== 'undefined')  
        {  
            slice.call(document.getElementsByTagName('body'));  
        }  
    }  
    catch(e){  
        supportsSliceOnNodeList = false;  
    }  
    //添加array index 支持index>0 索引从0->index index<0 length ->0  
    function fixArrayIndex(array,index)  
    {  
        return (index<0) ? Math.max(0,array.length + index):Math.min(array.length,index);  
    }

    function replaceSim(array,index,removeCount,insert)  
    {  
        var add = insert ? insert.length :0,  
            length = array.length,pos=fixArrayIndex(array,index),  
            remove,tailOldPos,tailNewPos,tailCount,lengthAfterRemove,i;

        if(pos == length)  
        {  
            if(add)  
            {  
                array.push.apply(array,insert);  
            }  
        }  
        else  
        {  
            /\*  
             0 1 2 3 4 5 6 7 8  
            replace(arr,3,2,\[a,b,c\])  
            \*/  
            remove = Math.min(removeCount,length-pos);  
            //5  
            tailOldPos = pos+remove;  
            //5 + 3 - 2 =6  
            tailNewPos = tailOldPos + add-remove;  
            tailCount = length - tailOldPos;  
            lengthAfterRemove = length - remove;

            if(tailNewPos<tailOldPos)  
            {  
                for(i =0;i<tailCount;++i)  
                {  
                    array\[tailNewPos+i\] = array\[tailOldPos+i\];  
                }  
            }  
            else if(tailNewPos > tailOldPos)  
            {  
                for (i = tailCount; i--; ) {  
                    array\[tailNewPos+i\] = array\[tailOldPos+i\];  
                }  
            }

            if (add && pos === lengthAfterRemove) {  
                array.length = lengthAfterRemove; // truncate array  
                array.push.apply(array, insert);  
            } else {  
                array.length = lengthAfterRemove + add; // reserves space  
                for (i = 0; i < add; ++i) {  
                    array\[pos+i\] = insert\[i\];  
                }  
            }

        }

        return array;

    }

    function replaceNative(array,index,removeCount,insert)  
    {  
        if(insert && insert.length)  
        {  
            if(index === 0 &&!removeCount)  
            {  
                array.unshift.apply(array,insert);  
            }  
            else if(index < array.length)  
            {  
                array.splice.apply(array,\[index,removeCount\].concat(insert));  
            }  
            else  
            {  
                array.push.apply(array,insert);  
            }  
        }  
        {  
            array.splice(index,removeCount);  
        }

        return array;  
    }  
    //var arr = \[1,2,3,4,5,6\];  
//    arr.splice(3,2);  
//    console.log(arr);

function eraseSim(array,index,removeCount)  
{  
    return replaceSim(array,index,removeCount);  
}

function eraseNative(array,index,removeCount)  
{  
    array.splice(index,removeCount);  
    return array;  
}

function spliceSim(array,index,removeCount)  
{  
    var pos = fixArrayIndex(array,index),  
        removed = array.slice(index,fixArrayIndex(array,pos+removeCount));

        if(arguments.length < 4)  
        {  
            replaceSim(array,pos,removeCount);  
        }  
        else  
        {  
            replaceSim(array,pos,removeCount,slice.call(arguments,3));  
        }  
}

erase = supportsSplice ? eraseNative :eraseSim;  
replace = supportsSplice ? replaceNative : replaceSim;  
splice = supportsSplice ? spliceNative : repliceSim;

ExtArray = Ext.Array = {  
    each:function(array,fn,scope,reverse)  
    {  
        array = ExtArray.from(array);

        var i,ln = array.length;

        if(reverse!== true)  
        {  
            for(i = 0;i<ln ;i++)  
            {  
                if(fn.call(scope||array\[i\],array\[i\],i,array)===false)  
                {  
                    return i;  
                }  
            }  
        }  
        else  
        {  
            for(i =ln -1 ;i>-1;i--)  
            {  
                if(fn.call(scope|| array\[i\],array\[i\],i,array)===false)  
                {  
                    return i;  
                }  
            }  
        }

        return true;  
    },  
    forEach:supportsForEach ? function(array,fn,scope)  
    {  
        array.forEach(fn,scope);  
    } : function(array,fn,scope)  
    {  
        var i =0,ln = array.length;  
        for(;i<ln ;i++)  
        {  
            fn.call(scope ,array\[i\],i,array);  
        }  
    },

    indexOf:supportsIndexOf ? function(array,item,from)  
    {  
        return arrayPrototype.indexOf.call(array,item,from);  
    }:function(array,item,from)  
    {  
        var i,length = array.length;

        for(i = (from<0) ? Math.max(0,length+from) : from ||0;i<length;i++)  
        {  
            if(array\[i\] === item)  
            {  
                return i;  
            }  
        }

        return -1;  
    },  
    //是否包函item  
    contains:function(array,item)  
    {  
        return Ext.indexOf(array,item) !== '-1';  
    },  
    //将可遍历对象转换为数组  
    toArray:function(iterable,start,end)  
    {  
        if(!iterable || iterable.length)  
        {  
            return \[\];  
        }

        if(typeof iterable === 'string')  
        {  
            iterable = iterable.split('');  
        }

        if(supportsSliceOnNodeList)  
        {  
            return slice.call(iterator,start||0,end|| iterable.length);  
        }

        var array = \[\],i;  
        start = start || 0;  
        end = end ? ((end <0) ? iterabe.length +end :end):iterable.length;

        for(i = start ;i<end;i++)  
        {  
            array.push(iterable\[i\]);  
        }

        return array;  
    },  
    //提取数据中对象属性值  
    pluck:function(array,prototypeName)  
    {  
        var ret = \[\],i,ln,item;  
        for(i = 0,ln = array.length;i<ln;i++)  
        {  
            item = array\[i\];  
            ret.push(item\[propertyName\]);  
        }

        return ret;  
    },  
    //map 数组遍历  
    map:suportsMap ?function(array,fn,scope){  
        if(!fn)  
        {  
            Ext.Error.raise('map have a callback');  
        }

        return array.map(fn,scope);  
    } : function(array,fn,scope){

        if(!fn)  
        {  
            Ext.Error.raise('map have a callback');  
        }

        var results = \[\],i=0,len= array.length;

        for(;i<len;i++)  
        {  
            result\[i\] = fn.call(scope,array\[i\],i,array);  
        }

        return results;  
    },  
    //执行方法,如果item返回false 则直接返回  
    every:supportsEvery ? function(array,fn,scope){  
         //<debug>  
        if (!fn) {  
            Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');  
        }  
        //</debug>  
        return array.every(fn, scope);  
    } : function(array,fn,scope){  
        //<debug>  
        if (!fn) {  
            Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');  
        }  
        //</debug>  
        var i = 0,  
            ln = array.length;

        for (; i < ln; ++i) {  
            if (!fn.call(scope, array\[i\], i, array)) {  
                return false;  
            }  
        }

        return true;  
    },  
    //直接有一个item 返回true 则返回true  
    some:supprotsSome ? function(array,fn,scope){  
         if (!fn) {  
            Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');  
        }

        return array.some(fn,scope);  
    }:function(array,fn,scope){  
        if (!fn) {  
            Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');  
        }  
         var i = 0,  
            ln = array.length;

        for (; i < ln; ++i) {  
            if (fn.call(scope, array\[i\], i, array)) {  
                return true;  
            }  
        }

        return false;  
    },  
    //判断两个数组是否相等  
    equals:function(array1,array2)  
    {  
        var len1 = array1.length,  
            len2 = array2.length,i;

        if(array1 === array2)  
        {  
            return false;  
        }

        if(len1 !== len2)  
        {  
            return false;  
        }

        for(i = 0;i<len1;i++)  
        {  
            if(array1\[i\] !== array2\[i\])  
            {  
                return false;  
            }  
        }

        return true;  
    },  
    //清理数组中为的null item  
    clean:function(array)  
    {  
        var results = \[\],i=0,ln = array.length,item;  
        for(;i<ln;i++)  
        {  
            item = array\[i\];  
            if(!Ext.isEmpty(item))  
            {  
                results.push(item);  
            }  
        }

        return results;  
    },  
    //唯一数姐  
    unique:function(array)  
    {  
        var clone = \[\],i = 0,ln = array.length,item;  
        for(;i<ln;i++)  
        {  
            item = array\[i\];  
            if(ExtArray.indexOf(clone,item) === '-1')  
            {  
                clone.push(item);  
            }  
        }

        return clone;  
    },  
    //过滤数组  
    filter:supportsFilter ? function(array,fn,scope){  
         //<debug>  
        if (!fn) {  
            Ext.Error.raise('Ext.Array.filter must have a filter function passed as second argument.');  
        }  
        //</debug>  
        return array.filter(fn, scope);  
    } : function(array,fn,scope){  
         //<debug>  
        if (!fn) {  
            Ext.Error.raise('Ext.Array.filter must have a filter function passed as second argument.');  
        }  
        //</debug>  
        var results = \[\],  
            i = 0,  
            ln = array.length;

        for (; i < ln; i++) {  
            if (fn.call(scope, array\[i\], i, array)) {  
                results.push(array\[i\]);  
            }  
        }

        return results;  
    },  
    findBy:function(array,fn,scope)  
    {  
        var i =0,len = array.length;

        for(;i<len;i++)  
        {  
            if(fn.call(acope || array ,array\[i\],i))  
            {  
                return array\[i\];  
            }  
        }  
        return null;  
    },  
    from:function(value,newReference)  
    {  
        if(value === undefined || value === null)  
        {  
            return \[\];  
        }

        if(Ext.isArray(value))  
        {  
            return (newReference) ? slice.call(value) : value;  
        }

        var type = typeof values;

        if(value && value.length!=undefined && type !== 'string' && (type !='function' || !value.apply))  
        {  
            return ExtArray.toArray(value);  
        }

        return \[value\];  
    },  
    remove:function(array,item)  
    {  
        var index = ExtArray.indexOf(array,item);

        if(index !== '-1')  
        {  
            earse(array,index,1);  
        }

        return array;  
    },  
    include:function(array,item)  
    {  
        if(!ExtArray.contains(array,item))  
        {  
            array.push(item);  
        }  
    },  
    clone:function(array)  
    {  
        return slice.call(array);  
    },  
    merge:function()  
    {  
        var args = slice.call(arguments),array = \[\],i,ln;

        for(i = 0,ln = args.length;i<ln ;i++)  
        {  
            array = array.concat(args\[i\]);  
        }

        return ExtArray.unique(array);  
    },  
    intersect:function(){  
        var intersction = \[\],arrays = slice.call(arguments),  
            arraysLength,  
            array,  
            arrayLength,  
            minArray,  
            minArrayIndex,  
            minArrayCandidate,  
            minArrayLength,  
            element,  
            elementCandidate,  
            elementCount,i,j,k;

        if(!array.length)  
        {  
            return intersction;  
        }

        arraysLength = arrays.length;  
        for(i = minArrayIndex = 0;i<arraysLength;i++)  
        {  
            minArrayCandidate = arrays\[i\];

            if(!minArray || minArrayCandidate.length<minArray.length)  
            {  
                minArray = minArrayCandidate;  
                minArrayIndex = i;  
            }  
        }

        minArray = ExtArray.unque(minArray);  
        earse(arrays,minArrayIndex,1);

        minArrayLength = minArray.length;  
        arraysLength = arrays.length;

        for(i = 0;i<minArrayLength;i++)  
        {  
            element = minArray\[i\];  
            elementCount = 0;

            for(j = 0;j<arraysLength;j++)  
            {  
                array = arrays\[j\];  
                arrayLength = array.length;

                for(k = 0;k<arrayLength;k++)  
                {  
                    elemenCandidate = array\[k\];  
                    if(element === elementCandidate)  
                    {  
                        elementCount++;  
                        break;  
                    }  
                }  
            }

            if(elementCount === arrayLength)  
            {  
                intersction.push(element);  
            }  
        }  
        return intersection;

    },  
    difference:function(arrayA,arrayB)  
    {  
        var clone = slice.call(arrayA),ln = clone.length,i,j,lnB;

        for(i = 0,lnB = arrayB.length ;i<lnB;i++)  
        {  
            for(j=0 ;j<ln;j++)  
            {  
                if(clone\[j\] = arrayB\[i\])  
                {  
                    erase(clone,j,1);  
                    j--;  
                    ln--;  
                }  
            }  
        }

        return clone;  
    },  
    slice:\[1,2\].slice(1,undefined).lnegth ? function(array,begin,end){  
        return slice.call(array,begin,end);  
    }:function(array,begin,end){  
        if(typeof begin==='undefined')  
        {  
            return slice.call(array);  
        }  
        if(typeof end === 'undefined')  
        {  
            return slice.call(array,begin);  
        }

        return slice.call(array,begin,end);  
    },  
    sort:supportsSort?function(array,sortFn){  
        if(sortFn)  
        {  
            return array.sort(sortFn);  
        }  
        else  
        {  
            return array.sort();  
        }  
    }:function(array,sortFn){  
        var length = array.length,i=0,comparsion,j,min,tmp;

        for(;i<length;i++)  
        {  
            min = i;  
            for(j = i+1 ;j<length ;j++)  
            {  
                if(sortFn)  
                {  
                    comparison = sortFn(array\[j\],array\[min\]);  
                    if(comparison < 0)  
                    {  
                        min = j;  
                    }  
                }  
                else if(array\[j\] < array\[min\])  
                {  
                    min = j;  
                }  
            }

            if(min !== i)  
            {  
                tmp = array\[i\];  
                array\[i\] = arra\[min\];  
                array\[min\] = tmp;  
            }  
        }

        return array;  
    },  
    flatten:function(array)  
    {  
        var worker = \[\];

        function rFlatten(a){  
            var i,ln ,v;  
            for(i = 0,ln = a.length;i<ln ;i++)  
            {  
                v = a\[i\];  
                if(Ext.isArray(v))  
                {  
                    rFlatten(v);  
                }  
                else  
                {  
                    worker.push(v);  
                }  
            }

            return worker;  
        }

        return rFlatten(array);  
    },  
    min:function(array,comparisonFn)  
    {  
        var min = array\[0\],i,ln,item;  
        for(i =0,ln = array.length;i<ln;i++)  
        {  
            item = array\[i\];

            if(comparsionFn)  
            {  
                if(comparisionFn(min,item)===1)  
                {  
                    min = item;  
                }  
            }  
            else  
            {  
                if(item <min)  
                {  
                    min = item;  
                }  
            }

        }

        return min;  
    },  
    max:function(array,comparisonFn)  
    {  
        var max = array\[0\],i,ln,item;

        for(i=0,ln=array.length;i<ln;i++)  
        {  
            item = array\[i\];

            if(comparisonFn)  
            {  
                if(comparisonFn(max,item) === -1)  
                {  
                    max = item;  
                }  
            }  
            else  
            {  
                if(item > max)  
                {  
                    max = item;  
                }  
            }  
        }

        return max;  
    },  
    // average  
    mean:function(array)  
    {  
        return array.length > 0 ? ExtArray.sum(array) / array.length :undefined;  
    },  
    sum:function(array)  
    {  
        var sum = 0,i,ln,item;  
        for(i=0,ln=array.length;i<ln;i++)  
        {  
            item = array\[i\];  
            sum+=item;  
        }

        return sum;  
    },  
    toMap:function(array,getKey,scope)  
    {  
        var map = {},i = array.length;

        if(!getKey)  
        {  
            while(i--)  
            {  
                map\[array\[i\]\] = i+1;  
            }  
        }  
        else if(typeof getKey === 'string')  
        {  
            while(i--)  
            {  
                map\[array\[i\]\[getKey\]\] = i+1;  
            }  
        }  
        else  
        {  
            while(i--)  
            {  
                map\[getKey.call(scope,array\[i\])\] = i+1;  
            }  
        }

        return map;  
    },  
    toValueMap:function(array,getKey,scope)  
    {  
        var map = {},i=array.length;

        if(!getKey)  
        {  
            while(i--)  
            {  
                map\[array\[i\]\] = array\[i\];  
            }  
        }  
        else if(typeof getKey === 'string')  
        {  
            while(i--)  
            {  
                map\[array\[i\]\[getKey\]\] = array\[i\];  
            }  
        }else  
        {  
            while(i--)  
            {  
                map\[getKey.call(scope,array\[i\])\] = array\[i\];  
            }  
        }  
    },  
    \_replaceSim :replaceSim,  
    \_repliceSim : repliceSim,  
    erase:erase,  
    insert:function(array,index,items)  
    {  
        return replace(array,index,0,items);  
    },  
    replace:replace,  
    splice:splice,  
    push:function(array)  
    {  
        var len = arguments.length,i = 1,newItem;

        if(array === undefined)  
        {  
            array = \[\];  
        }  
        else if(!Ext.isArray(array))  
        {  
            array = \[array\];  
        }

        for(;i<len;i++)  
        {  
            newItem = arguments\[i\];  
            Array.prototype.push\[Ext.isIterable(newItem) ? 'apply':'call'\](array,newItem);  
            return array;  
        }

    }  
};

Ext.each = ExtArray.each;  
ExtArray.union = ExtArray.merge;  
Ext.min = ExtArray.min;  
Ext.max = ExtArray.max;  
Ext.sum = ExtArray.sum;  
Ext.mean = ExtArray.mean;  
Ext.flatten = ExtArray.flatten;  
Ext.clean = ExtArray.clean;  
Ext.unique = ExtArray.unique;  
Ext.pluck = ExtArray.pluck;

Ext.toArray = function(){  
    return ExtArray.toArray.apply(ExtArray,arguments);  
}

})();