Подтвердить что ты не робот

Javascript "pop" из объекта

Я написал следующий код для "pop" свойства объекта, как если бы это был массив. Это похоже на тот код, который заставил бы меня похлопать более серьезных программистов, поэтому мне было интересно, как правильно это сделать:

// wrong way to pop:
for( key in profiles ){
    var profile = profiles[key];  // get first property
    profiles[key] = 0;            // Save over property just in case "delete" actually deletes the property contents instead of just removing it from the object
    delete profiles[key];         // remove the property from the object
    break;                        // "break" because this is a loop
}

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

4b9b3361

Ответ 1

for( key in profiles ){

Вы действительно должны объявить key как var.

profiles[key] = 0;            // Save over property just in case "delete" actually deletes the property contents instead of just removing it from the object

не требуется. Удалить не затрагивает значение свойства (или в случае свойства, у которого есть сеттер, но нет геттера, даже требует, чтобы он имел значение).

Если объект имеет какие-либо перечислимые свойства на своем прототипе, то это сделает что-то нечетное. Рассмотрим

Object.prototype.foo = 42;

function pop(obj) {
  for (var key in obj) {
    // Uncomment below to fix prototype problem.
    // if (!Object.hasOwnProperty.call(obj, key)) continue;
    var result = obj[key];
    // If the property can't be deleted fail with an error.
    if (!delete obj[key]) { throw new Error(); }
    return result;
  } 
}

var o = {};
alert(pop(o));  // alerts 42
alert(pop(o));  // still alerts 42

Ответ 2

Свойства объекта не хранятся в стеке, поэтому базовая концепция не будет работать надежно (кроме других вопросов, упомянутых в комментариях выше).

Если вам действительно нужна такая конструкция, попробуйте что-то вроде этого.

var ObjectStack = function(obj) {
    this.object = obj;
    this.stack=[];
};
ObjectStack.prototype.push = function(key,value) {
    this.object[key]=value;
    this.stack.push(key);
};
ObjectStack.prototype.pop = function() {
    var key = this.stack.pop();
    var prop = this.object[key];
    delete this.object[key];
    return prop;
};

var my_obj = {};
var my_stack = new ObjectStack(my_obj);
my_stack.push("prop1",val1);
my_stack.push("prop2",val2);

var last_prop = my_stack.pop(); //val2

Демо: http://jsfiddle.net/a8Rf6/5/

Ответ 3

В настоящее время вы можете просто использовать оператор распространения с его способом Rest:
const {key,... profileWithoutKey} = анкеты;

Кредит на этот пост

Ответ 4

В браузерах нет "правильного" порядка в том, что они дают для цикла for in. Некоторые делают их в том порядке, в котором они помещены, а другие - это числовые индексы. Таким образом, действительно невозможно сделать это, не создавая собственный пользовательский объект

Ответ 5

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

Object.defineProperty(Object.prototype, 'pop',{
    writable: false
    , configurable: false
    , enumerable: false
    , value: function (name) {
        var value = this[name];
        delete this[name];
        return value;
    }
});

по какой-то причине, используя только Object.prototype.pop = function... breaks JQuery

Ответ 6

Лучший подход вместо прямой модификации входного массива. Например.

let arr = [{label: "a"}, {label: "b"}, {label: "p"}, {label: "c"}] 
let newArr = arr.filter(p => { return p.label !== "p";});

Ответ 7

Изучив все комментарии и решения выше, я могу предложить полностью готовое решение на их основе:

Object.prototype.pop = function() {
    for (var key in this) {
        if (!Object.hasOwnProperty.call(this, key)) continue;
        var result = this[key];
        if (!delete this[key]) throw new Error();
        return result;
    }
};

var obj = {
    a: '1',
    b: '2',
    c: '3'
};

console.log(obj.pop()); // 1
console.log(obj.pop()); // 2
console.log(obj.pop()); // 3
console.log(obj); // Object {  }

Возможно, кому-то пригодится; )


PS. Если вы используете предложенный мной код вместе с библиотекой jQuery, вы можете столкнуться с ошибками в консоли. В этом случае уместен вариант, указанный ниже:

function _pop() {
    for (var key in this) {
        if (!Object.hasOwnProperty.call(this, key)) continue;
        if (key === 'pop') continue;
        var result = this[key];
        if (!delete this[key]) throw new Error();
        return result;
    }
}

var obj = {
    a: '1',
    b: '2',
    c: '3'
};

obj.pop = _pop;

console.log(obj.pop()); // 1
console.log(obj.pop()); // 2
console.log(obj.pop()); // 3
console.log(obj); // Object { pop: _pop() }