And*_*Kou 572 javascript scope coding-style iife
我最近一直在阅读很多Javascript,并且我注意到要导入的.js文件中的整个文件包含如下所示.
(function() {
...
code
...
})();
Run Code Online (Sandbox Code Playgroud)
这样做的原因是什么,而不是一组简单的构造函数?
Viv*_*ath 777
它通常用于命名空间(见后面)并控制成员函数和/或变量的可见性.把它想象成一个对象定义.jQuery插件通常都是这样编写的.
在Javascript中,您可以嵌套函数.所以,以下是合法的:
function outerFunction() {
function innerFunction() {
// code
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以打电话了outerFunction(),但是它的可见性innerFunction()仅限于它的范围outerFunction(),这意味着它是私有的outerFunction().它基本上遵循与Javascript中的变量相同的原则:
var globalVariable;
function someFunction() {
var localVariable;
}
Run Code Online (Sandbox Code Playgroud)
与此相对应:
function globalFunction() {
var localFunction1 = function() {
//I'm anonymous! But localFunction1 is a reference to me!
};
function localFunction2() {
//I'm named!
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的场景中,你可以globalFunction()从任何地方打电话,但你不能打电话localFunction1或localFunction2.
你在写作时所做的(function() { ... code ... })()是,你是在函数文字中创建代码(意味着整个"对象"实际上是一个函数).在那之后,你是自我调用函数(最后的()).所以我之前提到的主要优点是你可以拥有私有方法/函数和属性:
(function() {
var private_var;
function private_function() {
//code
}
})()
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,globalFunction()是可以调用以访问公共功能的公共函数,但在上面的示例中,您如何调用它?这里的自调用函数使代码在启动时自动运行.就像你可以添加initMyStuff(); 在任何.js文件的顶部,它将自动作为全局范围的一部分运行,这个自调用函数也将自动运行,虽然因为它是一个未命名的函数,所以它不能像initMyStuff()那样被多次调用.
整洁的事情是你也可以在里面定义东西并将它暴露给外面的世界(这是一个命名空间的例子,所以你基本上可以创建自己的库/插件):
var myPlugin = (function() {
var private_var;
function private_function() {
}
return {
public_function1: function() {
},
public_function2: function() {
}
}
})()
Run Code Online (Sandbox Code Playgroud)
现在你可以打电话myPlugin.public_function1(),但你无法访问private_function()!非常类似于类定义.为了更好地理解这一点,我推荐以下链接进行进一步阅读:
编辑
我忘了提.在那个决赛中(),你可以传递你想要的任何东西.例如,当你创建jQuery插件时,你传入jQuery或者$像这样:
(function(jQ) { ... code ... })(jQuery)
Run Code Online (Sandbox Code Playgroud)
所以你在这里做的是定义一个接受一个参数的函数(称为jQ局部变量,只有该函数知道).然后你自我调用函数并传入一个参数(也称为jQuery,但这个来自外部世界,并且是对实际jQuery本身的引用).没有迫切需要这样做,但有一些优点:
之前我描述了这些函数在启动时是如何自动运行的,但是如果它们自动运行谁传入参数?该技术假设所有参数都定义为全局变量.因此,如果jQuery未被定义为全局变量,则此示例将无法工作,并且由于我们的示例是匿名函数,因此无法以任何其他方式调用.正如您可能猜到的,jquery.js在初始化过程中所做的一件事就是定义一个'jQuery'全局变量,以及它更着名的'$'全局变量,它允许此代码在包含jquery.js后工作.
Adr*_* Be 78
在其最简单的形式中,此技术旨在将代码包装在函数范围内.
它有助于降低以下几率:
这不,当文档准备好检测-这是不是某种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
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,函数中定义的任何变量(即声明的使用var)将是"私有的",并且只能在函数范围内访问(如Vivin Paliath所说).换句话说,这些变量在函数外部是不可见/可达的.查看现场演示.
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
Run Code Online (Sandbox Code Playgroud)
有一天,有人可能认为"必须有办法避免命名'myMainFunction',因为我们想要的就是立即执行它."
如果你回到基础,你会发现:
expression:评估价值的东西.即3+11/xstatement:代码行做某事但它没有评估为值.即if(){}类似地,函数表达式计算为值.一个结果(我假设?)是可以立即调用它们:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
Run Code Online (Sandbox Code Playgroud)
所以我们更复杂的例子变成:
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
Run Code Online (Sandbox Code Playgroud)
下一步是"为什么var myMainFunction =我们甚至不使用它?" 的想法.
答案很简单:尝试删除它,如下所示:
function(){ console.log('mamamia!'); }();
Run Code Online (Sandbox Code Playgroud)
它不起作用,因为"函数声明不可调用".
诀窍是通过删除var myMainFunction =我们将函数表达式转换为函数声明.有关详细信息,请参阅"资源"中的链接.
接下来的问题是"为什么我不能将它作为一个函数表达式而不是其他东西var myMainFunction =?
答案是"你可以",并且实际上有很多方法可以做到这一点:在一对括号中添加a +,a !,a -或者包装(因为它现在通过惯例完成),我更相信.例如:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
Run Code Online (Sandbox Code Playgroud)
要么
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
Run Code Online (Sandbox Code Playgroud)
要么
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
Run Code Online (Sandbox Code Playgroud)
因此,一旦将相关修改添加到曾经的"替代代码"中,我们将返回与"代码说明"示例中使用的代码完全相同的代码
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
Run Code Online (Sandbox Code Playgroud)
了解更多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
Run Code Online (Sandbox Code Playgroud)
基本上,如果未在当前作用域中声明的变量被赋值,则"查找作用域链直到找到变量或命中全局作用域(此时它将创建它)".
在浏览器环境中(与nodejs之类的服务器环境相比),全局范围由window对象定义.因此我们可以做到window.myOtherFunction().
我在这个主题上的"好习惯"提示是在定义任何东西时始终使用var:它是数字,对象还是函数,甚至是在全局范围内.这使代码更简单.
注意:
block scope(更新:在添加区块范围的局部变量ES6).function scope&global scope(window浏览器环境中的范围)了解更多Javascript Scopes:
一旦你得到这个IIFE概念,它就会导致这种情况module pattern,这通常是通过利用这种IIFE模式来实现的.玩得开心 :)
Gar*_*eth 26
浏览器中的Javascript只有几个有效的范围:功能范围和全局范围.
如果变量不在函数范围内,则它在全局范围内.全局变量通常都很糟糕,因此这是一个将库的变量保存到自身的构造.
Joe*_*oel 19
那被称为封闭.它基本上密封了函数内部的代码,以便其他库不会干扰它.它类似于在编译语言中创建命名空间.
例.假设我写道:
(function() {
var x = 2;
// do stuff with x
})();
Run Code Online (Sandbox Code Playgroud)
现在其他库无法访问x我创建的变量以在我的库中使用.
您也可以将函数闭包用作较大表达式中的数据,就像在确定浏览器对某些html5对象的支持的方法中一样.
navigator.html5={
canvas: (function(){
var dc= document.createElement('canvas');
if(!dc.getContext) return 0;
var c= dc.getContext('2d');
return typeof c.fillText== 'function'? 2: 1;
})(),
localStorage: (function(){
return !!window.localStorage;
})(),
webworkers: (function(){
return !!window.Worker;
})(),
offline: (function(){
return !!window.applicationCache;
})()
}
Run Code Online (Sandbox Code Playgroud)
小智 7
除了将变量保持为局部之外,一个非常方便的用法是在使用全局变量编写库时,可以为其提供一个较短的变量名,以便在库中使用.它经常用于编写jQuery插件,因为jQuery允许你使用jQuery.noConflict()禁用指向jQuery的$变量.如果它被禁用,你的代码仍然可以使用$而不是中断,如果你只是这样做:
(function($) { ...code...})(jQuery);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
104523 次 |
| 最近记录: |