Ecmascript 标准中的Array.prototype中的函数定义

来源:互联网 发布:js获取被选中的radio 编辑:程序博客网 时间:2024/05/16 15:49

大家都知道javascript中的 call 和 apply 是很有用的。不懂的自行百度。
看到别人用内置的函数处理一个自定义的对象我们都会感到非常的崇拜。比如 删除obj 中前五个和后五个数据[].slice.call(obj,5,-5)。对于Array的原型中的函数(不限于Array),Ecmascript标准中也是有这样的描述:

xxx 函数被有意设计成通用的;它的 this 值并非必须是数组对象。因此,它可以作为方法转移到其他类型的对象中。一个宿主对象是否可以正确应用这个 splice 函数是依赖于实现的。

我们疑惑的是一个对象具有什么样的属性才可以调用一些内置的函数呢。这个就需要我们去查阅Ecmascript 协议标准,可是大家都懂得,标准写的还是很有技术水平的,不是一时半会儿可以看得懂的。
所以我就根据Ecmascript的标准写出了Array.prototype(目前只写了这个,以后补充)中函数近似等价的javascript函数,当然并不能完全等价,可是大部分还是尽量贴近原始函数的实现。当然只能贴近有些功能是不能用javascript中语句实现的。
结果你会发现,其实一个对象基本是只要有 length属性就可以使用这个对象作为 Array.prototype 中函数的this执行而不出错,而且 length 属性不必非要是数字。只要可以转换成整型就可以。
另一点就是可以让大家知道一个功能的具体作用,没有什么比计算机语言更严谨的描述了。
未经测试,难免有所疏漏,请大家予以指正。

