简体   繁体   English

Javascript-自执行功能:如果我可以创建不具有自执行功能的本地范围,为什么要使用它们?

[英]Javascript - self-executing functions : why to use them if I can create local scope with not self-executing functions?

I know there are a lot of posts here and elsewhere about selfexecuting functions but I still have some questions after reading posts. 我知道这里和其他地方都有很多关于自执行功能的文章,但是阅读文章后我仍然有一些疑问。

  1. why would I ever assign a self-executing function to a variable? 为什么我要给变量分配一个自执行函数? If seems that they execute themselves anyways. 如果看起来他们仍然执行自己。

     var myFunc=(function() { console.log('Hello World'); })(); 
  2. I read a lot that the reason to use self-executing functions is to keep variables private. 我读到很多文章,使用自我执行功能的原因是使变量保持私有。 If I have a not self-executing function, everything I define inside that function is gonna be private anyways?! 如果我有一个不能自我执行的功能,那么我在该功能内定义的所有内容都将是私有的?

     (function() { var name="my Name" console.log(name); })(); vs. function() { var name="my Name" console.log(name); }; //its the same 

So I dont quite understand how self-executing functions are to keep local scope (as you can do that using not self-executing functions) so the only reason I see is to use them when you want to execute automatically for example on page load. 因此,我不太了解自我执行功能如何保持本地范围(因为您可以使用非自我执行功能来做到这一点),所以我看到的唯一原因是要在例如页面加载时自动执行时使用它们。

Thanks! 谢谢!

just one more question: 只是一个问题:

var test=(function myFunc(){
      var name="Hello World"
      return {
        test1: function(){
          return name;
        },
        test2:function(){
          return name+"1"
        }
      }
    })()

    test.test1()

vs

    var test=function myFunc(){
      var name="Hello World"
      return {
        test1: function(){
          return name;
        },
        test2:function(){
          return name+"1"
        }
      }
    }

    test.test1()

