>웹 프론트엔드 >JS 튜토리얼 >js에서 (function(){xxx})() 사용에 대한 자세한 설명

js에서 (function(){xxx})() 사용에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-06-04 17:35:483177검색

이번에는 js의 (function(){xxx})() 사용에 대한 자세한 설명을 가져왔는데, js의 (function(){xxx})() 사용 시 주의사항은 무엇이며, 다음은 실무적인 내용입니다. 사례를 살펴보겠습니다. 살펴보겠습니다.

(function(){xxx})(); js

self-executinganonymous function:

  • 에서 분석 작성: (function() { /* code */ } ) ();

  • 설명: 함수 (function(){})를 둘러싸는 첫 번째 대괄호 쌍은 이름이 지정되지 않은 함수를 스크립트에 반환한 다음, 빈 대괄호 쌍은 반환된 이름이 없는 함수를 즉시 실행합니다. 대괄호는 익명의 함수 매개변수입니다.

  • 함수: 이 특수 함수 패키지에 모든 코드를 작성하는 한 이를 사용하여 네임스페이스를 만들 수 있습니다. 허용하지 않는 한 외부에서 액세스할 수 없습니다. 변수이므로 함수 또는 변수가 전역이 됩니다.) 각 JavaScript 라이브러리의 코드는 기본적으로 이런 방식으로 구성됩니다.

요약하자면, 실행 함수의 주요 기능은 익명 및 자동 실행입니다. 코드는 해석될 때 이미 실행 중입니다.

다른 쓰기 방법

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function () { /* code */ } ()); <br>!function () { /* code */ } ();<br>~function () { /* code */ } ();<br>-function () { /* code */ } ();<br>+function () { /* code */ } ();</span>

함수와 느낌표

요즘 시간이 좀 있어서 마음을 차분히 정리하고 다양한 코드를 볼 수 있는 함수와 느낌표가 자주 등장하는 게 생각나네요. 2달 전에 내가 한 일. 마침내 항저우에서 열린 팀 회의에 참석했을 때 @西子剑影님이 같은 질문을 하셨습니다. 기능 앞에 느낌표(!)를 추가하면 어떻게 될까요? 예를 들어 다음 코드는

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>!function(){alert('iifksp')}()        // true</span>

콘솔에서 실행한 후 얻은 값이 true입니다. 이 익명 함수는 값을 반환하지 않고 기본 반환 값이 정의되지 않기 때문에 이것이 true인 이유를 이해하기 쉽습니다. 부정 결과는 매우 자연스럽습니다. 따라서 문제는 결과 값에 관한 것이 아니라 왜 부정 연산을 통해 익명 함수의 자체 조정을 합법적으로 만들 수 있습니까?

익명 함수를 호출하기 위해 괄호를 추가하는 것이 더 익숙할 수도 있습니다.

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')})()        // true</span>

또는

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')}())        // true</span>

위 괄호의 위치는 다르지만 효과는 완전히 동일합니다.

그럼 많은 분들이 이 느낌표 방식을 애용하게 만드는 장점은 무엇일까요? 문자 하나만 저장하는 것이라면 너무 불필요합니다. 100K 라이브러리라도 많은 공간을 절약할 수는 없습니다. 공간이 아니기 때문에 시간적 고려가 있을 수 있다는 의미이며, 성능에 대해서는 기사 마지막 부분에 언급되어 있습니다.

핵심 질문으로 돌아가서, 왜 이것이 가능할까요? 더욱 중요한 질문은 이것이 왜 필요한가입니다.

사실 괄호든 느낌표든 전체 문장이 합법적으로 할 수 있는 일은 딱 하나, 함수 선언문을 표현식으로 바꾸는 것뿐입니다.

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>function a(){alert('iifksp')}        // undefined</span>

这是一个函数声明,如果在这么一个声明后直接加上括号调用,解析器自然不会理解而报错:

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>function a(){alert('iifksp')}()        // SyntaxError: unexpected_token</span>

因为这样的代码混淆了函数声明和函数调用,以这种方式声明的函数 a,就应该以 a(); 的方式调用。

但是括号则不同,它将一个函数声明转化成了一个表达式,解析器不再以函数声明的方式处理函数a,而是作为一个函数表达式处理,也因此只有在程序执行到函数a时它才能被访问。

所以,任何消除函数声明和函数表达式间歧义的方法,都可以被解析器正确识别。比如:

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>var i = function(){return 10}();        // undefined  1 && function(){return true}();        // true  1, function(){alert('iifksp')}();        // undefined</span>

赋值,逻辑,甚至是逗号,各种操作符都可以告诉解析器,这个不是函数声明,它是个函数表达式。并且,对函数一元运算可以算的上是消除歧义最快的方式,感叹号只是其中之一,如果不在乎返回值,这些一元运算都是有效的:

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>!function(){alert('iifksp')}()        // true+function(){alert('iifksp')}()        // NaN-function(){alert('iifksp')}()        // NaN~function(){alert('iifksp')}()        // -1</span>

