2013-10-08 5 views
2

У меня есть некоторые небольшие, но полезные дополнительные методы для основных JS объектов, таких как массив:Javascript: прототип х defineProperty х, что еще

Array.prototype.indexOfObject (свойство, значение)

Этот метод возвращает индекс объект в массиве (объектов), где свойство == значение, простое и продуктивное для меня.

Однако, когда я перечислить любой массив, метод будет отображаться, поэтому каждый раз, когда я должен сделать так:

for(var i in MyArray){ 
    if(typeof(MyArray[i])=="typeneeded"){ 
    // do something 
    } 
} 

Как я знаю, defineProperty сделать ноны перечислимого метода так он будет решать моя проблема, когда все браузеры ее принимают. Кстати, это уже безопасное использование defineProperty? IE9 работает хорошо? Другие браузеры? Есть ли третий способ сделать это?

+1

Попробуйте [caniuse. com] (http://caniuse.com/), имеет полезную информацию об этом. –

+6

Вы не должны использовать 'for ... in' с массивом. Используйте обычный цикл 'for' с инкрементирующим индексом или' forEach', если он доступен. – Phil

+0

Использование традиционных для решения проблемы взламывания бесполезного оператора if. Я думаю, что мне нравится ... в, напомнить мне другие языки, но это жизнь ... – Gustavo

ответ

3

Существует несколько совместимых с ECMAScript матриц: kangax's подходит только для ES5, Thomas Lahn's расскажет вам, какие функции поддерживаются в версиях различных версий ECMAScript.

A «третий путь» является использование hasOwnProperty теста, который работает во всех браузерах и является хорошей идеей, в любой среде, что вы не контролируете полностью:

for (var p in obj) { 

    if (obj.hasOwnProperty(p)) { 

    // p is an own property of obj 
    // do stuff with obj[p] 
    } 
} 

Вы также можете использовать Object.keys, который возвращает только собственные свойства, но поддержка может быть меньше, чем для defineProperty.

Следует также отметить, что для .. в необязательно возвращает свойства в каком-либо конкретном порядке и может быть отображен для возврата их в разных заказах в разных браузерах. Поэтому используйте его только с массивом, где порядок доступа к членам не важен.

PS. Вы можете также использовать propertyIsEnumerable тоже, как только возвращает истину свойства на самый объекте:

if (obj.propertyIsEnumerable(p)) { 

Это было использовано для размещения ошибки в начале Safari, но эта версия не должна быть в использовании больше ,

Кстати, в:

> typeof(MyArray[i]) 

нет необходимости в скобках, TypeOf является оператором. Кроме того, проверка свойства Type не означает, что это собственное свойство объекта или нет, или даже если оно существует (хотя в этом случае оно происходит, потому что оно исходит от для .. в).

+0

Это улучшит мой код, но сохранит структуру, которую я хочу сломать. – Gustavo

+0

@RobG: Ваша ссылка Томаса Лэна кажется сломанной. – Aeoril

+0

@ aeoril - ссылка в порядке, сервер немного медленный. – RobG

1

Вы можете использовать hasOwnproperty безопасно для всех браузеров, но ваш вопрос был о Object.defineProperty.Если вы не беспокоитесь о старых браузерах (IE8), то вы можете использовать это:

//you should reload when you want to change value 
//or you'll get a can't redefine error 
Object.defineProperty(Array.prototype,"someFn",{ 
    enumerable: false, 
    configurable: false, 
    writable: false, 
    value: function(){console.log("my fn");} 
}); 

var a = [1,2,3,4]; 
for(thing in a){ 
    console.log(thing);//=0,1,2,3 
} 
a.someFn();//=my fn 
+0

Если проблема заключается только в IE8 и предыдущем IE, возможно, я изменю прототип методом defineProperty, это будет «улучшенный» способ реализации методов. Я устал от беспокойства с IE8 ... – Gustavo

1

Просто используйте традиционный цикл, или Foreach:

var i, 
    ary = ['val0', 'val1', 'val2']; 

Array.prototype.getElem = function (i) { 
    return this[i]; 
}; 

console.log('First way - using standard for loop:'); 
for (i = 0; i < ary.length; i++) { 
    console.log('Element ' + i + ' has value ' + ary[i]); 
} 

console.log('second way - use "first order function" - "functional programming" style'); 
ary.forEach(function (e, i) { 
    console.log('Element ' + i + ' has value ' + ary[i]); 
}); 

console.log('getElem says: element 2 has value ' + ary.getElem(2)); 

FIDDLE

+0

@ Расскажите о других типах циклов. forEach не всегда доступен, и традиционный вариант - это вариант, да. Но я открыл этот поток для «предыдущего» решения, потому что, когда лучше просто изменить способ, которым вы занимались. Но спасибо за создание скриптов для нас. – Gustavo

+0

@GustavoPinent Если вы хотите, чтобы ваши новые методы были неперечислимыми, используйте defineProperty. Однако при перечислении элементов массива с индексом с целыми числами вы, вероятно, должны использовать традиционные или forEach. defineProperty также не всегда доступен. – Aeoril