使用自调用匿名函数

时间:2015-07-10 08:24:12

标签: javascript object anonymous-function

我正在尝试构建一个用于学习目的的购物车。我有以下代码

HTML

<div id="MyCart" class="product-cart">
    <ul>
        <li class="item"></li>
        <li class="item"></li>
        <li class="item"></li>
    </ul>
</div>

JS

var cart = (function () {

    cart.createCart = function (cartId) {
        console.log(cartId);
        cartId = document.getElementById(cartId);
    }   


    return cart;
}());

var shoopingCart = cart.createCart("MyCart");

但此代码会抛出以下错误

  

未捕获的TypeError:无法设置属性&#39; createCart&#39;未定义的

在互联网上花了几个小时并按照一些教程后,我对代码进行了更改,然后开始工作。

但我仍然不明白我在这里做了什么

var cart = (function (cart) {

    cart.createCart = function (cartId) {
        console.log(cartId);
        cartId = document.getElementById(cartId);
    }   


    return cart;
}(cart || {}));

var shoopingCart = cart.createCart("MyCart");

有人可以解释一下为什么在将cart || {}表达式传递给匿名函数后代码开始工作了吗?一些详细的解释会很棒。 :)

4 个答案:

答案 0 :(得分:3)

所以没有传递给范围的变量。

var cart = (function (cart) {

    // can't add a property or method onto undefined.
    cart.createCart = function (cartId) {
        console.log(cartId);
        cartId = document.getElementById(cartId);
    }   


    return cart;
}()); // without any value here ^ cart will be undefined.

var shoopingCart = cart.createCart("MyCart");

但是,如果将变量传递给上下文:

var cart = (function (cart) {

    // cart now is an object which you can attach a property or method
    cart.createCart = function (cartId) {
        console.log(cartId);
        cartId = document.getElementById(cartId);
    }   


    return cart;
}(cart || {})); // pass in cart, or if it is null a new object {}

var shoopingCart = cart.createCart("MyCart");

所以IIFE看起来像这样:

(function () { })();

在第二对括号中忽略function得到( )();,将参数传递给第一组中的function。这是因为IIFE创造了一个全新的清洁范围。这就是我们使用IIFE的原因,因为它可以隔离我们在其中使用的全局变量。

所以,如果你有这个:

<script>

var someGlobalVariable = "hey";

(function () {

   // using someGlobalVariable here will be fine

   var myIIFEScopedVariable = "ho"; 

})();

// trying to access myIIFEScopedVariable here will fail because again, it hasn't been defined here.

</script>

因此,IIFE非常适合控制范围内的内容。

cart || {}是一个JavaScript null coalesce,所以它说,传入购物车,但如果它为null则为它提供一个空对象

答案 1 :(得分:2)

因为您正在声明购物车变量,所以它尚未实例化。当你改为传入一个空对象时(cart || {}会对它进行评估,然后将该方法添加到该对象,返回它,然后cart将成为该对象。第二个函数的作用基本上与以下代码:

var cart = (function () {
    var cart = {};
    cart.createCart = function (cartId) {
        console.log(cartId);
        cartId = document.getElementById(cartId);
    }   


    return cart;
}());

var shoopingCart = cart.createCart("MyCart");

答案 2 :(得分:2)

我没有运行此代码,而是阅读它:

在第一个示例中,在第三行,您调用 cart.createCart ,对象购物车尚不存在。该函数尚未返回其自身在内部引用的对象!

在第二个示例中,购物车对象仍然不存在,但您提供了对新空白对象的回退:

cart || {}

因此,在函数内部,购物车是一个新的空白对象,您应用 createCart 属性。

编辑:Erik Lundgren刚刚发布的替代功能就是您所需要的。它的意思更清晰,因为cart对象在函数内部被清楚地实例化。用那个! :)

我要添加的唯一内容是,在这种特殊情况下,你没有任何理由在一个立即调用的函数表达式中完成所有这些操作。那里没有什么需要确定范围。所以这样做:

var cart = {};
cart.createCart = function (cartId) {
    console.log(cartId);
    cartId = document.getElementById(cartId);
}   

var shoopingCart = cart.createCart("MyCart");

答案 3 :(得分:1)

使用此代码:

(cart || {})

您正在传递函数的范围,如果它是空的,则传递一个空对象({})。您似乎有一个cart对象,当您创建var cart = (function ....时,您将覆盖它。

也许你的对象必须用大写调用Cart,它也适用:

  var cart = (function() {
       Cart.createCart()...
  });