IE8 ошибка в for-in заявлении JavaScript? - PullRequest
9 голосов
/ 14 сентября 2010

Я думаю, что нашел ошибку в обработке IE (IE8) для оператора javascript for-in. После нескольких часов обработки этого примера до небольшого, похоже, что IE специально пропускает любое свойство, называемое «toString» в цикле for-in - независимо от того, находится ли оно в прототипе или является «собственным свойством» объекта.

Я разместил свой тестовый код здесь :

function countProps(obj) {
    var c = 0;
    for (var prop in obj) {
        c++;
    }
    return c;
}

var obj = {
    toString: function() {
        return "hello";
    }
};

function test() {
    var o = "";
    var d = document.getElementById('output');

    o += "<br/>obj.hasOwnProperty('toString') == " + obj.hasOwnProperty('toString');
    o += "<br/>countProps(obj) = " + countProps(obj);
    o += "<br/>obj.toString() = " + obj.toString();

    d.innerHTML = o;
}

Это должно дать:

obj.hasOwnProperty('toString') == true
countProps(obj) = 1
obj.toString() = hello

но в IE я получаю:

obj.hasOwnProperty('toString') == true
countProps(obj) = 0
obj.toString() = hello

Этот особый случай любого свойства, называемого toString, разрушает мой код, который пытается скопировать методы в Function.prototype - моя пользовательская функция toString всегда пропускается.

Кто-нибудь знает обходной путь? Это какое-то поведение только в режиме причуд - или просто ошибка?

Ответы [ 2 ]

10 голосов
/ 14 сентября 2010

Да, это ошибка. См. этот ответ .

Цитирование CMS :

Другая известная ошибка JScript - это «Ошибка DontEnum», если объект в его цепочке областей действия содержит свойство, которое не является перечисляемым (имеет атрибут {DontEnum}), если свойство затенено для другого объекта, оно останется как не перечисляемый, например:

var dontEnumBug = {toString:'foo'}.propertyIsEnumerable('toString');

В IE он оценивается как ложный, это вызывает проблемы при использовании оператора for-in, поскольку свойства не будут посещаться.

2 голосов
/ 14 сентября 2010

Это ошибка в IE, которая также применяется к свойствам с именем valueOf.

. Вы можете обойти это следующим образом:

if(obj.toString !== Object.prototype.toString || obj.hasOwnProperty("toString"))
    //Handle it
if(obj.valueOf !== Object.prototype.valueOf || obj.hasOwnProperty("valueOf"))
    //Handle it
...