Program Tip

"(function () {…}) ()"과 같은 익명 함수에서 전체 Javascript 파일을 래핑하는 목적은 무엇입니까?

programtip 2020. 10. 3. 11:34
반응형

"(function () {…}) ()"과 같은 익명 함수에서 전체 Javascript 파일을 래핑하는 목적은 무엇입니까?


나는 최근에 많은 Javascript를 읽고 있으며 가져올 .js 파일에서 전체 파일이 다음과 같이 래핑되어 있음을 알았습니다.

(function() {
    ... 
    code
    ...
})();

간단한 생성자 함수 세트가 아닌이 작업을 수행하는 이유는 무엇입니까?


일반적으로 네임 스페이스 (나중 참조)이며 멤버 함수 및 / 또는 변수의 가시성을 제어합니다. 객체 정의처럼 생각하십시오. jQuery 플러그인은 일반적으로 다음과 같이 작성됩니다.

Javascript에서는 함수를 중첩 할 수 있습니다. 따라서 다음은 합법적입니다.

function outerFunction() {
   function innerFunction() {
      // code
   }
}

outerFunction()이제을 호출 할 수 있지만의 가시성은 innerFunction()의 범위로 제한 outerFunction()됩니다 outerFunction(). 즉, . 기본적으로 Javascript의 변수와 동일한 원칙을 따릅니다.

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()어디서나,하지만 당신은 호출 할 수 없습니다 localFunction1localFunction2.

를 작성할 때 (function() { ... code ... })()하는 것은 함수 리터럴 내부에 코드를 만드는 것입니다 (전체 "객체"가 실제로 함수임을 의미). 그 후 함수를 자체 호출합니다 (최종 ()). 그래서 앞서 언급했듯이 이것의 가장 큰 장점은 private 메서드 / 함수 및 속성을 가질 수 있다는 것입니다.

(function() {
   var private_var;

   function private_function() {
     //code
   }
})()

첫 번째 예제에서 globalFunction ()은 공용 기능에 액세스하기 위해 호출 할 수있는 공용 함수 였지만 위의 예제에서는 어떻게 호출합니까? 여기서 자체 호출 기능은 시작시 코드가 자동으로 실행되도록합니다. initMyStuff ();를 추가 할 수있는 것처럼 모든 .js 파일의 맨 위로 이동하고 전역 범위의 일부로 자동으로 실행됩니다.이 자체 호출 함수는 이름이 지정되지 않은 함수이기 때문에 initMyStuff ()처럼 여러 번 호출 할 수 없지만 자동으로 실행됩니다.

깔끔한 점은 내부를 정의하고 외부 세계에 노출 할 수도 있다는 것입니다 (기본적으로 고유 한 라이브러리 / 플러그인을 만들 수있는 네임 스페이스의 예).

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) 

그래서 여기서하는 것은 하나의 매개 변수 ( jQ, 지역 변수 라고 하며 해당 함수 에만 알려진)를 받는 함수를 정의하는 것입니다 . 그런 다음 함수를 자체 호출하고 매개 변수를 전달합니다 (라고도 jQuery하지만 이것은 외부 세계에서 온 것이며 실제 jQuery 자체에 대한 참조입니다). 이 작업을 시급하게 할 필요는 없지만 몇 가지 장점이 있습니다.

  • 전역 매개 변수를 재정의하고 로컬 범위에서 의미가있는 이름을 지정할 수 있습니다.
  • 스코프 체인을 전역 스코프로 이동하는 대신 로컬 스코프에서 검색하는 것이 더 빠르기 때문에 약간의 성능 이점이 있습니다.
  • 압축 (최소화)에 대한 이점이 있습니다.

앞에서 이러한 함수가 시작시 자동으로 실행되는 방법을 설명했지만 자동으로 실행되는 경우 인수를 전달하는 사람은 누구입니까? 이 기술은 모든 매개 변수가 전역 변수로 정의되어 있다고 가정합니다. 따라서 jQuery가 전역 변수로 정의되지 않은 경우이 예제는 작동하지 않으며 우리 예제는 익명 함수이므로 다른 방법으로 호출 할 수 없습니다. 짐작할 수 있듯이 jquery.js가 초기화하는 동안 수행하는 작업 중 하나는 'jQuery'전역 변수와 jquery.js가 포함 된 후이 코드가 작동 할 수 있도록하는 더 유명한 '$'전역 변수를 정의하는 것입니다.


간단히 말해서

요약

가장 간단한 형태로이 기술은 함수 범위 내에서 코드를 래핑하는 것을 목표로 합니다.

