首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这个代码构造包装了库的各个部分,它有什么用处?

这个代码构造包装了库的各个部分,它有什么用处?
EN

Stack Overflow用户
提问于 2015-01-15 09:48:30
回答 6查看 4.1K关注 0票数 39

我模仿了一个库,并能够编写以下代码。此代码创建了分配给'c'函数的'a'对象。因此,要调用'a',我必须编写c.a()

此外,我还向这个'c'对象添加了更多的函数。我想了解这段代码中发生了什么。它看起来不像普通的面向对象编程。这种类型的javascript编程叫什么?

代码语言:javascript
运行
复制
var c = (function(c) {
    if (c === undefined) {
        c = {};
    }

    function a() {
        alert(1);
    }
    c.a = a;
    return c;
}(c));
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2015-01-15 09:53:27

这是一个模块模式。你会看到这个模式的许多变体,所以了解真正发生的事情是很重要的,你不能只是模仿一个。

这段代码的目的是完成一个对象c (通常是全局库)。您可能在应用程序中有许多类似的代码,所有构建c的代码片段,可能每个都在自己的文件中。

如果作为参数传递给函数的库对象c还不存在( c === undefined ),则创建它。这使得不依赖于执行顺序或预执行文件成为可能。

赋值的右边部分是生平 (立即调用函数表达式),即立即调用的函数。这种结构的优点是它创建了一个变量(例如a函数)可以在不污染外部(全局)作用域的情况下声明的作用域。在这里,问题是没有意义的,因为a是外部化的,但是一个模块通常依赖于几个内部(私有)函数和变量。

一个可能需要解释的细节:所有这些文件看起来都定义了一个新变量c,但是这里没有问题,即使这些文件是连接的:如果一个var语句已经存在,它就不会定义一个新变量(在这里,甚至在声明点之前,就为整个作用域定义了一个变量)。

另一种写这个的方法是

代码语言:javascript
运行
复制
var c = c || {}; // ensure the c variable is defined, and initialize its value it if necessary

(function() { // let's use an IIFE to have a protected scope and not pollute the global one
  function a() {
    alert(1);
  }
  c.a = a; // let's augment c
})();

这个可能更清楚

  • 它显式地分隔了两个步骤(c初始化和使用IIFE完成c )。
  • 它不依赖于同名的两个c变量
  • 它不那么冗长
票数 42
EN

Stack Overflow用户

发布于 2015-01-15 09:56:27

下面是相同的代码,并添加了注释,说明每行都做了什么,以及传递时会发生什么。

代码语言:javascript
运行
复制
//Here, we're defining a function that will return an object.
//its only parameter is named 'c'
//this is confusing, since the parameter has the same name as the global definition of the function.

//the var c definition is the global definition. the function parameter is not.
//so every reference to anything named 'c' inside the function definition is local. 
var c = (function(c) 
{
  //if c (the c we passed as a parameter) is not yet defined
  if (c === undefined) {
    //define c as an object
    c = {};
  }

  //define a function
  function a() {
    alert(1);
  }
  //attach it to the object
  c.a = a;

  //return the object
  return c;
}(c)); // call the constructor we just defined, using the global definition of `c`.
       // the first time we pass this point, c as a variable is still undefined.
票数 36
EN

Stack Overflow用户

发布于 2015-01-15 21:39:31

代码语言:javascript
运行
复制
var c = (function(c) {
    if (c === undefined) {
        c = {};
    }

    function a() {
        alert(1);
    }
    c.a = a;
    return c;
}(c));

让我们一步一步地走。

var c =

初始化一个名为c的变量。注意,此时,如果名为c的变量已经初始化,c只会引用该值,直到我们到达此声明的末尾为止。

( .... )

这意味着里面的任何东西都应该被看作是一个表达式。

function(c)

这意味着这个“表达式”是一个接受参数的函数。此后,这个参数将以名称c来引用,直到函数结束为止。因此,在函数作用域之外声明的任何名称为c的变量都不能直接在这里访问。虽然如果它在全局作用域中,而且全局作用域恰好是窗口对象,但它可以称为window.c

if (c === undefined) { ... }

检查传递给它的参数是否未定义。如果是未定义的,则返回true,从而执行if块中的任何内容。

c = {}

将变量c设置为空对象。因此,如果参数是(传递的或)未定义的,我们在这里自己定义它(并且我们将它定义为一个空对象.)。

function a() { alert(1); }

声明一个名为a调用的函数,这将导致通知数字1。注意,这只是一个函数声明。我们还没给这个函数打电话。

c.a = a

现在为参数c分配了一个名为a的属性,它引用了我们刚才创建的函数a

return c

在对传递的参数进行更改之后,以返回值作为c的最后值,从函数中分离出来。

(fun...}(c))

调用我们刚刚创建的函数,并将c的当前值作为参数传递给它。因为我们将函数作为表达式调用,这个表达式的结果将是函数的返回值。而我们的函数在分配了一个属性后,返回一个对象(我们传递给它)。

由于这个表达式等同于变量c,所以表达式的返回值(即函数的返回值)现在与变量c保持在一起。

如果正确阅读所有这些内容,您就会知道变量c现在将保存一个对象,该对象具有一个属性a,它是一个警告数字1的函数。该对象还保留了它以前可能拥有的属性。

如果我们通过将变量名称描述为描述性来使代码变得可读性,那么我们就可以对代码进行去丑化:

代码语言:javascript
运行
复制
var myObject = (function(someObject) {
    if (someObject === undefined) {
        someObject = {};
    }
    function alertOne () {
        alert(1);
    }
    someObject.alertOne = alertOne;
    return someObject;
}(myObject));

这个节目是系列模块揭示模式的一个插曲,它告诉我们如何以优雅的方式向以前声明的对象添加附加属性,而不会污染全局范围。立即调用函数表达式(IIFE)。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27960682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档