Internet Explorer'da JavaScript Dizisi işlevlerini düzeltme (indexOf, forEach, vb.) [Kapalı]


137

Detaylı olarak başka bir yerde ve başka türlü görünüşte iyi bilinen, (kesinlikle sürüm 7 ve bazı durumlarda, sürüm 8), Internet Explorer üzerinde özellikle önemli işlevleri uygulamak değil Array(örneğin forEach, indexOfvb).

Burada ve orada bir takım geçici çözümler var, ancak kendi uygulamalarımızda kopyalayıp yapıştırmak veya kesmek yerine sitemize uygun, kanonik bir dizi uygulama katlamak istiyorum. Ben umut verici görünüyor js yöntemleri buldum , ama başka bir kütüphane daha şiddetle tavsiye gelip gelmediğini görmek için buraya göndereceğini düşündüm. Birkaç çeşitli kriter:

  • Kütüphane, tarayıcının zaten uyguladığı işlevler için bir işlem olmamalıdır ( js-methodsburada oldukça iyi görünüyor).
  • Olmayan GPL , olsa lütfen LGPL kabul edilebilir.

Yanıtlar:


220

Birçoğu MDC yedek uygulamalarını kullanır (örn. İndexOf için ). Genellikle tüm argümanların türlerini açıkça kontrol etseler bile, standartlara titizlikle uyumludurlar.

Ne yazık ki, yazarların bu kodu önemsiz ve serbestçe kullanılabilir olarak gördükleri açık olsa da, bunu yazılı hale getirmek için açık bir lisans hibesi yoktur. Wiki bir bütün olarak CC Attribution-ShareAlike, eğer bu kabul edilebilir bir lisans ise (CC kod için tasarlanmamış olsa da).

js-yöntemleri genel olarak iyi görünür, ancak işlevlerin nasıl olması gerektiğinin kenarlarında standartlarla uyumlu değildir (örn. tanımlanmamış liste öğeleri, listeyi değiştiren işlevler). Ayrıca, tehlikeli şerit Etiketleri ve eksik UTF-8 codec bileşeni gibi bazı şüpheli standart olmayan yöntemlerle de doludur ( unescape(encodeURIComponent)hile de biraz gereksizdir ).

Değeri için, işte kullandığım şey (işte telif hakkı olduğu söylenebilirse, bu şekilde kamu malı olarak serbest bırakıyorum). MDC sürümlerinden biraz daha kısadır, çünkü işlevsiz geri aramalar veya tamsayı olmayan dizinler gibi aptalca bir şey yapmadığınızı yazın, ancak bunun dışında standartlarla uyumlu olmaya çalışır. (Bir şey kaçırırsam haberim olsun. ;-))

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

Burada uygulanmayan diğer ECMA262-5 yöntemleri arasında Array reduce/ reduceRight, JSON Objectyöntemleri ve JS işlevleri olarak güvenilir bir şekilde uygulanabilecek birkaç yeni yöntem bulunmaktadır.


5
Bu işaretçi için teşekkürler - bu tür impls'ların bulunabileceği mozdev'de gördüğüm diğer bağlantılar bayattı. Bilginize, kod burada belirtildiği gibi MIT lisanslıdır: developer.mozilla.org/Project:Copyrights (yaklaşık olarak alabileceğiniz kadar iyi! :-)
cemerick

1
İlginç bir şekilde, jquery 1.4.2'den önce tüm MDC ECMA262-5 impls'lerini içeren bir js dosyasına başvurursam, jquery bozulur - örneğin tüm seçiciler başarısız olur, null döndürür. JQuery sonra MDC hareketleri beklenen davranışa yol açar. Çok tuhaf.
cemerick

Yani bir meraklı! Şuna bakacağım (bir test vakanız var mı?) ... Bunun neden olabileceğini hemen anlayamıyorum, ancak jQuery'nin 72. satırda yaptığı şey şüpheli görünüyor.
bobince

4
NOT: Bu saplamaların gerekli olduğu çoğu tarayıcıda, bir "for (somearray dizininde) {...}" yaparsanız, denetim olarak somearray.hasOwnProperty (index) kullanmanız gerekir. IE <= 8'in JS motoru buna array.prototype uzantılarını ekleyecektir. Google Adwords async kodu bunu yapmaz. En iyisi Underscore veya bu konuda standartlaşan başka bir kütüphanenin işlevselliğini kullanmak.
Tracker1

1
Bu IE 8 için bulabildiğim en hızlı indexOf () uygulamasıdır. Teşekkürler!
Alex Denysenko

27

Underscore.js'ye bir göz atın .


2
ES5Shim ve diğer saplamalar (MDC gibi) de başka sonuçlara yol açma eğilimindedir. Bu tür işlevler için, varsa iç yöntemleri kullanacak şekilde alt çizgi veya başka bir kitaplık kullanmak en iyisidir.
Tracker1

Underscore.js ile var arr = ['a', 'a1', 'b'] _.filter (arr, fonksiyon (a) {dönüş a.indexOf ('a')> -1;})
sri_bb

9

Kris Kowal , tarayıcının uygulamasında eksik olabilecek ECMAScript 5 işlevleri için bir dolgu işlevi gören küçük bir kütüphane derledi. Bazı işlevler hız için optimize edilecek ve tarayıcı hataları üzerinde çalışmak için diğer insanlar tarafından defalarca revize edilmiştir. Fonksiyonlar, spesifikasyonu mümkün olduğunca yakından takip etmek için yazılmıştır.

es5-shim.js , MIT lisansı altında piyasaya sürüldü, Array.prototype uzantıları en üste yakın ve kolayca ihtiyaç duymadığınız tüm işlevleri kesip kaldırabilirsiniz. Ayrıca yorumların olması gerekenden çok daha büyük olması nedeniyle senaryoyu küçültmenizi öneririm.


1

'Temel işlevleri yerine getirmemek' ile aslında 'ECMA 262 3'üncü ed'e uygun' anlamına mı geliyorsunuz? :)

Bahsettiğiniz yöntemler yeni 5'inci sürümün bir parçasıdır - bunu desteklemeyen tarayıcılar için 3'üncü değeri 5'inci boyuta genişleten aşağıdaki 'şimi' kullanabilirsiniz http://github.com/kriskowal/narwhal- lib / blob / narwhal-lib / lib / global-es5.js .


1
Bu iyi bir başlangıç, ancak MDC'den alınmayan uygulamalarda oldukça az hata var. Örneğin. dizi yöntemlerinin çoğu geri aramalarına yeterli sayıda bağımsız değişken iletmez ve geri arama işlevinde dizi mutasyonu durumunda oldukça doğru davranmaz.
bobince

Js'yi daha akılcı / minimal yetenekli bir dil haline getirmek için her türlü şeyi alacağım. </snark> :-)
cemerick

1

Bu senaryolar testlerimde iyi çalışmıyor. MDN belgelerine dayalı olarak aynı işlevlere sahip bir dosya oluşturuyorum .

Internet Explorer 8'de çok fazla sorun alanı çözüldü. Egermano / ie-fix.js içindeki koda bakın .


0

Underscore.js ile

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.