Почему мои методы работы с массивами не работают в классе в ECMA6

Igor Shvets спросил: 10 мая 2018 в 04:18 в: javascript
  1. Метод удаления продукта по имени "deleteProductByName" не работает
  2. Метод, который возвращает имена всех созданных продуктов "getAllProductNames" не работает.
  3. Метод, который возвращает общую стоимость всех продуктов "get totalProductsPrice", должен работать как "getter". Помогите исправить эти методы
  4. ол>
    class Product {
        constructor(name, count, price) {
            this.name = name;
            this.count = count;
            this.price = price;
        }
    }
    class Shop extends Product {
        constructor(products) {
            super();
            this.products = [];
        }
    
        addProduct(newProduct) {
            this.products.push(newProduct);
        }
    
        deleteProductByName(productName) {
            let i = this.products.length;
            while (i--) {
                if (productName in this.products[i]) {
                    this.products.splice(i, 1);
                }
            }
        }
    
        getAllProductNames() {
            return this.products.map(object => Object.values(object)[0].name);
        }
    
        get totalProductsPrice() {
            return this.products.map(object => Object.values(object)[0].price).
            reduce((p, c) => p + c);
        }
    }
    const shop = new Shop();
    shop.addProduct(new Product("product 1", 1, 200));
    shop.addProduct(new Product("product 1", 1, 500));
    shop.addProduct(new Product("product 2", 2, 1000));
    
    console.log(shop.totalProductsPrice);
    console.log(shop.getAllProductNames());
    shop.deleteProductByName("product 2");
    console.log(shop.products);

2 ответа

HMR ответил: 10 мая 2018 в 04:32

Object.values(object)[0] - плохая идея, потому что Object.values ​​не гарантирует, что он находится в каком-либо конкретном порядке, в документации здесь говорится:

в том же порядке как это предусмотрено в for ... in loop

И для ... в документации говорится:

A для ... в цикле выполняет итерации по свойствам объекта в произвольном порядке (более подробно о том, почему нельзя зависеть от кажущейся упорядоченности итерации, по крайней мере, в настройках кросс-браузера).

Вот как вы могли это сделать:

getAllProductNames() {
    return this.products.map(p=>p.name);
}get totalProductsPrice() {
    return this.products.map(p=>p.price).reduce((p, c) => p + c);
}

И для удаления продуктов вы можете использовать filer:

deleteProductByName(productName) {
    this.products = this.products.filter(p=>p.name!==productName);
}
Есть решение
Terry ответил: 10 мая 2018 в 04:27

В общем, причина, по которой ваш скрипт не работает, объясняется главным образом вашей путаницей в том, как обращаться с массивами. Обратите внимание, что ваш this.products представляет собой массив объектов. Чтобы ответить на ваши вопросы один за другим:

Это потому, что вы проверяете ключ (а не значение) своей логикой:

productName in this.products[i] 

Что вы должны сделать это, вместо этого:

productName === this.products[i].name

Это потому, что object в предикате / обратном вызове фактически ссылается на отдельный product объект. И этот объект имеет name, count и price. Поэтому вместо того, чтобы делать то, что вы сделали:

return this.products.map(object => Object.values(object)[0].name);

... использование этого будет работать (это просто доступ к свойству / ключу продукта с использованием точечной нотации):

return this.products.map(product => product.name);

Он определен как геттер правильно, но вы совершили ту же ошибку, что и в Q2: вы неправильно обращаетесь к ценам. Вместо этого:

return this.products.map(object => Object.values(object)[0].price).reduce((p, c) => p + c);

... вы должны делать как таковое:

return this.products.map(product => product.price).reduce((p, c) => p + c);

См. Доказательство -concept example:

class Product {
    constructor(name, count, price) {
        this.name = name;
        this.count = count;
        this.price = price;
    }
}
class Shop extends Product {
    constructor(products) {
        super();
        this.products = [];
    }

    addProduct(newProduct) {
        this.products.push(newProduct);
    }

    deleteProductByName(productName) {
        let i = this.products.length;
        while (i--) {
            if (productName === this.products[i].name) {
                this.products.splice(i, 1);
            }
        }
    }

    getAllProductNames() {
        return this.products.map(product => product.name);
    }

    get totalProductsPrice() {
        return this.products.map(product => product.price).reduce((p, c) => p + c);
    }
}
const shop = new Shop();
shop.addProduct(new Product("product 1", 1, 200));
shop.addProduct(new Product("product 1", 1, 500));
shop.addProduct(new Product("product 2", 2, 1000));

console.log(shop.totalProductsPrice);
console.log(shop.getAllProductNames());
shop.deleteProductByName("product 2");
console.log(shop.products);

Дополнительное видео по вопросу: Почему мои методы работы с массивами не работают в классе в ECMA6

Javascript - forEach, filter, map, every, some, reduce, reduceRight (методы перебора массива)

JavaScript - #11 МАССИВЫ (свойства и методы объекта)

Основы ES6 #9: Классы