将整个Javascript文件包装在匿名函数中的目的是什么,例如“(function(){ ... })()"?总之更多详情资源后续步骤
我最近一直在阅读很多Javascript,我注意到整个文件被包装在要导入.js文件中。
(function() {
...
code
...
})();
这样做的原因是什么,而不是一组简单的构造函数?
我最近一直在阅读很多Javascript,我注意到整个文件被包装在要导入.js文件中。
(function() {
...
code
...
})();
这样做的原因是什么,而不是一组简单的构造函数?
它通常是命名空间(见后面)并控制成员函数和/或变量的可见性。把它想象成一个对象定义。它的技术名称是立即调用的函数表达式 (IIFE)。jQuery插件通常是这样写的。
在Javascript中,你可以嵌套函数。因此,以下内容是合法的:
function outerFunction() {
function innerFunction() {
// code
}
}
现在你可以调用 ,但 的可见性被限制在 的范围,这意味着它是私有的。它基本上遵循与Javascript中的变量相同的原理:outerFunction()
innerFunction()
outerFunction()
outerFunction()
var globalVariable;
function someFunction() {
var localVariable;
}
相应:
function globalFunction() {
var localFunction1 = function() {
//I'm anonymous! But localFunction1 is a reference to me!
};
function localFunction2() {
//I'm named!
}
}
在上面的场景中,您可以从任何地方调用,但不能调用 或 。globalFunction()
localFunction1
localFunction2
当你写的时候,你正在做的是你把第一组括号内的代码变成一个函数文字(意味着整个“对象”实际上是一个函数)。之后,您将自行调用刚刚定义的函数(最终函数)。因此,正如我之前提到的,这样做的主要优点是,您可以拥有私有方法/函数和属性:(function() { ... })()
()
(function() {
var private_var;
function private_function() {
//code
}
})();
在第一个示例中,您将按名称显式调用以运行它。也就是说,您只需运行它即可。但是在上面的例子中,你不只是定义了一个函数;您正在一次性定义和调用它。这意味着当加载 JavaScript 文件时,它会立即执行。当然,你可以做到:globalFunction
globalFunction()
function globalFunction() {
// code
}
globalFunction();
除了一个显著的区别之外,行为基本上是相同的:当您使用IIFE时,您可以避免污染全局范围(因此,这也意味着您无法多次调用该函数,因为它没有名称,但由于此函数仅在一旦真正不是问题时才执行)。
IIFE的巧妙之处在于,您还可以在内部定义内容,并且仅向外部世界公开您想要的部分(命名空间的示例,因此您基本上可以创建自己的库/插件):
var myPlugin = (function() {
var private_var;
function private_function() {
}
return {
public_function1: function() {
},
public_function2: function() {
}
}
})()
现在你可以打电话,但你无法访问!所以非常类似于类定义。为了更好地理解这一点,我建议使用以下链接进行进一步阅读:myPlugin.public_function1()
private_function()
编辑
我忘了提。在最后,你可以通过任何你想要的东西。例如,当您创建jQuery插件时,您可以传入或类似内容:()
jQuery
$
(function(jQ) { ... code ... })(jQuery)
因此,您在这里要做的是定义一个函数,该函数接受一个参数(称为,一个局部变量,并且只有该函数知道)。然后,您将自调用该函数并传入一个参数(也称为 ,但这个参数来自外部世界,是对实际 jQuery 本身的引用)。没有迫切需要这样做,但有一些优点:jQ
jQuery
前面我描述了这些函数如何在启动时自动运行,但是如果它们自动运行,谁在传入参数?此技术假定所需的所有参数都已定义为全局变量。因此,如果jQuery尚未被定义为全局变量,则此示例将不起作用。正如您可能猜到的那样,jquery.js在初始化期间所做的一件事是定义一个“jQuery”全局变量,以及其更着名的“$”全局变量,这允许此代码在包含jQuery之后工作。
在最简单的形式中,此技术旨在将代码包装在函数范围内。
它有助于减少以下几率:
它不检测文档何时准备就绪 - 它不是某种或document.onload
window.onload
它通常称为 或 。Immediately Invoked Function Expression (IIFE)
Self Executing Anonymous Function
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
在上面的示例中,函数中定义的任何变量(即使用 声明)都将是“私有的”,并且只能在函数范围内访问(如Vivin Paliath所说)。换句话说,这些变量在函数外部不可见/不可访问。观看现场演示。var
Javascript具有函数范围。“函数中定义的参数和变量在函数外部不可见,并且在函数内任何位置定义的变量在函数内的任何位置都可见。(摘自“Javascript: The Good Parts”)。
最后,之前发布的代码也可以按如下方式完成:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
有一天,有人可能会想“一定有办法避免命名'myMainFunction',因为我们想要的就是立即执行它。
如果您回到基础,您会发现:
expression
:计算值为值的东西。即3+11/x
statement
:代码行执行某些操作,但它的计算结果不是值。即if(){}
同样,函数表达式的计算结果为值。一个结果(我假设?)是它们可以立即被调用:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
因此,我们更复杂的示例变为:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
下一步是思考“如果我们甚至不使用它,为什么还要使用它!?var myMainFunction =
答案很简单:尝试删除它,如下所示:
function(){ console.log('mamamia!'); }();
它不起作用,因为“函数声明不可调用”。
诀窍是,通过删除,我们将函数表达式转换为函数声明。有关此内容的更多详细信息,请参阅“参考资料”中的链接。var myMainFunction =
下一个问题是“为什么我不能把它作为一个函数表达式,而不是其他东西?var myMainFunction =
答案是“你可以”,实际上有很多方法可以做到这一点:添加一个,一个,一个,或者可能用一对括号括起来(就像现在按照惯例所做的那样),我相信更多。例如:+
!
-
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
或
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
或
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
因此,一旦将相关修改添加到曾经是我们的“替代代码”中,我们就会返回到与“代码解释”示例中使用的代码完全相同的代码。
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
阅读更多关于 :Expressions vs Statements
人们可能想知道的一件事是“当你没有在函数中'正确'定义变量时会发生什么 - 即做一个简单的赋值?
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
基本上,如果一个未在其当前作用域中声明的变量被赋值,则“在找到该变量或命中全局作用域(此时它将创建它)之前,将查找作用域链”。
在浏览器环境中(与 nodejs 等服务器环境相比),全局作用域由对象定义。因此,我们可以做到.window
window.myOtherFunction()
关于这个主题,我的“良好实践”技巧是在定义任何东西时始终使用var
:无论是数字,对象还是函数,甚至在全局范围内也是如此。这使得代码更简单。
注意:
block scope
function scope
global scope
window
阅读更多关于 :Javascript Scopes
一旦你得到了这个概念,它就会导致 ,这通常是通过利用这个IIFE模式来完成的。玩得开心:)IIFE
module pattern