请解释以下在javascript函数中编写函数的方法:
(function (){
// some code
})()
Run Code Online (Sandbox Code Playgroud)
我理解这样一个事实:由于尾随大括号"()",函数会立即执行,但是括号中的函数是什么意思呢?
我最近一直在研究很多JavaScript代码,并且我已经看到了使用IIFE的"公共"属性的两种不同方式.
第一个是创建变量并将该变量分配给IIFE内部的属性,如下所示:
var public1;
(function(){
var foo= "Foo", bar= "Bar";
public1= {
getFoo: function(){
return foo;
}
};
}());
Run Code Online (Sandbox Code Playgroud)
我看到的第二种方式是从IIFE返回一个对象,如下所示:
var public2 = (function(){
var foo2= "Foo2", bar2= "Bar2";
return {
getBar: function(){
return bar2;
}
};
}());
Run Code Online (Sandbox Code Playgroud)
这两种方式之间是否存在根本区别,还是只是偏好?我还创建了一个小提琴,以便您可以运行或更新代码:http://jsfiddle.net/bittersweetryan/gnh79/3/
很明显,在EcmaScript中,调用时的函数会创建一个新的执行上下文.函数中定义的所有变量和函数只能在该函数范围内访问.但是当我们使用闭包变量时,可以在该上下文之外访问函数.IIFE是一个立即调用的函数表达式.很简单.
但是为什么IIFE与自我执行的匿名函数不同,对我来说还不完全清楚!?
首先,一个伪代码示例:
;(function(foo){
foo.init = function(baz) { ... }
foo.other = function() { ... }
return foo;
}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)
这样称呼:
FOO.init();
Run Code Online (Sandbox Code Playgroud)
window.FOO = window.FOO || {}?我理解代码的作用...请参阅下面的我的原因.
我这样称呼全球传递:
;(function(foo){
... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)
...但我只是不喜欢称小写" foo",考虑到全局被称为大写FOO......它只是看起来令人困惑.
如果我知道这种技术的技术名称,我可以说:
;(function(technicalname){
... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)
我见过一个最近(很棒)的例子,他们称之为" exports":
;(function(exports){
...
}(window.Lib = …Run Code Online (Sandbox Code Playgroud) 闭包通过引用(而不是值)存储它们的外部变量.但是,在下面的代码中,我想按值存储.任何人都可以告诉我如何使用IIFE吗?
var i = -1;
var f = function () {
return i; // I want to capture i = -1 here!
};
i = 1;
f(); // => 1, but I want -1
Run Code Online (Sandbox Code Playgroud) Airbnd建议我这样做:
!function() {
// ...
}();
Run Code Online (Sandbox Code Playgroud)
因为:
这可确保如果格式错误的模块忘记包含最终分号,则在脚本连接时,生产中不会出现错误.
爆炸让我可以解决语言的语法规则:
// Evaluated in Chromium 34 console.
function(){}(); // => SyntaxError: Unexpected token (
!function(){}(); // => true
Run Code Online (Sandbox Code Playgroud)
当连接其他模块时,爆炸似乎可以解决问题:
!function(){}();function(){}(); // => SyntaxError: Unexpected token (
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true
Run Code Online (Sandbox Code Playgroud)
然而,它似乎并不"安全",因为如果其他人的脚本末尾没有分号:
!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
(function(){}())!function(){}(); // => SyntaxError: Unexpected token !
Run Code Online (Sandbox Code Playgroud)
看起来领先的分号IIFE更好.
;(function() {
// ...
}());
!function(){}();(function(){}()); // => undefined
(function(){}());(function(){}()); // => undefined
!function(){}();;(function(){}()); // => undefined
(function(){}());;(function(){}()); // => undefined …Run Code Online (Sandbox Code Playgroud) 我正在处理一个巨大的JavaScript代码库,我正在尝试重新组织.我不是真正的专家,我刚开始研究良好的JavaScript编码实践.所以,我要做的一件事就是将模块中的所有代码分开.在这个特殊情况下,我正在尝试创建一个可以帮助我优化视频嵌入的模块.我想传递一个id的模块,并从中接收一些HTML代码或图像.
我不是把整个代码都放在这里,但这对于这个例子来说已经足够了:
var videoIframe = (function($) {
'use strict';
var id,
setVideoId = function(videoId) {
id = videoId;
console.log(id);
},
getVideoThumbnail = function(videoId) {
setVideoId(videoId);
},
test = function() {
console.log(id)
},
getVideoEmbedCode = function() {
};
return {
test: test,
getVideoThumbnail: getVideoThumbnail
};
})(jQuery);
Run Code Online (Sandbox Code Playgroud)
在另一个模块中,我将它分配给两个变量:
var video1 = videoIframe;
var video2 = videoIframe;
video1.getVideoThumbnail(123);
video2.getVideoThumbnail(456);
video1.test();
video2.test();
Run Code Online (Sandbox Code Playgroud)
而且,当然,我没有达到我的预期.第二次getVideoThumbnail调用后,它始终打印456.
做一些研究我明白我正在创建一个单例,一个实例,而我只是在该实例中更改值.我想我的模块需要一个构造函数,但我不确定如何与IIFE模式一起创建它.这是正确的方法吗?
我currenlty有以下基本IIFE在JavaScript:
var Test = (function(service){
var me = this;
me.service = service;
var my = {};
my.getData1 = function(){
return me.service.GetData1();
}
my.getData2 = function(){
return me.service.GetData2();
}
return my;
}());
Run Code Online (Sandbox Code Playgroud)
我希望能做的是以下内容:
var myService = new Service(); //code omitted but its a service class that gets data
var myTest = Test(myService);
Run Code Online (Sandbox Code Playgroud)
以上不起作用.该行var myTest = Test(myService);抛出一个错误:
测试不是一个功能
我也知道,在一个IIFE,必须传入值,因为它立即被调用,所以最后一行应该是这样的:
}(service));
我可以使这个代码工作,如果我只是删除Test是持有的全局变量IIFE,而是使其成为具有以下签名的全局函数:
function Test(service) {}
但是,我正在IIFE …
所以我有一个现有的应用程序,它在浏览器中广泛使用 IIFE。我正在尝试在代码中引入一些单元测试,并保持 IIFE 模式以对代码库进行新的更新。除此之外,我什至无法编写一个测试来处理代码。例如,我在代码库中看到了这种类型的逻辑:
var Router = (function (router) {
router.routeUser = function(user) {
console.log("I'm in! --> " + user)
};
return router;
})(Router || {});
Run Code Online (Sandbox Code Playgroud)
然后将 JS 文件包含在标记中的脚本标记中:
<script src="js/RouteUser.js"></script>
Run Code Online (Sandbox Code Playgroud)
并在生产代码中这样调用:
Router.routeUser(myUser)
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,我该如何编写测试routeUser方法的测试?我在摩卡测试中试过这个:
var router = require('../../main/resources/public/js/RouteUser');
suite('Route User Tests', function () {
test('Route The User', function () {
if (!router)
throw new Error("failed!");
else{
router.routeUser("Me")
}
});
});
Run Code Online (Sandbox Code Playgroud)
但我得到一个例外:
TypeError: router.routeUser is not a function
at Context.<anonymous> (src\test\js\RouteUser.test.js:8:20)
Run Code Online (Sandbox Code Playgroud)
然后我尝试返回该方法,它给出了相同的错误:
var Router = (function (router) …Run Code Online (Sandbox Code Playgroud) 以下代码是线程安全的吗?(使用 IIFE 初始化静态局部变量。)
int MyFunc(){
static int Val = ([]()
{
return 1 + 2 + 3 + 4; // Real code is more complex, but thread-safe
})();
return Val;
}
Run Code Online (Sandbox Code Playgroud) iife ×10
javascript ×9
c++ ×1
closures ×1
function ×1
lambda ×1
mocha.js ×1
syntax ×1
unit-testing ×1