다음과 같은 가능성을 줄이는 데 도움이됩니다.

  • 다른 응용 프로그램 / 라이브러리와 충돌
  • 상위 (글로벌 가능성이 가장 높은) 범위 오염

그것은 하지 않는 문서가 준비되면 감지 - 그것은 어떤 종류의하지 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

위의 예에서 함수에 정의 된 모든 변수 (예 :를 사용하여 선언 됨 var)는 "비공개"이며 함수 범위 내에서만 액세스 할 수 있습니다 (Vivin Paliath가 말한대로). 즉, 이러한 변수는 함수 외부에서 표시 / 접근 할 수 없습니다. 라이브 데모를 참조하십시오 .

Javascript에는 함수 범위가 있습니다. "함수에 정의 된 매개 변수와 변수는 함수 외부에서 볼 수 없으며 함수 내에서 정의 된 변수는 함수 내 모든 곳에서 볼 수 있습니다." ( "자바 스크립트 : 좋은 부분"에서).


자세한 내용은

대체 코드

결국 이전에 게시 된 코드는 다음과 같이 수행 할 수도 있습니다.

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

라이브 데모를 참조하십시오 .


뿌리

반복 1

어느 날 누군가는 "우리가 원하는 것은 즉시 실행하는 것이기 때문에 '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

라이브 데모를 참조하십시오 .

반복 2

다음 단계는 " var myMainFunction =우리가 그것을 사용하지 않으면 ?"라는 생각입니다.

대답은 간단합니다. 다음과 같이 제거해보십시오.

 function(){ console.log('mamamia!'); }();

라이브 데모를 참조하십시오 .

It won't work because "function declarations are not invokable".

The trick is that by removing var myMainFunction = we transformed the function expression into a function declaration. See the links in "Resources" for more details on this.

The next question is "why can't I keep it as a function expression with something other than var myMainFunction =?

The answer is "you can", and there are actually many ways you could do this: adding a +, a !, a -, or maybe wrapping in a pair of parenthesis (as it's now done by convention), and more I believe. As example:

 (function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.

or

 +function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console

or

 -function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console

So once the relevant modification is added to what was once our "Alternative Code", we return to the exact same code as the one used in the "Code Explained" example

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

Read more about Expressions vs Statements:


Demystifying Scopes

One thing one might wonder is "what happens when you do NOT define the variable 'properly' inside the function -- i.e. do a simple assignment instead?"

(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

See live demo.

Basically, if a variable that was not declared in its current scope is assigned a value, then "a look up the scope chain occurs until it finds the variable or hits the global scope (at which point it will create it)".

When in a browser environment (vs a server environment like nodejs) the global scope is defined by the window object. Hence we can do window.myOtherFunction().

My "Good practices" tip on this topic is to always use var when defining anything: whether it's a number, object or function, & even when in the global scope. This makes the code much simpler.

Note:

  • javascript does not have block scope (Update: block scope local variables added in ES6.)
  • javascript has only function scope & global scope (window scope in a browser environment)

Read more about Javascript Scopes:


Resources


Next Steps

Once you get this IIFE concept, it leads to the module pattern, which is commonly done by leveraging this IIFE pattern. Have fun :)


Javascript in a browser only really has a couple of effective scopes: function scope and global scope.

If a variable isn't in function scope, it's in global scope. And global variables are generally bad, so this is a construct to keep a library's variables to itself.


That's called a closure. It basically seals the code inside the function so that other libraries don't interfere with it. It's similar to creating a namespace in compiled languages.

Example. Suppose I write:

(function() {

    var x = 2;

    // do stuff with x

})();

Now other libraries cannot access the variable x I created to use in my library.


You can use function closures as data in larger expressions as well, as in this method of determining browser support for some of the html5 objects.

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

In addition to keeping the variables local, one very handy use is when writing a library using a global variable, you can give it a shorter variable name to use within the library. It's often used in writing jQuery plugins, since jQuery allows you to disable the $ variable pointing to jQuery, using jQuery.noConflict(). In case it is disabled, your code can still use $ and not break if you just do:

(function($) { ...code...})(jQuery);

  1. To avoid clash with other methods/libraries in the same window,
  2. Avoid Global scope, make it local scope,
  3. To make debugging faster (local scope),
  4. JavaScript has function scope only, so it will help in compilation of codes as well.

We should also use 'use strict' in the scope function to make sure that the code should be executed in "strict mode". Sample code shown below

(function() {
    'use strict';

    //Your code from here
})();

참고URL : https://stackoverflow.com/questions/2421911/what-is-the-purpose-of-wrapping-whole-javascript-files-in-anonymous-functions-li

반응형