Internet Explorer에서 JavaScript 배열 함수 수정 (indexOf, forEach 등) [닫기]


137

자세한으로 다른 , 그렇지 않으면 분명히 잘 알려진, (확실히 버전 7, 일부 경우에, 버전 8) 인터넷 익스플로러에 특히 중요한 기능을 구현하지 않는 Array(예 forEach, indexOf등).

여기저기서 여러 가지 해결 방법이 있지만, 자체 구현에서 복사하여 붙여 넣거나 해킹하는 대신 적절한 표준 구현 세트를 사이트에 접고 싶습니다. 유망한 것으로 보이는 js-methods를 찾았 지만 다른 라이브러리가 더 많이 권장되는지 여기에 게시한다고 생각했습니다. 몇 가지 기타 기준 :

  • 라이브러리는 브라우저가 이미 구현 한 기능에 대해 작동하지 않아야합니다 ( js-methods여기서는 잘 작동하는 것으로 보입니다).
  • LGPL 이 허용 되지만 GPL이 아닌 경우에 문의하십시오 .

답변:


220

많은 사람들이 MDC 폴백 구현을 사용합니다 (예 : indexOf 등 ). 일반적으로 모든 인수의 유형을 명시 적으로 확인하는 범위까지 엄격하게 표준을 준수합니다.

불행히도 저자가이 코드를 사소하고 자유롭게 사용할 수있는 것으로 간주하는 것은 분명하지만,이를 서면으로 명시 적으로 허가 한 사람은없는 것 같습니다. 전체 위키는 CC Attribution-ShareAlike입니다. CC가 코드 용으로 설계되지는 않았지만 수용 가능한 라이센스 인 경우입니다.

js-methods는 일반적으로 괜찮아 보이지만 함수가 있어야하는 방식의 가장자리 (예 : 정의되지 않은 목록 항목, 목록을 변경하는 함수) 주위의 표준을 준수하지는 않습니다. 또한 dodgy stripTags 및 불완전한 UTF-8 코덱과 같은 의심스러운 방법을 포함한 다른 임의의 비표준 방법으로 가득합니다 ( unescape(encodeURIComponent)트릭이 필요하지 않은 경우도 있습니다 ).

가치있는 것에 대해, 여기 내가 사용하는 것이 있습니다 (저는 저작권이 있다고 말할 수 있다면 공개 도메인으로 공개합니다). 함수가 아닌 콜백 또는 정수가 아닌 인덱스를 전달하는 것과 같은 어리석은 짓을 시도하지는 않지만 표준 호환을 시도한다는 점에서 형식 감지를 시도하지 않기 때문에 MDC 버전보다 약간 짧습니다. (내가 놓친 것이 있으면 알려주세요. ;-))

'use strict';

// Add ECMA262-5 method binding if not supported natively
//
if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        if (arguments.length<=1) {
            return function() {
                return that.apply(owner, arguments);
            };
        } else {
            var args= Array.prototype.slice.call(arguments, 1);
            return function() {
                return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
            };
        }
    };
}

// Add ECMA262-5 string trim if not supported natively
//
if (!('trim' in String.prototype)) {
    String.prototype.trim= function() {
        return this.replace(/^\s+/, '').replace(/\s+$/, '');
    };
}

// Add ECMA262-5 Array methods if not supported natively
//
if (!('indexOf' in Array.prototype)) {
    Array.prototype.indexOf= function(find, i /*opt*/) {
        if (i===undefined) i= 0;
        if (i<0) i+= this.length;
        if (i<0) i= 0;
        for (var n= this.length; i<n; i++)
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('lastIndexOf' in Array.prototype)) {
    Array.prototype.lastIndexOf= function(find, i /*opt*/) {
        if (i===undefined) i= this.length-1;
        if (i<0) i+= this.length;
        if (i>this.length-1) i= this.length-1;
        for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('forEach' in Array.prototype)) {
    Array.prototype.forEach= function(action, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                action.call(that, this[i], i, this);
    };
}
if (!('map' in Array.prototype)) {
    Array.prototype.map= function(mapper, that /*opt*/) {
        var other= new Array(this.length);
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                other[i]= mapper.call(that, this[i], i, this);
        return other;
    };
}
if (!('filter' in Array.prototype)) {
    Array.prototype.filter= function(filter, that /*opt*/) {
        var other= [], v;
        for (var i=0, n= this.length; i<n; i++)
            if (i in this && filter.call(that, v= this[i], i, this))
                other.push(v);
        return other;
    };
}
if (!('every' in Array.prototype)) {
    Array.prototype.every= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && !tester.call(that, this[i], i, this))
                return false;
        return true;
    };
}
if (!('some' in Array.prototype)) {
    Array.prototype.some= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && tester.call(that, this[i], i, this))
                return true;
        return false;
    };
}

