我模仿了一个库,并能够编写以下代码。此代码创建了分配给'c'函数的'a'对象。因此,要调用'a',我必须编写c.a()。
此外,我还向这个'c'对象添加了更多的函数。我想了解这段代码中发生了什么。它看起来不像普通的面向对象编程。这种类型的javascript编程叫什么?
var c = (function(c) {
if (c === undefined) {
c = {};
}
function a() {
alert(1);
}
c.a = a;
return c;
}(c));发布于 2015-01-15 09:53:27
这是一个模块模式。你会看到这个模式的许多变体,所以了解真正发生的事情是很重要的,你不能只是模仿一个。
这段代码的目的是完成一个对象c (通常是全局库)。您可能在应用程序中有许多类似的代码,所有构建c的代码片段,可能每个都在自己的文件中。
如果作为参数传递给函数的库对象c还不存在( c === undefined ),则创建它。这使得不依赖于执行顺序或预执行文件成为可能。
赋值的右边部分是生平 (立即调用函数表达式),即立即调用的函数。这种结构的优点是它创建了一个变量(例如a函数)可以在不污染外部(全局)作用域的情况下声明的作用域。在这里,问题是没有意义的,因为a是外部化的,但是一个模块通常依赖于几个内部(私有)函数和变量。
一个可能需要解释的细节:所有这些文件看起来都定义了一个新变量c,但是这里没有问题,即使这些文件是连接的:如果一个var语句已经存在,它就不会定义一个新变量(在这里,甚至在声明点之前,就为整个作用域定义了一个变量)。
另一种写这个的方法是
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变量发布于 2015-01-15 09:56:27
下面是相同的代码,并添加了注释,说明每行都做了什么,以及传递时会发生什么。
//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.发布于 2015-01-15 21:39:31
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的函数。该对象还保留了它以前可能拥有的属性。
如果我们通过将变量名称描述为描述性来使代码变得可读性,那么我们就可以对代码进行去丑化:
var myObject = (function(someObject) {
if (someObject === undefined) {
someObject = {};
}
function alertOne () {
alert(1);
}
someObject.alertOne = alertOne;
return someObject;
}(myObject));这个节目是系列模块揭示模式的一个插曲,它告诉我们如何以优雅的方式向以前声明的对象添加附加属性,而不会污染全局范围。立即调用函数表达式(IIFE)。
https://stackoverflow.com/questions/27960682
复制相似问题