我知道这里和其他地方有很多关于自我执行功能的帖子,但在阅读帖子后我还有一些问题。
为什么我会为变量分配一个自执行函数?如果看起来他们仍然执行自己。
(a = b or a = c) and d = e
我读了很多,使用自执行函数的原因是保持变量私有。如果我有一个不自动执行的功能,我在该功能中定义的所有东西都会是私有的吗?!
var myFunc=(function() {
console.log('Hello World');
})();
所以我不太明白自动执行函数如何保持局部范围(因为你可以使用非自动执行的函数),所以我看到的唯一原因就是当你想自动执行时使用它们,例如on页面加载。
谢谢!
还有一个问题:
(function() {
var name="my Name"
console.log(name);
})();
vs.
function() {
var name="my Name"
console.log(name);
};
//its the same
- >这里到底发生了什么,因为IIFE我实际上可以执行test.test1()而不是常规函数?
答案 0 :(得分:1)
如果那个IIFE没有返回任何东西,那么将它分配给任何东西确实没用。虽然当然可能会有一些IIFE返回你想要使用的东西的例子;在这种情况下,IIFE是设置某个对象的私有范围,例如:
var foo = (function () {
var bar = 'something';
// here be dragons
return baz;
})();
这为您提供了一个私有范围来汇集baz
,而不会不必要地将临时变量泄漏到全局范围内。
这些例子没有区别,只是第二个没有执行,因此从不做任何事情。范围界定和范围的目的不变。
答案 1 :(得分:1)
当您想要保持范围时,通常将函数包装在匿名函数中。这也是模块模式的一部分,它仍然很受欢迎:
https://toddmotto.com/mastering-the-module-pattern/
然后,您可以将IIFE的结果分配给变量,这样只能通过调用该变量来访问您的范围。
myScope.myLocallyScopedProperty or myScope[myLocallyScopedProperty]
您的其他功能需要手动调用,也可以从任何地方访问。
我建议阅读Todd Moto的文章,它解释了很多。
答案 2 :(得分:1)
首先,简单地说,这些不是自动执行的功能。 (这将是一个递归函数。)这些是内联调用的函数表达式(IIFE)。 函数不调用自身,表达式调用函数。
为什么我要为变量分配一个自执行函数?
这不是代码所做的。它将调用IIFE的结果分配给变量。你想要那个结果时使用它,例如:
var x = (function() {
var n = 0;
return {
increment: function() { return ++n; }
};
})();
console.log(typeof x); // "object"
console.log(x.increment()); // 1
console.log(x.increment()); // 2
x
没有收到IIFE,它会收到IIFE 返回的内容 - 在这种情况下,是一个带有函数的对象。
我读了很多,使用自执行函数的原因是保持变量私有。如果我有一个不自动执行的功能,我在该功能中定义的所有东西都会是私有的吗?!
是的,那是真的。当您只需要在IIFE 内执行时,您就可以使用IIFE。否则,绝对地,您定义函数,为其命名,然后在需要的地方重复使用它。函数内部的变量确实是私有的(除非以某种方式暴露),并且特定于每次调用函数。
答案 3 :(得分:1)
以IIFE(或立即调用的函数表达式)的形式,它们可以是used to create plugins或used as namespaces并附加到window / jquery /或其他全局级别对象以供稍后使用。
当您为一个变量分配匿名函数这样的函数时,您可以稍后通过使用括号调用变量来使用它,在您的示例中,使用
定义myFuncvar myFunc=(function() {
console.log('Hello World');
});
稍后在代码myFunc()
中使用它;
在您的示例中,您将函数的输出直接存储在变量中,通过立即调用它,并且不存储任何输出。
因此,如果您稍后写console.log(myFunc);
,则输出undefined
。
您的代码示例中更好的IIFE示例如下所示。
(function() {
var name="my Name"
console.log(name);
})();
执行,执行console.log,然后执行。在您的情况下,不向名称空间或全局对象添加任何内容。
您的最后一个示例定义了一个函数,然后不执行它,并且由于它没有分配命名变量或名称,因此它会出现语法错误,以后不能在代码中使用。所以,下面的例子是没用的。
function() {
var name="my Name"
console.log(name);
};
您已使用var test
= function myFunc
添加了两个示例。第一个可以与test.test1()
一起使用。对于第二个,您需要首先将test评估为函数,然后调用其函数,如test().test1()
。
答案 4 :(得分:1)
1:将IIFE分配给局部变量对于类似的东西是有意义的:
var getID = (function () {
var id = 0;
return function () { return id++; };
})();
通过这种方式,除了通过重新声明变量之外,您可以获得新ID,而不会冒险从代码中的任何其他位置重置内部计数器。
2:基本上你通过创建一个函数来创建Scope。但如果你不执行它,那么它就什么都不做。所以如果你有:
function () { return 'foo' };
如果未分配给变量或没有名称,您想如何调用它?它本身不会做任何事情,因为它没有被调用。像这样的东西是死代码,可以安全地删除。
答案 5 :(得分:1)
你的第一件事没有任何意义:
var myFunc = =(function() {
console.log('Hello World');
})();
myFunc
不是函数,而是undefined
。
正如我所看到的,自我执行功能的意义是打包一些必须立即执行的代码。
var p1=1, p2=2, obj = {
prop: (function(x,y){ return x+y;})(p1, p2)
}
或强> 如果你喜欢,你的脚本将插入已经存在的应用程序并创建一种私有方法,避免覆盖已经定义的函数/对象:
function aFunction() {
console.log('a code');
}
(function(w) {
function aFunction() {
console.log('b code');
}
w.run = function() {
aFunction();
};
})(window)
aFunction();
run();