Array.prototype.constructor = Array;Array.prototype.toString = function(){    //需要的属性 join    var array = this; // toObject 后面这样的注释都表示强制类型转换    var func = array.join;    // if (! func instanceof Function) {throw "type Error"}    return func.call(array);};Array.prototype.concat = function (item1){    var O = this;  // toObject    var A = []; var n = 0;    var items = [O];var i;    for(i = 0; i < arguments.length; i++) {        items.push(arguments[i]); // 标准里没有使用push实现这个,只是为了表达标准里的意思,后面相同    }    while(items.length){        var E = items.shift();  //标准里写的不是shift函数实现这个,后面相同        if(E instanceof Array){            var k = 0; var len = E.length;            while(k < len){                if(E.hasOwnPropery(k.toString())){                    A[n] = E[k];                }                n++; k++;            }        }else{            A[n] = E;            n++;        }    }    return A;};Array.prototype.join = function(sepatator){    var O = this;  // toObject    var lenVal = O.length;    var len = lenVal; //toUint32    sepatator = sepatator || ",";    var sep = sepatator.toString();    if(len === 0) { return ""; }     var element0 = O[0];    var R = element0 === undefined || element0 === null ? "" : element0.toString();    var k = 1;    while(k < len){        var S = R + sep;        element = O[k];        var next = element === undefined || element === null ? "" : element.toString();        R = S + next;        k++;    }    return R;};Array.prototype.pop = function (){    var O = this; // toObject    var lenVal = O.length;    var len = lenVal; // 强制类型转换toUint32;    if(len === 0){        O.length = 0;        return undefined;    }    var element = O[len-1];    delete O[len-1];  //对于数组,这句可以没有,但是对于obj这是必须的    O.length = len-1;    return element;};Array.prototype.push = function(item1) {    var O = this ; //toObject    var lenVal = O.length;    var n = lenVal; // toUint32;    var items = [O];var i;    for(i = 0; i < arguments.length; i++) {        items.push(arguments[i]); // 标准里没有使用push实现这个    }    while(items.length > 0){        var E = items.shift();        O[n] = E;        n++;    }    O.length = n;    return n;};Array.prototype.reverse = function () {    var O = this;  //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    var middle = Math.floor(len/2);    var lower = 0;    while(lower !== middle){ //不知道为什么标准里写的不是 lower >= middle        var upper = len - lower - 1;        var lowerValue = O[lower];        var upperValue = O[upper];        if(O.hasOwnPropery(lower.toString()) && O.hasOwnPropery(upper.toString())){            O[lower] = upperValue;            O[upper] = lowerValue;        }else if(!O.hasOwnPropery(lower.toString()) && O.hasOwnPropery(upper.toString())){            O[lower] = upperValue;            delete O[upper] ;        }else if( O.hasOwnPropery(lower.toString()) && !O.hasOwnPropery(upper.toString()) ){            delete O[lower];            O[upper] = lowerValue;        }        lower++;    }    return O;};Array.prototype.shift = function (){    var O = this; //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    if(len === 0) { O.length = 0; return undefined; }    var first = O[0];    var k =1;    while(k < len){        var from = k.toString();        if(O.hasOwnPropery(from)){            O[k-1] = O[k];        }else{            delete O[k-1];        }        k++;    }    delete O[k-1];    O.length = len - 1;    return first;};Array.prototype.slice = function (start, end){    var O = this; //toObject    var A = [];    var lenVal = O.length;    var len = lenVal; // toUint32    var relativeStart = start; // toIntger    var k = relativeStart < 0 ? Math.max(len + relativeStart,0):Math.min(relativeStart,len);    var relatveEnd = typeof end ==="undefined" ? len : end; // toIntger(end)    var final_ = relatveEnd < 0 ? max(len+relatveEnd,0) : min(relativeEnd,len);    var n  = 0;    while(k < final_){        if(O.hasOwnPropery(k.toString())){            A[n] = O[k];        }        k++;n++;    }    return A;};Array.prototype.sort = function (){};Array.prototype.splice = function (start,deleteCount) {    var O = this; //toObject    var A = [];    var lenVal = O.length;    var len = lenVal; // toUint32    var relatveStart = start; // toIntger    var actualStart = relatveStart < 0 ? Math.max(len + relatveStart,0): Math.min(relatveStart,len);    var actualDeleteCount = Math.min(max(deleteCount,0),len - actualStart); //toIntger(deleteCount)    var k = 0;    var from;    while(k < actualDeleteCount){        from = (actualStart+k).toString();        if(O.hasOwnPropery(from)){            A[k] = O[actualStart+k];        }        k++;    }    var items = [];    for(i = 2; i < arguments.length; i++) {        items.push(arguments[i]); // 标准里没有使用push实现这个    }    var itemCount = items.length;    if(itemCount < actualDeleteCount){        k = actualStart;        while(k < len - actualDeleteCount){            from = (k+actualDeleteCount).toString();            if(O.hasOwnPropery(from)){                O[k+itemCount] = O[k+actualDeleteCount];            }else{                delete O[k+itemsCount];            }            k++;        }        k = len;        while(k > len-actualDeleteCount + itemsCount){            delete O[k-1];            k--;        }    }else if(itemCount > actualDeleteCount){        k = len - actualDeleteCount;        while(k > actualStart){            from = (k+actualDeleteCount - 1).toString();            if(O.hasOwnPropery(from)){                O[k + itemCount - 1] = O[k+actualDeleteCount -1];            }else{                delete O[k + itemCount -1];            }            k--;        }    }    k = actualStart;    while(items.length>0){        var E = items.shift();        O[k] = E;        k++;    }    O.length = len - actualDeleteCount + itemCount;    return A;};Array.prototype.unshift = function (item1){    var O = this; //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    var argCount = arguments.length;    var k = len;    while(k > 0){        var from = (k-1).toString();        if(O.hasOwnPropery(from)){            O[k + argCount - 1] = O [k-1];        }else{            delete O[k + argCount -1];        }        k--;    }    var j = 0;    var items = []; var i;    for(i = 0 ; i < arguments.length;i++){        items.push(arguments[i]);    }    while(items.length > 0){        var E = items.shift();        O[j] = E;        j++;    }    O.length = len + argCount;    return len+argCount;};Array.prototype.indexOf = function (searchElement){    var O = this; //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    if(len === 0) { return -1; }    var n = arguments.length >=2 ? arguments[1] : 0; //toIntger(arguments[1])    if(n > len) { return -1; }    var k = n>=0 ? n : Math.max(len + n, 0);    while(k < len){        if(O.hasOwnPropery(k.toString)()){            if(searchElement === O[k]) {                return k;            }        }        k++;    }    return -1;};Array.prototype.lastIndexOf = function (searchElement){    var O = this;    var lenVal = O.length;    var len = lenVal; // toUint32    if(len === 0) { return -1; }    var n = arguments.length >=2 ? arguments[1] : 0; //toIntger(arguments[1])    var k = n>=0 ? min(n,len-1) : len + n;    while(k >= 0){        if(O.hasOwnPropery(k.toString)()){            if(searchElement === O[k]) {                return k;            }        }        k++;    }    return -1;};Array.prototype.every = function (callbackfn){    var O = this; //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    var T = arguments.length >=2 ? arguments[1] : undefined;    var k = 0;    while(k < len){        if(O.hasOwnPropery(k.toString())){            var testResult = callbackfn.call(T,O[k],k,O);            if(!testResult) { return false; }        }        k++;    }    return true;};Array.prototype.some = function (callbackfn){    var O = this; //toObject    var lenVal = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    var T = arguments.length >=2 ? arguments[1] : undefined;    var k = 0;    while(k < len){        if(O.hasOwnPropery(k.toString())){            var testResult = callbackfn.call(T,O[k],k,O);            if(testResult) { return true; }        }        k++;    }    return false;};Array.prototype.forEach = function(callbackfn){    var O = this; //toObject    var lenValue = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    var T = arguments.length >=2 ? arguments[1] : undefined;    var k = 0;    while( k < len ){        if(O.hasOwnPropery(k.toString())){            callbackfn.call(T,O[k],k,O);        }        k++;    }    return undefined;};Array.prototype.map = function(callbackfn){    var O = this; //toObject    var lenValue = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    var T = arguments.length >=2 ? arguments[1] : undefined;    var A = [];    var k = 0;    while( k < len ){        if(O.hasOwnPropery(k.toString())){            A[k] = callbackfn.call(T,O[k],k,O);        }        k++;    }    return A;};Array.prototype.filter = function(callbackfn){    var O = this; //toObject    var lenValue = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    var T = arguments.length >=2 ? arguments[1] : undefined;    var A = [];    var k = 0;    var to = 0;    while( k < len ){        if(O.hasOwnPropery(k.toString()) ){            if( callbackfn.call(T,O[k],k,O) ){                A[to] = O[k];                to++;            }        }        k++;    }    return A;};Array.prototype.reduce = function (callbackfn){    var O = this; //toObject    var lenValue = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    //if(len === 0 && arguments.length <  2 ) {throw "type error"}    var k = 0;    var accumulator;    if(arguments.length > 2) {         accumulator = arguments[1];     }else{        var kPresent = false;        while(kPresent === false && k < len){            kPresent = O.hasOwnPropery(k.toString());            if(kPresent){                accumulator = O[k];            }            k++;        }        // if(!kPresent) {throw "type error"}    }    while( k < len ){        if(O.hasOwnPropery(k.toString())){            accumulator = callbackfn.call(undefined,accumulator,O[k],k,O);        }        k++;    }    return accumulator;};Array.prototype.reduceRight = function (callbackfn){    var O = this; //toObject    var lenValue = O.length;    var len = lenVal; // toUint32    //if(! callbackfn instanceof Function) {throw "typeerror"}    //if(len === 0 && arguments.length <  2 ) {throw "type error"}    var k = len - 1;    var accumulator;    if(arguments.length > 2) {         accumulator = arguments[1];     }else{        var kPresent = false;        while(kPresent === false && k >= 0){            kPresent = O.hasOwnPropery(k.toString());            if(kPresent){                accumulator = O[k];            }            k--;        }        // if(!kPresent) {throw "type error"}    }    while( k >= 0 ){        if(O.hasOwnPropery(k.toString())){            accumulator = callbackfn.call(undefined,accumulator,O[k],k,O);        }        k--;    }    return accumulator;};
0 0
原创粉丝点击