--> what exactly happens here that because of IIFE I can actually execute test.test1() and not with a regular function? ->由于IIFE,我实际上可以执行test.test1()而不用常规函数执行什么操作呢?

  1. If that IIFE doesn't return anything, then there's indeed absolutely no use to assign it to anything. 如果该IIFE不返回任何东西,那么将它分配给任何东西确实绝对没有用。 Though there may of course be examples of IIFEs returning something you want to use later; 尽管当然可能有IIFE返回一些您以后想要使用的东西的例子; in that case the IIFE is a private scope to set up some object for example: 在这种情况下,IIFE是设置某些对象的私有范围,例如:

     var foo = (function () { var bar = 'something'; // here be dragons return baz; })(); 

    This gives you a private scope to assemble baz without unnecessarily leaking temporary variables into the global scope. 这为您提供了一个私有范围来组装baz而不必将临时变量泄漏到全局范围内。

  2. There's no difference in those examples, except that the second one doesn't execute and therefore never does anything. 这些示例没有区别,只是第二个示例不执行,因此从不执行任何操作。 Scoping and the purpose for the scoping are unchanged. 作用域和作用域的目的不变。

You usually wrap your functions in a anonymous function when you want to keep your scope contained. 当您想保留范围时,通常将函数包装在匿名函数中。 This is also part of the module pattern which is still pretty popular: 这也是仍然很流行的模块模式的一部分:

https://toddmotto.com/mastering-the-module-pattern/ https://toddmotto.com/mastering-the-module-pattern/

Then you can assign the outcome of that IIFE to a variable so your scope can only be accessed by calling that variable. 然后,您可以将IIFE的结果分配给变量,以便只能通过调用该变量来访问范围。

myScope.myLocallyScopedProperty or myScope[myLocallyScopedProperty]

Your other function needs to be called manually and it also accessible from anywhere. 您的其他函数需要手动调用,也可以从任何地方访问。

I suggest reading the article by Todd Moto it explains a lot. 我建议阅读Todd Moto撰写的文章,它对此有很多解释。

First, briefly, these are not self-executing functions. 首先,简要地讲,这些不是自执行功能。 (That would be a recursive function.) These are inline-invoked function expressions (IIFEs). (这将是一个递归函数。)这些是内联调用的函数表达式(IIFE)。 The function doesn't call itself, the expression calls the function. 函数不会自行调用,表达式会调用该函数。

why would I ever assign a self-executing function to a variable? 为什么我要给变量分配一个自执行函数?

That's not what that code does. 那不是该代码的作用。 It assigns the result of calling the IIFE to the variable. 它将调用IIFE的结果分配给该变量。 You'd use it when you want that result, for instance: 您可以在需要该结果时使用它,例如:

 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 doesn't receive the IIFE, it receives what that IIFE returns — in this case, an object with a function on it. x不接收IIFE,而是接收IIFE 返回的内容 -在这种情况下,该对象具有函数。

I read a lot that the reason to use self-executing functions is to keep variables private. 我读到很多文章,使用自我执行功能的原因是使变量保持私有。 If I have a not self-executing function, everything I define inside that function is gonna be private anyways?! 如果我有一个不能自我执行的功能,那么我在该功能内定义的所有内容都将是私有的?

Yes, that's true. 是的,这是真的。 You use an IIFE when you only need to do what's inside the IIFE once . 当您只需要执行一次 IIFE内部的操作时, 就可以使用IIFE。 Otherwise, absolutely, you define the function, give it a name, and then reuse it wherever you need it. 否则,绝对可以定义函数,为其命名,然后在需要的地方重复使用它。 The variables inside the function are indeed private to it (unless exposed in some way), and are specific to each call to the function. 函数内部的变量确实是私有的(除非以某种方式公开),并且特定于函数的每次调用。

In the form of IIFE (or immediately invoked function expressions), they can then be used to create plugins or used as namespaces and attached to window / jquery / or other global level object for use later. 然后,可以IIFE(或立即调用的函数表达式)的形式将它们用于创建插件用作名称空间 ,并附加到window / jquery /或其他全局级别的对象中,以备后用。


When you name a function like assigning anonymous function to a variable, you can use it later by calling the variable with parentheses, in your example, defined myFunc with 当给函数命名(例如为变量分配匿名函数)时,可以稍后在括号中调用该变量,例如在示例中定义myFunc

var myFunc=(function() {
 console.log('Hello World');
}); 

Use it later in code as myFunc() ; 以后在代码中用作myFunc()

In your example, you are storing the output of function directly in variable, by calling it immediately, and there is no output to be stored. 在您的示例中,您将通过立即调用直接将函数的输出存储在变量中,并且没有要存储的输出。

So, if you later write console.log(myFunc); 因此,如果您稍后编写console.log(myFunc); , there is undefined as output. undefined为输出。


Better IIFE example from your code samples is the one mentioned below. 下面是您的代码示例中更好的IIFE示例。

(function() {
 var name="my Name"
 console.log(name);
})();

It executes, does a console.log and that's it. 它执行,执行console.log就是这样。 Adds nothing to namespace or the global object in your case. 在您的情况下,不向名称空间或全局对象添加任何内容。


The last of your examples defines a function, does not execute it then, and since it does not have a named variable assigned, or a name, it gives syntax error and cannot be used later in code. 您的最后一个示例定义了一个函数,然后不执行该函数,并且由于该函数未分配命名变量或名称,因此它会产生语法错误,以后无法在代码中使用。 So, below example is useless. 所以,下面的例子是没有用的。

function() {
 var name="my Name"
 console.log(name);
 };

You have added two more examples with var test = function myFunc . 您还使用var test = function myFunc添加了两个示例。 First one will work fine with test.test1() . 第一个可以与test.test1()正常工作。 For the second one, you need to evaluate test as a function first and then call its function, like test().test1() . 对于第二个,您需要首先将test评估为一个函数,然后调用其函数,例如test().test1()

1: To assign an IIFE to a local Variable makes sense for something like that: 1:将IIFE分配给局部变量对于类似这样的事情是有意义的:

var getID = (function () {
  var id = 0;
  return function () { return id++; };
})();

This way you can get new IDs without running the risk to reset the internal counter from anywhere else in the code, except by redeclaring the variable. 这样,您可以获取新的ID,而不必冒着从代码中其他任何地方复位内部计数器的风险,除非重新声明变量。

2: Basically you create Scope by creating a function. 2:基本上,您通过创建函数来创建范围。 But if you do not execute it, well, it doesn't do anything. 但是,如果您不执行它,那么它什么也不会做。 So if you have that: 因此,如果您有:

function () { return 'foo' };

How do you want to call it if it is not assigned to a variable or does not have a name? 如果未分配变量或没有名称,如何调用它? By itself it wont do anything, since it is not called. 它本身不会做任何事情,因为它没有被调用。 Something like that is dead code and can safely be removed. 这样的东西就是无效代码,可以安全地删除。

your first thing has no sense whatsoever: 您的第一件事毫无意义:

var myFunc = =(function() {
       console.log('Hello World');
    })();

myFunc is not a function and it is undefined . myFunc不是函数,并且undefined

The sense, as I see it, for a self executing function is to package some code that has to be executed right away. 正如我所看到的,自执行功能的意义是打包一些必须立即执行的代码。

var p1=1, p2=2, obj = {
   prop: (function(x,y){ return x+y;})(p1, p2)
}

OR avoiding overwriting already defined functions/objects in the case your script will be inserted in a already existing application and also creating a kind of private methods, if you like: 或者 ,如果您希望将脚本插入到已经存在的应用程序中,并且避免创建一种私有方法,则避免覆盖已经定义的函数/对象:

 function aFunction() { console.log('a code'); } (function(w) { function aFunction() { console.log('b code'); } w.run = function() { aFunction(); }; })(window) aFunction(); run(); 

You use self executing functions to expose only what you need out of a scope. 您使用自我执行功能仅将您需要的内容暴露在范围之外。 I think I have a somewhat clear example: 我想我有一个明确的例子:

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
  }
}());

