JavaScript-Объекты Размещения / Метод Разбора Строк


Это JS функция предназначена для извлечения или место значение в объект с вложенными ключами, как струна.

Например

var obj = {a: {b: [4]}};
parse_obj_key(obj, "a.b.0") should equal 4.
parse_obj_key(obj, "a.c", 2) should add another element to "a" named "c" with value 2.

Метод работает, но я хочу его убрать, если это возможно (или более полированный реализации, которая является общедоступной). Я тоже люблю знать, какие граничные случаи неудач, которые могут быть найдены.

function parse_obj_key(obj, loc, val){
    var _o = obj;
    while (true){ 
        var pos = loc.indexOf('.');                        

        if (!_o || typeof _o != 'object'){
            $.log("Invalid obj path: " + loc + "\n" + JSON.stringify(obj));
            return null;      
        }                                                    

        if (pos === -1){
            if (val){
                _o[loc] = val;                 
                return obj;                                           
            } else {
                if (!isNaN(parseInt(loc)))
                    loc = parseInt(loc);

                return _o[loc];
            }
        }
        var part = loc.substring(0, pos);                    
        var loc = loc.substring(pos + 1);                     

        if (!isNaN(parseInt(part)))
            part = parseInt(part);   

        if (!(part in _o)){
            if (val)
                _o[part] = new object;                                        
            else
                return null;                                           
        }
        _o = _o[part];                      
    }                                                                         
}


578
5
задан 27 января 2011 в 11:01 Источник Поделиться
Комментарии
3 ответа

Вот что не так с вашим кодом:


  • Не используйте имена переменных, как _o. Получите редактор с хорошим авто-завершения.

  • typeof на _o != 'объект' не делать то, что вы думаете, что он делает: для вызова typeof([1,2]) // "объект".
    В общем, делать те виды проверок-это код запах.

  • если (!isNaN(parseInt(Лок))) Лок = parseInt(Лок);. Запутанно и не нужен.
    На JavaScript: ['А', 'Б']["1"] // 'б'. То же самое касается других isNaN

  • в. Не делайте это проверить. значение NULL - это значение, но то, что вы хотите вернуть-это отсутствие ценности. Это значение undefined в JavaScript, и это то, что будет возвращено, если нет никакого значения.

  • Рассмотрите возможность использования сплит вместо помощи indexOf и подстроки. Это гораздо быстрее и делает код более читаемым.

Итак, вот красивый вариант для вас:

function chained(obj, chain, value){
var assigning = (value !== undefined);
// split chain on array and property accessors
chain = chain.split(/[.\[\]]+/);
// remove trailing ']' from split
if (!chain[chain.length - 1]) chain.pop();
// traverse 1 level less when assigning
var n = chain.length - assigning;
for (var i = 0, data = obj; i < n; i++) {
data = data[chain[i]];
// if (data === undefined) return; // uncomment to handle bad chain keys
}

if (assigning) {
data[chain[n]] = value;
return obj;
} else {
return data;
}
}

Расказывает: http://glebm.blogspot.com/2011/01/javascript-chained-nested-assignment.html

Пожалуйста, придумать дальнейшие улучшения :)

3
ответ дан 28 января 2011 в 04:01 Источник Поделиться

Я мало знаю о JavaScript, и думал, что решение твое-хорошо.
уже glebm код, кажется, не работает для parse_obj_key(объект, "это.С. С. с", 2)

Я пытаюсь изменить код в стиле рекурсии, и она работает, "новый объект" идет неправильно на мой Firefox, так что я изменить его на = {}

function parse_obj_key(obj, loc, val) {
if(!obj || typeof obj != 'object') {
alert("error")
return null
}
var pos = loc.indexOf('.');
var part = loc.substring(0, pos);
var endpart = loc.substring(pos+1);

if (!isNaN(parseInt(part)))
part = parseInt(part);

if (pos === -1) {
if (val) {
obj[loc] = val
return obj
}
else
return obj[loc]
}

if (val) {
if (!(part in obj))
obj[part] = {}

parse_obj_key(obj[part], endpart, val)
return obj
}
else {
return parse_obj_key(obj[part], endpart, val)
}
}

0
ответ дан 28 января 2011 в 07:01 Источник Поделиться

Мой код основан уже glebm, но я изменил его так, что такие поиски должны всегда использовать . синтаксис. Я сделал несколько других изменений, таких как создание объекта цепь, если назначение на вложенный ключ, который еще не существует.

function parse_obj_key(obj, key, value){
var is_assigning = (value !== undefined);
key = key.split('.');

var data = obj;
var length = key.length - is_assigning;

for (var i = 0; i < length; i++) {
var child = data[key[i]];
var has_child = (child !== undefined);

if (!has_child && !is_assigning) {
$.log("Invalid obj path: " + key + "\n" + JSON.stringify(obj));
return null;
}

if (!has_child) {
child = {};
data[key[i]] = child;
}

data = child;
}

if (is_assigning) {
data[key[i]] = value;
} else {
return data;
}
}

Если вы пытаетесь создать необязательный параметр, вы должны проверить, если он не определен, используя если (парам !== не определено), а не только если (парам), в противном случае вы будете иметь проблемы с установкой ложь ценностей, таких как ложь, нуль, 0 и "".

Одна из вещей, которая позволяет этот код, чтобы быть намного короче, это замечание о том, что в JavaScript модуль arr['А']['Б'][0] такое же, как и Арр['А']['Б']['0'] - это, так сказать, массив подстановок, используя целое число, ничем не отличается от выбора подстановки, используя строку, содержащую число. Это позволяет избежать необходимости разобрать цифры, как вы делаете.

Основных Saver является использование Сплит, а не индексация, что делает его легко для петли за части ключа.

0
ответ дан 29 января 2011 в 09:01 Источник Поделиться