答案 6 :(得分:1)
使用自执行函数仅显示范围内所需的内容。我想我有一个明显的例子:
let myObject = (function(){
let privateVariable = "I'm private";
function privateMethod() {
//private method
};
function methodToExpose() {
//this method I will expose
}
//what is returned here, is what is public
return {
PublicMethod: methodToExpose
//other public properties
}
}());
因此,该函数立即执行,发生的事情是我有一个由我从函数返回的对象定义的对象。
我可以给你的另一个例子是在闭包内保留当前作用域的变量,但你不会真正使用它,因为我们现在有let
。一个实际的例子:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){ event.target.innerHTML = toPrint; })
}
</script>
单击某个范围时,该值将替换为值“... new:4”! 那是因为当你完成执行时,这就是toPrint的价值。分配给click事件的函数检索toPrint,并在检索它时,它是“new:4”。我们用闭包来解决这个问题:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){
var currPrint = toPrint;
return function(event){ event.target.innerHTML = currPrint ; };
}())
}
</script>
通过使用自执行功能,我们将toPrint的当前值保存在本地范围内的currPrint变量中。当我们稍后点击一个跨度时,分配给click的函数甚至会使用变量currPrint,它包含toPrint在分配函数时所具有的值,而不是toPrint在完成执行时的值。
请注意,这也是通过使用let而不是var来解决的,但它仍然是自执行函数的一个示例:)
答案 7 :(得分:0)
我猜你错过了什么。只是为了使基本的事情清楚 - 如果你将一个自执行的函数赋给变量,那么当执行时函数的实际return value
被赋给变量而不是函数本身。
var myFunc = (function() {
console.log('Hello World');
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === undefined
var myFunc = (function() {
console.log('Hello World');
return 'japp';
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === 'japp'
IIFE对
非常有用限制范围 如果你宣布
var test = 'test'; // var test actually will be assigned as a property of the current context (this)
window.test = 'test'; // so you pollute the global namespace which is not a good practice
所以这将是更好的
(function() {
var test = 'test';
})();
IIF的另一个非常好的方法是你可以用&#34; privates&#34;
来实现设计var myFunc;
(function() {
var i = 0; // i is available for myFunc with private access
myFunc = function() { console.log( ++i ) };
})();
myFunc(); // logs 1
myFunc(); // logs 2