甚至下面这些关键字,都能很好的工作:

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>void function(){alert('iifksp')}()        // undefined  new function(){alert('iifksp')}()        // Object  delete function(){alert('iifksp')}()        // true</span>

最后,括号做的事情也是一样的,消除歧义才是它真正的工作,而不是把函数作为一个整体,所以无论括号括在声明上还是把整个函数都括在里面,都是合法的:

<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')})()        // undefined(function(){alert('iifksp')}())        // undefined</span>

说了这么多,实则在说的一些都是最为基础的概念——语句,表达式,表达式语句,这些概念如同指针与指针变量一样容易产生混淆。虽然这种混淆对编程无表征影响,但却是一块绊脚石随时可能因为它而头破血流。

最后讨论下性能。我在jsperf上简单建立了一个测试:http://jsperf.com/js-funcion-expression-speed ,可以用不同浏览器访问,运行测试查看结果。我也同时将结果罗列如下表所示(由于我比较穷,测试配置有点丢人不过那也没办法:奔腾双核1.4G,2G内存,win7企业版):

Option Code Ops/sec
Chrome 13 Firefox 6 IE9 사파리 5
! !function(){;}() 3,773,196 10,975,198 572,694 2,810, 197
+ +function(){; }() 21,553,847 12,135,960 572,694 1,812,238
- -함수(){;}() 21,553,847 12,135,960 572,694 1,864,155
~ ~function(){;}() 3,551,136 3,651,652 572,694 1,876,002
(1) (함수(){;})() 3,914,953 12,135,960 572,694 3,025,608
(2) (함수(){;}()) 4,075,201 12,135,960 572,694 3,025,608
void void function(){;}() 4,030,756 12,135,960 572,694 3,025,608
new 새 함수(){;}() 619,606 299,100 407,104 816,903
delete delete 함수(){;}() 4,816,225 12,135,960 572,694 2,693,524
= var i = 함수(){;}() 4,984,774 12,135,960 565,982 2,602,630
&& 1 && 함수(){;}( ) 5,307,200 4,393,486 572,694 2,565,645
|| 0 || 기능(){;}() 5,000,000 4,406,035 572,694 2,490,128
& 1 & function(){;}() 4,918,209 12,135,960 572,694 1,705,551
| 1 | 함수(){;}() 4,859,802 12,135,960 572,694 1,612,372
^ 1 ^ 함수(){;}() 4,654,916 12,135,960 572,694 1,579,778
, 1, 함수(){;}() 4,878,193 12,135,960 572,694 2,281,186

다른 방법으로 생성 된 결과는 동일하지 않으며 차이가 크고 브라우저마다 다르다는 것을 알 수 있습니다.

하지만 여전히 많은 공통점을 찾을 수 있습니다. 새로운 방법은 항상 가장 느립니다. 물론 그렇습니다. 그 외 여러 측면에서 차이는 사실 크지 않지만, 한 가지 확실한 것은 느낌표가 가장 이상적인 선택은 아니라는 것입니다. 반면 전통적인 괄호는 항상 테스트에서 매우 빠르게 수행되며 대부분의 경우 느낌표보다 빠르므로 일반적으로 사용하는 방법에는 문제가 없으며 최적이라고 할 수도 있습니다. 더하기 및 빼기 기호는 Chrome에서 놀라운 성능을 발휘하고 일반적으로 다른 브라우저에서도 빠르며 느낌표보다 더 잘 작동합니다.

물론 이는 단순한 테스트일 뿐이며 문제를 설명할 수는 없습니다. 그러나 일부 결론은 의미가 있습니다. 괄호와 더하기 및 빼기 기호가 최적입니다.

그런데 왜 그렇게 많은 개발자가 느낌표를 좋아할까요? 이는 단지 습관의 문제일 뿐, 그 사이의 장단점은 완전히 무시할 수 있다고 생각합니다. 코딩 스타일에 익숙해지면 이 규칙은 프로그램을 혼란스러운 것에서 읽기 쉬운 것으로 바꿔줄 것입니다. 느낌표에 익숙해지면 괄호보다 가독성이 더 좋다는 점을 인정해야 합니다. 읽을 때 괄호 매칭에 신경쓰지 않아도 되고, 쓸 때 함부로 잊어버릴 필요도 없고——

그렇게 하다가 너무 자랑스러워서 한 글자 더 저장했을 때, 급하게 읽다가 잊어버렸다. 굴러간 C언어 교과서의 당혹감과 황당함... 누구나 가끔 잊어버리고, 다시 집어 들었을 때, 잊어버린 것만이 아니다.

이 기사의 사례를 읽으신 후 방법을 마스터하셨다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!

추천 도서:

JS 프레임워크 라이브러리 사용 사례에 대한 자세한 설명

네이티브 js를 사용하여 별이 빛나는 하늘 효과를 만드는 방법

위 내용은 js에서 (function(){xxx})() 사용에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.