여기에 구현되지 않은 다른 ECMA262-5 메소드에는 Array reduce/ reduceRight, JSON Object메소드 및 JS 함수로 안정적으로 구현할 수있는 몇 가지 새로운 메소드가 포함됩니다.


5
그 포인터에 감사드립니다-내가 찾은 mozdev에있는 다른 링크는 부실합니다. 여기에 지정된대로 참고로, 코드, MIT-라이센스 : developer.mozilla.org/Project:Copyrights가 (에 대한 좋은 당신이 얻을 수 :-)!
cemerick

1
흥미롭게도 jquery 1.4.2 이전에 모든 MDC ECMA262-5 impls를 포함하는 js 파일을 참조하면 jquery가 손상됩니다. 예를 들어 모든 선택기가 실패하고 null을 반환합니다. jquery가 MDC를 이동하면 예상되는 동작이 발생합니다. 매우 이상합니다.
cemerick

그것은 입니다 호기심! 그것을 볼 것입니까 (테스트 사례가 있습니까?) ... jQuery가 72 번째 줄에서하는 일이 의심 스럽지만 이것이 왜 일어날 수 있는지 즉시 생각할 수는 없습니다.
bobince

4
참고 : 이러한 스텁이 필요한 대부분의 브라우저에서 "for (somearray의 색인) {...}"을 수행하는 경우 somearray.hasOwnProperty (index)를 검사로 사용해야합니다. IE <= 8의 JS 엔진은 이것에 array.prototype 확장을 포함합니다. Google 애드워즈 비동기 코드는이 작업을 수행하지 않습니다. Underscore 또는이를 표준화하는 다른 라이브러리 기능을 사용하는 것이 가장 좋습니다.
추적자

1
이것은 내가 찾을 수있는 IE 8에 대한 가장 빠른 indexOf () 구현입니다. 감사!
Alex Denysenko

27

Underscore.js를 살펴보십시오 .


2
ES5Shim 및 다른 스텁 (예 : MDC)도 다른 결과를 가져 오는 경향이 있습니다. 이러한 유형의 함수에는 밑줄이나 다른 라이브러리를 사용하는 것이 가장 좋으며, 사용 가능한 경우 내부 방법을 사용합니다.
추적자

Underscore.js를 사용하면 var arr = [ 'a', 'a1', 'b'] _.filter (arr, function (a) {return a.indexOf ( 'a')> -1;})
sri_bb

9

Kris Kowal 은 브라우저 구현에서 누락 될 수있는 ECMAScript 5 기능을위한 shim 역할을하는 작은 라이브러리를 컴파일했습니다. 일부 기능은 속도에 최적화되고 브라우저 버그를 해결하기 위해 다른 사람들에 의해 여러 번 수정되었습니다. 기능은 사양을 최대한 가깝게 따르도록 작성되었습니다.

es5-shim.js 는 MIT 라이센스에 따라 배포되었으며 Array.prototype 확장은 맨 위 근처에 있으며 매우 필요하지 않은 기능을 잘라 내고 제거 할 수 있습니다. 또한 주석이 필요한 것보다 훨씬 더 커지므로 스크립트를 축소하는 것이 좋습니다.


1

'핵심 기능을 구현하지 않음'은 실제로 'ECMA 262 3'ed에 부합한다는 의미입니까? :)

언급 한 방법은 새로운 5 판의 일부입니다.이를 지원하지 않는 브라우저의 경우 3 번째로 5 번째로 확장되는 다음 '심'을 사용할 수 있습니다 http://github.com/kriskowal/narwhal- lib 디렉토리 / 방울 / 일각 고래-lib 디렉토리 / lib 디렉토리 / 글로벌 es5.js .


1
좋은 시작이지만 MDC에서 가져 오지 않은 구현에는 꽤 많은 오류가 있습니다. 예. 많은 배열 메소드는 콜백에 충분한 인수를 전달하지 않으며 콜백 함수의 배열 변이의 경우 제대로 작동하지 않습니다.
bobince

js를보다 정교하고 최소한의 언어로 만들기 위해 가능한 모든 것을 취할 것입니다. </ snark> :-)
cemerick

1

해당 스크립트는 테스트에서 제대로 작동하지 않습니다. MDN 문서를 기반으로 동일한 기능을 가진 파일을 만듭니다 .

Internet Explorer 8에서 너무 많은 문제 영역이 해결되었습니다 . egermano / ie-fix.js 의 코드를 참조하십시오 .


0

Underscore.js로

var arr=['a','a1','b'] _.filter(arr, function(a){ return a.indexOf('a') > -1; })

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.