纯JS |篮子|关闭

时间:2014-11-24 09:49:43

标签: javascript oop closures cart

我正在开发一个小型JavaScript应用程序,用户可以点击页面上的按钮并将其传递给他们的篮子。我这样做的问题是我不确定在同一个函数中处理多个按钮。我不想为每个按钮写出不同的功能。

我正在努力做到OOP并且到目前为止这样做了:

var shop = {};

shop.items = [];

shop.Item = function(item, description, price) {
    this.item = item;
    this.description = description;
    this.price = price;
};

shop.print = function() {
    var itemCon = document.getElementById('items'),
        html = "";
    for(var i = 0; i < this.items.length; i++) {
        html += '<div id="item">';
        for(prop in this.items[i]) {
            html += '<p><span class="title">' + prop + '</span>: ' + this.items[i][prop] + '</p>';
        };
        html += '<button id="' + this.items[i].item + '">Add to Basket</button>'
        html += '</div>';
    };
    itemCon.innerHTML += html;
};

shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");

var basket = {};

basket.items = [];

basket.Item = function(item, description, price) {
    this.item = item;
    this.description = description;
    this.price = price;
};

basket.add = function(data) {
    this.items[items.length] = new Item(data.item, data.description, data.price);
};

basket.costCalculate = function() {
    var cost = 0,
        html = "Total: " + cost;
    for(var i = 0; i < this.items.length; i++) {
        cost += items[i].price;
    };
    return html;
};

basket.print = function() {
    var output;
    for(var i = 0; i < this.items.length; i++) {
        for(prop in this.items[i]) {
            console.log(prop + ":  " + this.items[i][prop]);
        };
    };
};

function init() {
    shop.print()
};
window.onload = init;

如何确定点击了哪个项目以运行basket.add(数据)。我如何将每个项目的数据传递给该函数。

另外,如何实现关闭呢?我明白是内部函数可以访问外部函数的变量,到目前为止我正在使用闭包吗?

1 个答案:

答案 0 :(得分:2)

好的,你已经取得了不错的开局,但这里有一些建议:

  1. 每个Item只有一个实例可能是个好主意。我的意思是看起来你创建了一堆Item来填充商店的库存,例如:

    var coat = new Item("Coat", "Warm", 20);
    shop.items.push(coat);
    

    现在,当您点击UI元素时,理想情况下您希望同一个coat实例也进入您的购物篮,所以:

    // User clicks on UI element, which triggers the following to execute:
    basket.add( someItemIdentifier );
    

    所以现在,如果您决定将所有价格提高10美元,那么您可以这样做:

    shop.increasePricesBy = function(amount) {
        for(var i = 0; i < shop.items.length; i++) {
            shop.items[i].price += amount;
        }
        // execute some function to update existing baskets' totals
    };
    

    我希望这对于为什么应该有多个集合引用的每个项目的一个实例是有意义的。

    这就引出了一个问题,即如何将客户的互动与添加正确的项目联系起来。一种解决方案可以是使用任意ID来跟踪项目。例如:

    // Create new item with some randomly generated ID
    var coat = new Item({
        id: "93523452-34523452",
        name: "Coat",
        description: "Warm",
        price: 20
    });
    shop.items = {}; // Use a hash so it's easier to find items
    shop.items[coat.id] = coat;
    

    你的UI元素可能是这样的div:

    <div class="add-product-button" data-id="93523452-34523452">
    

    添加点击处理程序:

    // Pure JS solution - untested
    var clickTargets = document.getElementsByClassName("add-product-button");
    for(var i = 0; i < clickTargets.length; i++) {
        var clickTarget = clickTargets[i];
        clickTarget.onClick = function() {
            var itemID = clickTarget.getAttribute("data-id");
            var item = shop.items[itemID];
    
            basket.add(item);
        };
    }
    
    // Equivalent jQuery code
    $(".add-product-button").click(function() {
        var id = $(this).attr('data-id');
        var item = shop.items[id];
        basket.add(item);
    });
    

    虽然你的篮子实现add类似的东西:

    basket.add = function(items) {
        this.items.push(item);
    };
    

    您的costCalculate方法变得更容易:

    basket.costCalculate = function() {
        var cost = 0;
        for(var i = 0; i < this.items.length; i++) {
            cost += this.item[i].price;
        }
        return cost;
    };
    
  2. 而不是这样做:

    shop.items[shop.items.length] = new shop.Item("Coat", "Warm", "20");
    

    您可以改为:

    shop.items.push(new shop.Item("Coat", "Warm", "20");
    
  3. 使用数字代替字符串代表价格可能是个好主意。

  4. shop.print循环中,您可能不希望硬编码<div id="item">,因为这会导致多个div具有相同的ID。

  5. 最后,我不打算在这里回答你的关闭问题,因为我觉得我已经得到了比我已经解决的更好的答案,所以我只是将你链接到一些帮助我理解它的优秀资源: / p>


  6. 如果您有任何问题,请告诉我,我完全可以讨论这些问题了。