So, the function gets executed immediately, and what happens is I have an object that is defined by what I returned from the function. 因此,该函数将立即执行,然后发生的事情是我有一个由我从函数返回的值定义的对象。

Another example I could give you is to retain variables of the current scope inside a closure, but you wouldn't really use it that much, since we now have let . 我可以给您的另一个示例是将当前作用域的变量保留在闭包中,但是您实际上并不会使用太多,因为现在有了let A practical example: 一个实际的例子:

<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>

When you click on a span, the value will be replaced with the value... "new: 4"! 当您单击跨度时,该值将被替换为值...“ new:4”! That's because when you finished executing, that's the value that toPrint has. 这是因为完成执行后,这就是toPrint的价值。 The function assigned to the click event retrieves that toPrint, and at the time it retrieves it, it is "new: 4". 分配给click事件的函数检索该toPrint,而在检索该函数时,它是“ new:4”。 We solve this with closures: 我们用闭包来解决这个问题:

<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>

By using a self executing function, we save the current value of toPrint in the currPrint variable inside a local scope. 通过使用自执行函数,我们将toPrint的当前值保存在本地作用域内的currPrint变量中。 When we later click on a span, the function assigned to the click even will use the variable currPrint, which contains the value that toPrint had at the time the function was assigned, not the value that toPrint has at finished execution. 当我们稍后单击跨度时,分配给click的函数将使用变量currPrint,该变量包含toPrint在分配函数时所具有的值,而不是toPrint在完成执行时所具有的值。

Note that this is solved also by using let instead of var, but still, it's an example of self-executing functions :) 请注意,这也可以通过使用let而不是var来解决,但这仍然是一个自执行函数的示例:)

I guess you miss something here. 我想你在这里想念什么。 Just to make basic things clear - if you assign a self executed function to a variable the actual return value of the function when executed at this time is assigned to the variable and not the function itself. 只是为了使基本情况清楚-如果将自执行函数分配给变量,则此时执行时函数的实际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'

So why is this pattern around? 那么为什么会出现这种模式呢?

IIFEs are very useful to IIFE对

  • limit the scope if you declare 如果声明则限制范围

     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 

    so this would be mouch better 所以这会更好

     (function() { var test = 'test'; })(); 
  • another very good thigs with IIFs is that you can achieve a design with "privates" IIF的另一个很好的特点是您可以使用“私有”来实现设计

     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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM