Undefined внутри for-in перебора без hasOwnProperty
Всем привет.
Что-то не могу разобраться в том, как работает перебор объекта. Вот код: if (typeof localStorage === 'object') { Storage.prototype.getFullSize = function() { var tempLen = 0; for(var x in localStorage) { tempLen = parseFloat(tempLen) + parseFloat((localStorage[x].length * 2)/1024/1024); } return tempLen; } } Ругается на localStorage[x].length, код ошибки: Unable to get property 'length' of undefined or null reference . Эмулировать подобную ошибку не получается, она проявляется в некоторых браузерах, вот один из них: Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MATBJS; rv:11.0) like Gecko (IE 11). Я встречал написание кода из документации с использованием hasOwnProperty: for (var prop in obj) { if(!obj.hasOwnProperty(prop)) continue; alert(prop + " = " + obj[prop]); } Гуглить пробовал, но не могу найти объяснения, зачем это надо и поможет ли это в данном случае. Почему элемент объекта может быть равен undefined или null ? localStorage.setItem('a',null); пробовал, ошибку в моих браузерах не кидает, включая IE 11. Подскажите почему происходит в редких браузерах подобная ошибка и как с ней бороться? И второй вопрос, для чего в таких случаях пишется hasOwnProperty, неужели доступа может не быть? |
Метод Object.prototype.hasOwnProperty используется, чтобы определить есть ли у объекта своё собственное, а не унаследованное свойство.
for(var property in object) {} не делает различия между свойствами объекта и его прототипа, перечисляет только перечислимые свойства. Ошибка, точней не то поведение, появляется во всех браузерах. Вы добавляете в Storage.prototype метод getFullSize, но не указываете, что оно не должно быть перечислимым. if(typeof localStorage === "object") { // добавленный метод Storage.prototype.getFullSize = function() {}; var items = []; // засчитано в localStore for(var property in localStorage) { items.push(property); } alert(items.join(", ")); } if(typeof localStorage === "object") { // тот же самый пример, но объявляем метод неперечислимым Object.defineProperty(Storage.prototype, "getFullSize", { value: function() {}, enumerable: false, configurable: true }); var items = []; // не засчитано в localStore for(var property in localStorage) { items.push(property); } alert(items.join(", ")); } Но например Модзилла считает свойства из Storage.prototype за перечислимые, поэтому необходима проверка на то, что свойство является собственным(что гарантирует, что ключ именно из локального хранилища). Вот здесь и нужен hasOwnProperty if(typeof localStorage === "object") { // тот же самый пример, но объявляем метод неперечислимым Object.defineProperty(Storage.prototype, "getFullSize", { value: function() {}, enumerable: false, configurable: true }); var items = []; for(var property in localStorage) { if(localStorage.hasOwnProperty(property)) { items.push(property); } } alert(items.join(", ")); } Ну, а также существует метод Object.keys, который позволяет получить свои собственные имена свойств объекта if(typeof localStorage === "object") { var items = []; Object.keys(localStorage).forEach(function(key) { items.push(key); }); alert(items.join(", ")); } |
Часовой пояс GMT +3, время: 20:07. |