使用自执行匿名函数

7
我正在尝试为学习目的构建一个购物车。我有以下代码:
HTML
<div id="MyCart" class="product-cart">
    <ul>
        <li class="item"></li>
        <li class="item"></li>
        <li class="item"></li>
    </ul>
</div>

JavaScript
var cart = (function () {

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


    return cart;
}());

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

这段代码抛出以下错误:
未捕获的类型错误:无法设置未定义的“createCart”属性。
在花费了几个小时在互联网上查找并跟随一些教程后,我对代码进行了以下更改,然后它开始工作了。
但是我仍然不明白我在这里做了什么。
var cart = (function (cart) {

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


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

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

可以有人解释一下在将`cart || {}`表达式传递到匿名函数中后,为什么代码开始工作了吗?详细的解释会非常好。 :)
这段英文的意思是:请问有人能够解释一下,在将`cart || {}`表达式传递到匿名函数中后,为什么代码开始工作了?希望能提供详细的解释。

1
cart 在 cart.createCart 中未定义。您应该在 cart 函数之外使用它。 - Bhojendra Rauniyar
1
该函数期望cart作为参数,如果不传入cart || {},则相当于未传入任何参数,因此cart将是未定义的。请记住,IIFE具有完全隔离的作用域。 (注:IIFE指立即调用的函数表达式) - Callum Linington
4个回答

4

如果没有变量传递到作用域中,那么就无法使用。

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的空值合并操作,它表示如果cart为空,则传递一个空对象。

2

由于您正在声明cart变量,因此它尚未实例化。当您传入一个空对象时(这就是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

我没有运行这段代码,但从阅读中:

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

在第二个示例中,cart对象仍不存在,但你提供了一个回退到新的空白对象:

cart || {}

因此,在函数内部,cart是一个新的空对象,您可以应用createCart属性。
编辑:Erik Lundgren刚刚发布的另一个函数是您所需要的。它的含义更清晰,因为cart对象在函数内明确实例化。使用那个! :)
我唯一想添加的是,在这种特定情况下,您没有任何理由在立即调用的函数表达式中执行所有这些操作。在其中没有需要作用域限制的内容。所以这样做会起到作用:
var cart = {};
cart.createCart = function (cartId) {
    console.log(cartId);
    cartId = document.getElementById(cartId);
}   

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

1
使用这段代码:
(cart || {})

你正在传递函数的作用域,如果为空,则传递一个空对象 ({})。看起来你有一个cart对象,并且当你执行 var cart = (function .... 时,你正在覆盖它。
也许你的对象必须被称为大写的 Cart ,这也可以工作:
  var cart = (function() {
       Cart.createCart()...
  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接