etc./StackOverFlow

var functionName = function() {} 대 함수 functionName() {}

청렴결백한 만능 재주꾼 2021. 9. 22. 13:27
반응형

질문자 :Richard Garside


최근에 다른 사람의 JavaScript 코드를 유지 관리하기 시작했습니다. 버그를 수정하고 기능을 추가하고 코드를 정리하고 일관성을 높이려고 노력하고 있습니다.

이전 개발자는 두 가지 방법으로 함수를 선언했는데, 그 뒤에 이유가 있는지 모르겠습니다.

두 가지 방법은 다음과 같습니다.

 var functionOne = function() { // Some code };
 function functionTwo() { // Some code }

이 두 가지 다른 방법을 사용하는 이유는 무엇이며 각각의 장단점은 무엇입니까? 한 방법으로 할 수 있고 다른 방법으로는 할 수 없는 일이 있습니까?



답변자 : Greg


차이점은 functionOne 은 함수 표현식이므로 해당 행에 도달할 때만 정의되는 반면, functionTwo 는 함수 선언이며 주변 함수 또는 스크립트가 실행되자마자( 호이스팅 으로 인해) 정의된다는 점입니다.

예를 들어, 함수 표현식은 다음과 같습니다.

 // TypeError: functionOne is not a function functionOne(); var functionOne = function() { console.log("Hello!"); };

그리고 함수 선언:

 // Outputs: "Hello!" functionTwo(); function functionTwo() { console.log("Hello!"); }

역사적으로 블록 내에 정의된 함수 선언은 브라우저 간에 일관되지 않게 처리되었습니다. Strict 모드(ES5에 도입됨)는 함수 선언을 둘러싸는 블록으로 범위를 지정하여 이 문제를 해결했습니다.

 'use strict'; { // note this block! function functionThree() { console.log("Hello!"); } } functionThree(); // ReferenceError



답변자 : Eugene Lazutkin


먼저 Greg를 수정하고 싶습니다. function abc(){} 도 범위가 지정됩니다. abc 라는 이름은 이 정의가 발생하는 범위에 정의되어 있습니다. 예시:

 function xyz(){ function abc(){}; // abc is defined here... } // ...but not here

둘째, 두 스타일을 결합하는 것이 가능합니다.

 var xyz = function abc(){};

xyz 는 평소와 같이 정의되며, abc 는 Internet Explorer를 제외한 모든 브라우저에서 정의되지 않습니다. 정의되는 것에 의존하지 마십시오. 그러나 그것은 본문 내부에서 정의될 것입니다:

 var xyz = function abc(){ // xyz is visible here // abc is visible here } // xyz is visible here // abc is undefined here

모든 브라우저에서 함수의 별칭을 지정하려면 다음과 같은 선언을 사용하십시오.

 function abc(){}; var xyz = abc;

이 경우 xyzabc 는 모두 동일한 객체의 별칭입니다.

 console.log(xyz === abc); // prints "true"

결합된 스타일을 사용해야 하는 한 가지 강력한 이유는 함수 개체의 "이름" 속성( Internet Explorer에서 지원하지 않음 )입니다. 기본적으로 다음과 같은 함수를 정의할 때

 function abc(){}; console.log(abc.name); // prints "abc"

이름이 자동으로 할당됩니다. 그러나 다음과 같이 정의할 때

 var abc = function(){}; console.log(abc.name); // prints ""

그 이름은 비어 있습니다 — 우리는 익명의 함수를 만들고 그것을 어떤 변수에 할당했습니다.

결합된 스타일을 사용하는 또 다른 좋은 이유는 짧은 내부 이름을 사용하여 자신을 참조하는 반면 외부 사용자에게는 충돌하지 않는 긴 이름을 제공하는 것입니다.

 // Assume really.long.external.scoped is {} really.long.external.scoped.name = function shortcut(n){ // Let it call itself recursively: shortcut(n - 1); // ... // Let it pass itself as a callback: someFunction(shortcut); // ... }

위의 예에서 우리는 외부 이름으로 동일한 작업을 수행할 수 있지만 너무 다루기 힘들고 더 느릴 것입니다.

(자신을 참조하는 또 다른 방법은 여전히 상대적으로 길고 엄격 모드에서 지원되지 않는 arguments.callee

심층적으로 JavaScript는 두 명령문을 다르게 취급합니다. 이것은 함수 선언입니다:

 function abc(){}

abc 는 현재 범위의 모든 곳에서 정의됩니다.

 // We can call it here abc(); // Works // Yet, it is defined down there. function abc(){} // We can call it again abc(); // Works

return 문을 통해 호이스트되었습니다.

 // We can call it here abc(); // Works return; function abc(){}

다음은 함수 표현식입니다.

 var xyz = function(){};

xyz 는 할당 지점에서 정의됩니다.

 // We can't call it here xyz(); // UNDEFINED!!! // Now it is defined xyz = function(){} // We can call it here xyz(); // works

함수 선언 대 함수 표현식은 Greg가 입증한 차이점이 있는 실제 이유입니다.

재미있는 사실:

 var xyz = function abc(){}; console.log(xyz.name); // Prints "abc"

개인적으로 "함수 표현식" 선언을 선호합니다. 이렇게 하면 가시성을 제어할 수 있기 때문입니다. 내가 다음과 같은 기능을 정의할 때

 var abc = function(){};

함수를 로컬로 정의했다는 것을 알고 있습니다. 내가 다음과 같은 기능을 정의할 때

 abc = function(){};

범위 체인의 어느 곳에서도 abc 정의하지 않았다는 전제하에 전역적으로 정의했다는 것을 알고 있습니다. eval() 내부에서 사용되는 경우에도 탄력적입니다. 정의하는 동안

 function abc(){};

eval() 의 경우 실제로 정의된 위치를 추측할 수 있습니다. 답은 다음과 같습니다. 브라우저에 따라 다릅니다.



답변자 : T.J. Crowder


다음은 함수를 생성하는 표준 형식에 대한 요약입니다. (원래 다른 질문을 위해 작성되었지만 표준 질문으로 옮겨진 후 수정되었습니다.)

자귀:

빠른 목록:

  • 함수 선언

  • "익명" function 표현식 (용어에도 불구하고 때때로 이름이 있는 함수를 생성함)

  • 명명된 function 표현식

  • 접근자 함수 이니셜라이저(ES5+)

  • 화살표 함수 표현식(ES2015+) (익명 함수 표현식과 마찬가지로 명시적 이름을 포함하지 않지만 이름이 있는 함수를 생성할 수 있음)

  • 객체 이니셜라이저의 메서드 선언(ES2015+)

  • class 생성자 및 메서드 선언(ES2015+)

함수 선언

첫 번째 형식은 다음과 같은 함수 선언입니다.

 function x() { console.log('x'); }

함수 선언은 선언입니다 . 그것은 진술이나 표현이 아닙니다. 따라서 ; (그렇게 하는 것은 무해하지만).

함수 선언은 단계별 코드가 실행 되기 전에 실행이 나타나는 컨텍스트에 들어갈 때 처리됩니다. 생성한 함수에는 고유한 이름( x )이 지정되고 해당 이름은 선언이 나타나는 범위에 포함됩니다.

동일한 컨텍스트에서 단계별 코드보다 먼저 처리되기 때문에 다음과 같이 할 수 있습니다.

 x(); // Works even though it's above the declaration function x() { console.log('x'); }

try , if , switch , while 등과 같은 제어 구조 내부에 함수 선언을 넣으면 JavaScript 엔진이 수행해야 하는 작업을 다루지 않았습니다.

 if (someCondition) { function foo() { // <===== HERE THERE } // <===== BE DRAGONS }

그리고 그것들은 단계별 코드가 실행되기 전에 처리되기 때문에 제어 구조에 있을 때 무엇을 해야 하는지 알기가 까다롭습니다.

이 작업은 ES2015까지 지정 되지 않았지만 블록에서 함수 선언을 지원하기 위해 허용되는 확장이었습니다. 불행히도 (그리고 불가피하게), 다른 엔진은 다른 일을 했습니다.

ES2015 현재 사양에는 수행할 작업이 나와 있습니다. 실제로 다음과 같은 세 가지 작업을 수행합니다.

  1. 웹 브라우저가 아닌 느슨한 모드에 있는 경우 JavaScript 엔진은 한 가지 작업을 수행해야 합니다.
  2. 웹 브라우저에서 느슨한 모드에 있으면 JavaScript 엔진이 다른 작업을 수행해야 합니다.
  3. 엄격 모드(브라우저 여부에 관계없이)에 있는 경우 JavaScript 엔진은 또 다른 작업을 수행해야 합니다.

느슨한 모드에 대한 규칙은 까다롭지만 엄격 모드에서는 블록의 함수 선언이 쉽습니다. 블록에 로컬 이며(ES2015에서도 새로운 기능인 블록 범위 를 가짐) 맨 위로 호이스트됩니다. 블록의. 그래서:

 "use strict"; if (someCondition) { foo(); // Works just fine function foo() { } } console.log(typeof foo); // "undefined" (`foo` is not in scope here // because it's not in the same block)

"익명" function 표현식

두 번째 일반적인 형식은 익명 함수 식이 라고 합니다.

 var y = function () { console.log('y'); };

모든 표현식과 마찬가지로 코드의 단계별 실행에 도달하면 평가됩니다.

ES5에서 이것이 생성하는 함수는 이름이 없습니다(익명). ES2015에서는 가능한 경우 컨텍스트에서 유추하여 함수에 이름을 할당합니다. 위의 예에서 이름은 y 입니다. 함수가 속성 이니셜라이저의 값인 경우 비슷한 작업이 수행됩니다. (이 경우에 대한 자세한 내용과 규칙의 경우, 검색 SetFunctionName사양 - 그것은 여기 저기 나타납니다.)

명명된 function 표현식

세 번째 형식은 명명된 함수 표현식 ("NFE")입니다.

 var z = function w() { console.log('zw') };

이것이 생성하는 함수는 고유한 이름(이 경우 w 모든 표현식과 마찬가지로 이것은 코드의 단계별 실행에서 도달할 때 평가됩니다. 함수 이름은 표현식이 나타나는 범위에 추가 되지 않습니다. 이름 함수 자체의 범위에 있습니다.

 var z = function w() { console.log(typeof w); // "function" }; console.log(typeof w); // "undefined"

NFE는 종종 JavaScript 구현에 대한 버그의 소스였습니다. 예를 들어 IE8 및 이전 버전은 NFE를 완전히 잘못 처리하여 두 개의 다른 시간에 두 개의 다른 기능을 생성합니다. Safari의 초기 버전에도 문제가 있었습니다. 좋은 소식은 현재 버전의 브라우저(IE9 이상, 현재 Safari)에는 더 이상 이러한 문제가 없다는 것입니다. (그러나 이 글을 쓰는 시점에서 슬프게도 IE8은 여전히 널리 사용되고 있으므로 일반적으로 웹용 코드와 함께 NFE를 사용하는 것은 여전히 문제가 있습니다.)

접근자 함수 이니셜라이저(ES5+)

때로는 기능이 크게 눈에 띄지 않고 몰래 들어갈 수 있습니다. 그것은 접근자 함수 의 경우입니다. 다음은 예입니다.

 var obj = { value: 0, get f() { return this.value; }, set f(v) { this.value = v; } }; console.log(obj.f); // 0 console.log(typeof obj.f); // "number"

함수를 사용할 때 () 사용하지 않았습니다! 속성에 대한 접근자 함수 이기 때문입니다. 우리는 일반적인 방식으로 속성을 얻고 설정하지만 배후에서 함수가 호출됩니다.

Object.defineProperty , Object.defineProperties Object.create 대한 덜 알려진 두 번째 인수를 사용하여 접근자 함수를 만들 수도 있습니다.

화살표 함수 표현식(ES2015+)

ES2015는 화살표 기능을 제공 합니다. 다음은 한 가지 예입니다.

 var a = [1, 2, 3]; var b = a.map(n => n * 2); console.log(b.join(", ")); // 2, 4, 6

n => n * 2 map() 호출에 숨겨져 있는 것을 보셨습니까? 그것은 기능입니다.

화살표 함수에 대한 몇 가지 사항:

  1. this 가지고 있지 않습니다 . 대신 정의된 컨텍스트의 this 를 닫습니다. arguments 와 관련이 있는 경우 super 대해서도 닫힙니다.) 이것은 그 안의 this this 와 동일하며 변경할 수 없음을 의미합니다.

  2. 위의 내용에서 알 수 있듯이 키워드 function 사용하지 않습니다. => 를 사용합니다.

위의 n => n * 2 예제는 그 중 하나입니다. 함수를 전달할 인수가 여러 개인 경우 괄호를 사용합니다.

 var a = [1, 2, 3]; var b = a.map((n, i) => n * i); console.log(b.join(", ")); // 0, 2, 6

Array#map 은 항목을 첫 번째 인수로 전달하고 인덱스를 두 번째 인수로 전달한다는 것을 기억하십시오.)

두 경우 모두 함수의 본문은 표현식일 뿐입니다. 함수의 반환 값은 자동으로 해당 표현식의 결과가 됩니다(명시적 return 사용하지 않음).

단일 표현식 이상을 수행하는 {} 및 명시적 return (값을 반환해야 하는 경우)을 사용합니다.

 var a = [ {first: "Joe", last: "Bloggs"}, {first: "Albert", last: "Bloggs"}, {first: "Mary", last: "Albright"} ]; a = a.sort((a, b) => { var rv = a.last.localeCompare(b.last); if (rv === 0) { rv = a.first.localeCompare(b.first); } return rv; }); console.log(JSON.stringify(a));

{ ... } 가 없는 버전 은 표현식 본문 또는 간결한 본문이 있는 화살표 함수라고 합니다. (또한 :. 간결한 기능 화살표)와 하나 { ... } 본체를 형성하는 기능은 본체와 화살표 함수이다. (또한: 자세한 화살표 기능.)

객체 이니셜라이저의 메서드 선언(ES2015+)

ES2015는 메서드 정의 라는 함수를 참조하는 속성을 선언하는 더 짧은 형식을 허용합니다. 다음과 같이 보입니다.

 var o = { foo() { } };

ES5 및 이전 버전에서 거의 동등한 것은 다음과 같습니다.

 var o = { foo: function foo() { } };

차이점(자세한 정도 제외)은 메서드가 super 를 사용할 수 있지만 함수는 사용할 수 없다는 것입니다. 따라서 예를 들어 메서드 구문을 사용하여 valueOf 를 정의한(말하자면) 객체가 super.valueOf() Object.prototype.valueOf 가 반환했을 값을 가져올 수 있습니다(아마도 다른 작업을 수행하기 전에). ES5 버전은 Object.prototype.valueOf.call(this) 을 수행해야 합니다.

이는 또한 메서드에 정의된 개체에 대한 참조가 있다는 것을 의미하므로 해당 개체가 임시인 경우(예: 소스 개체 중 하나로 개체 Object.assign 전달하는 경우) 메서드 구문은 다음을 의미할 수 있습니다. 객체는 그렇지 않으면 가비지 수집되었을 수 있는 경우 메모리에 유지됩니다(JavaScript 엔진이 해당 상황을 감지하지 못하고 super 사용하는 메서드가 없는 경우 처리).

class 생성자 및 메서드 선언(ES2015+)

ES2015는 선언된 생성자와 메소드를 포함한 class

 class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + " " + this.lastName; } }

위에 두 개의 함수 선언이 있습니다. 하나는 Person 이라는 이름을 가져오는 생성자용이고 다른 하나 Person.prototype 할당된 함수인 getFullName 용입니다.



답변자 : Christian C. Salvadó


전역 컨텍스트에 대해 말하면 var 문과 마지막에 FunctionDeclaration 은 전역 개체에 삭제할 수 없는 속성을 생성하지만 둘 다 값을 덮어쓸 수 있습니다 .

두 가지 방법의 미묘한 차이는 Variable Instantiation 프로세스가 실행될 때(실제 코드 실행 전에) var undefined 로 초기화되고 FunctionDeclaration 사용하는 식별자를 그 순간부터 사용할 수 있다는 것입니다. 예시:

 alert(typeof foo); // 'function', it's already available alert(typeof bar); // 'undefined' function foo () {} var bar = function () {}; alert(typeof bar); // 'function'

bar FunctionExpression 의 할당은 런타임까지 발생합니다.

FunctionDeclaration 의해 생성된 전역 속성은 변수 값처럼 문제 없이 덮어쓸 수 있습니다. 예:

 function test () {} test = null;

두 예제 사이의 또 다른 분명한 차이점은 첫 번째 함수에는 이름이 없지만 두 번째 함수에는 이름이 있다는 것입니다. 이는 디버깅(예: 호출 스택 검사)할 때 정말 유용할 수 있습니다.

편집된 첫 번째 예제( foo = function() { alert('hello!'); }; )에 대해서는 선언되지 않은 할당이므로 항상 var 키워드를 사용하는 것이 좋습니다.

var 문 없이 할당을 사용하면 참조된 식별자가 범위 체인에서 발견되지 않으면 전역 개체의 삭제 가능한 속성이 됩니다.

또한 선언되지 않은 할당 은 Strict Mode 의 ECMAScript 5에서 ReferenceError 를 발생시킵니다.

반드시 읽어야 할 사항:

참고 : 이 답변은 OP의 주요 의구심과 오해가 FunctionDeclaration 선언된 식별자를 덮어쓸 수 없다는 다른 질문에서 병합되었습니다.



답변자 : thomasrutter


여기에 게시한 두 개의 코드 조각은 거의 모든 목적에서 동일한 방식으로 작동합니다.

그러나 동작의 차이점은 첫 번째 변형( var functionOne = function() {} )에서 해당 함수는 코드의 해당 지점 이후에만 호출할 수 있다는 것입니다.

두 번째 변형( function functionTwo() )을 사용하면 함수가 선언된 위치 위에서 실행되는 코드에서 함수를 사용할 수 있습니다.

이는 첫 번째 변형에서 함수가 런타임에 foo 두 번째에서 함수는 구문 분석 시 foo

추가 기술 정보

JavaScript에는 함수를 정의하는 세 가지 방법이 있습니다.

  1. 첫 번째 스니펫은 함수 표현식을 보여줍니다. 여기에는 "함수" 연산자 를 사용하여 함수를 만드는 작업이 포함됩니다. 해당 연산자의 결과는 모든 변수 또는 개체 속성에 저장할 수 있습니다. 함수 표현은 그런 식으로 강력합니다. 함수 표현식은 이름이 필요하지 않기 때문에 종종 "익명 함수"라고 합니다.
  2. 두 번째 예는 함수 선언 입니다. 이것은 "function" 문 을 사용하여 함수를 생성합니다. 함수는 구문 분석 시간에 사용할 수 있으며 해당 범위의 어디에서나 호출할 수 있습니다. 나중에 변수나 개체 속성에 계속 저장할 수 있습니다.
  3. 함수를 정의하는 세 번째 방법은 원래 게시물에 표시되지 않은 "Function()" 생성자입니다. 문제가 있는 eval() 과 같은 방식으로 작동하므로 사용하지 않는 것이 좋습니다.


답변자 : suhailvs


Greg의 답변에 대한 더 나은 설명

 functionTwo(); function functionTwo() { }

왜 오류가 없습니까? 우리는 항상 표현식이 위에서 아래로(??) 실행된다고 배웠습니다.

때문에:

함수 선언과 변수 선언은 JavaScript 인터프리터에 의해 항상 포함 범위의 맨 위로 보이지 않게 hoisted 함수 매개변수와 언어 정의 이름은 분명히 이미 존재합니다. 벤 체리

이것은 다음과 같은 코드를 의미합니다.

 functionOne(); --------------- var functionOne; | is actually | functionOne(); var functionOne = function(){ | interpreted |--> }; | like | functionOne = function(){ --------------- };

선언의 할당 부분은 호이스팅되지 않았습니다. 이름만 올려집니다.

그러나 함수 선언의 경우 전체 함수 본문도 호이스팅됩니다 .

 functionTwo(); --------------- function functionTwo() { | is actually | }; function functionTwo() { | interpreted |--> } | like | functionTwo(); ---------------


답변자 : Sean McMillan


다른 코멘터들은 이미 위의 두 변형의 의미적 차이를 다루었습니다. 문체의 차이에 주목하고 싶었습니다. "할당" 변형만 다른 개체의 속성을 설정할 수 있습니다.

저는 종종 다음과 같은 패턴으로 JavaScript 모듈을 빌드합니다.

 (function(){ var exports = {}; function privateUtil() { ... } exports.publicUtil = function() { ... }; return exports; })();

이 패턴을 사용하면 공개 함수는 모두 할당을 사용하고 비공개 함수는 선언을 사용합니다.

(또한 선언은 금지하는 반면 할당은 명령문 뒤에 세미콜론을 요구해야 합니다.)



답변자 : Mbengue Assane


첫 번째 방법을 두 번째 방법보다 선호하는 경우는 함수의 이전 정의를 재정의하는 것을 피해야 하는 경우입니다.

와 함께

 if (condition){ function myfunction(){ // Some code } }

myfunction 이 정의는 구문 분석 시간에 수행되기 때문에 이전 정의를 재정의합니다.

하는 동안

 if (condition){ var myfunction = function (){ // Some code } }

condition 이 충족될 때만 myfunction 을 정의하는 올바른 작업을 수행합니다.



답변자 : Rob


중요한 이유는 네임스페이스의 "루트"로 하나의 변수만 추가하는 것입니다...

 var MyNamespace = {} MyNamespace.foo= function() { }

또는

 var MyNamespace = { foo: function() { }, ... }

네임스페이스에는 많은 기술이 있습니다. 사용 가능한 JavaScript 모듈이 너무 많아지면서 더욱 중요해졌습니다.

또한 JavaScript에서 네임스페이스를 선언하는 방법을 참조하십시오.



답변자 : Yash


호이스팅 은 모든 변수 및 함수 선언을 현재 범위의 맨 위로 이동하는 JavaScript 인터프리터의 작업입니다.

그러나 실제 선언만 호이스팅됩니다. 그들이 있는 곳에 과제를 남겨둠으로써.

  • 페이지 내부에 선언된 변수/함수는 전역적이며 해당 페이지의 어느 곳에서나 액세스할 수 있습니다.
  • 함수 내에서 선언된 변수/함수는 로컬 범위를 갖습니다. 함수 본문(범위) 내부에서 사용 가능/액세스할 수 있음을 의미하며, 함수 본문 외부에서는 사용할 수 없습니다.

변하기 쉬운

자바스크립트는 느슨한 형식의 언어라고 합니다. 이는 Javascript 변수가 모든 Data-Type 값을 보유할 수 있음을 의미합니다. Javascript는 런타임 중에 제공된 값/리터럴을 기반으로 변수 유형 변경을 자동으로 처리합니다.

 global_Page = 10; var global_Page; « undefined « Integer literal, Number Type. ------------------- global_Page = 10; « Number global_Page = 'Yash'; | Interpreted | global_Page = 'Yash'; « String « String literal, String Type. « AS « global_Page = true; « Boolean var global_Page = true; | | global_Page = function (){ « function « Boolean Type ------------------- var local_functionblock; « undefined global_Page = function (){ local_functionblock = 777;« Number var local_functionblock = 777; }; // Assigning function as a data. };

기능

 function Identifier_opt ( FormalParameterList_opt ) { FunctionBody | sequence of statements « return; Default undefined « return 'some data'; }
  • 페이지 내부에 선언된 함수는 전역 액세스 권한이 있는 페이지의 맨 위로 호이스트됩니다.
  • function-block 내부에 선언된 함수는 블록의 맨 위로 올라갑니다.
  • 함수의 기본 반환 값은 ' undefined '이고 변수 선언 기본값도 'undefined'입니다.

     Scope with respect to function-block global. Scope with respect to page undefined | not available.

함수 선언

 function globalAccess() { function globalAccess() { } ------------------- } globalAccess(); | | function globalAccess() { « Re-Defined / overridden. localAccess(); « Hoisted As « function localAccess() { function globalAccess() { | | } localAccess(); ------------------- localAccess(); « function accessed with in globalAccess() only. function localAccess() { } } globalAccess(); } localAccess(); « ReferenceError as the function is not defined

함수 표현

 10; « literal (10); « Expression (10).toString() -> '10' var a; a = 10; « Expression var a.toString() -> '10' (function invoke() { « Expression Function console.log('Self Invoking'); (function () { }); }) () -> 'Self Invoking' var f; f = function (){ « Expression var Function console.log('var Function'); f () -> 'var Function' };

변수에 할당된 함수 예:

 (function selfExecuting(){ console.log('IIFE - Immediately-Invoked Function Expression'); }()); var anonymous = function (){ console.log('anonymous function Expression'); }; var namedExpression = function for_InternalUSE(fact){ if(fact === 1){ return 1; } var localExpression = function(){ console.log('Local to the parent Function Scope'); }; globalExpression = function(){ console.log('creates a new global variable, then assigned this function.'); }; //return; //undefined. return fact * for_InternalUSE( fact - 1); }; namedExpression(); globalExpression();

자바 스크립트는 다음과 같이 해석됩니다.

 var anonymous; var namedExpression; var globalExpression; anonymous = function (){ console.log('anonymous function Expression'); }; namedExpression = function for_InternalUSE(fact){ var localExpression; if(fact === 1){ return 1; } localExpression = function(){ console.log('Local to the parent Function Scope'); }; globalExpression = function(){ console.log('creates a new global variable, then assigned this function.'); }; return fact * for_InternalUSE( fact - 1); // DEFAULT UNDEFINED. }; namedExpression(10); globalExpression();

jsperf Test Runner 사용하여 다른 브라우저에서 함수 선언, 표현식 테스트를 확인할 수 있습니다.


ES5 생성자 함수 클래스 : Function.prototype.bind를 사용하여 생성된 함수 객체

JavaScript는 함수를 일급 객체로 취급하므로 객체이므로 함수에 속성을 할당할 수 있습니다.

 function Shape(id) { // Function Declaration this.id = id; }; // Adding a prototyped method to a function. Shape.prototype.getID = function () { return this.id; }; Shape.prototype.setID = function ( id ) { this.id = id; }; var expFn = Shape; // Function Expression var funObj = new Shape( ); // Function Object funObj.hasOwnProperty('prototype'); // false funObj.setID( 10 ); console.log( funObj.getID() ); // 10

ES6에 Arrow 함수 도입: 화살표 함수 표현식은 구문이 더 짧고 비메서드 함수에 가장 적합하며 생성자로 사용할 수 없습니다.

ArrowFunction : ArrowParameters => ConciseBody .

 const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd


답변자 : Leon Gaban


다른 모든 사람들이 게양 부분을 철저히 다루었기 때문에 내 자신의 답변을 추가하고 있습니다.

나는 오랫동안 어떤 방법이 더 나은지 궁금했는데 http://jsperf.com 덕분에 이제 알았습니다. :)

여기에 이미지 설명 입력

함수 선언 이 더 빠르며, 이것이 웹 개발에서 정말 중요한 것입니다. 맞나요? ;)



답변자 : eljenso


변수에 할당된 함수 선언과 함수 표현식은 바인딩이 설정되면 동일하게 작동합니다.

그러나 함수 개체가 실제로 변수와 연결 되는 방법시기에 차이가 있습니다. 이 차이는 JavaScript에서 변수 호이스팅이라는 메커니즘 때문입니다.

기본적으로 모든 함수 선언과 변수 선언은 선언이 발생한 함수 의 맨 위로 호이스트됩니다(이것이 JavaScript에 함수 범위 가 있다고 말하는 이유입니다).

  • 함수 선언이 호이스트되면 함수 본문이 "따라서" 함수 본문이 평가될 때 변수가 즉시 함수 개체에 바인딩됩니다.

  • 변수 선언이 호이스트되면 초기화가 따르지 않고 "뒤에 남겨집니다". 변수는 함수 본문 시작 시 undefined 로 초기화되며 코드의 원래 위치에 값 이 할당됩니다. (실제로는 같은 이름의 변수 선언이 발생하는 모든 위치에 값이 할당됩니다.)

호이스팅의 순서도 중요합니다. 함수 선언은 같은 이름의 변수 선언보다 우선하고 마지막 함수 선언은 같은 이름의 이전 함수 선언보다 우선합니다.

몇 가지 예...

 var foo = 1; function bar() { if (!foo) { var foo = 10 } return foo; } bar() // 10

변수 foo 는 함수의 맨 위로 호이스트되고 undefined !footrue 이므로 foo 10 이 할당됩니다. bar 의 범위 밖에 있는 foo 는 아무 역할도 하지 않으며 건드리지 않습니다.

 function f() { return a; function a() {return 1}; var a = 4; function a() {return 2}} f()() // 2 function f() { return a; var a = 4; function a() {return 1}; function a() {return 2}} f()() // 2

함수 선언은 변수 선언보다 우선하며 마지막 함수 선언은 "고정"됩니다.

 function f() { var a = 4; function a() {return 1}; function a() {return 2}; return a; } f() // 4

이 예에서 a 는 두 번째 함수 선언을 평가한 결과 함수 객체로 초기화된 다음 4 가 할당됩니다.

 var a = 1; function b() { a = 10; return; function a() {}} b(); a // 1

여기서 함수 선언이 먼저 호이스트되어 변수 a 선언하고 초기화합니다. 다음으로 이 변수에 10 이 할당됩니다. 즉, 할당은 외부 변수 a 할당하지 않습니다.



답변자 : sla55er


첫 번째 예는 함수 선언입니다.

 function abc(){}

두 번째 예는 함수 표현식입니다.

 var abc = function() {};

주요 차이점은 어떻게 들어 올려지는가(들어 올리고 선언)입니다. 첫 번째 예에서는 전체 함수 선언이 호이스트됩니다. 두 번째 예에서는 var 'abc'만 호이스트되고 해당 값(함수)은 정의되지 않으며 함수 자체는 선언된 위치에 유지됩니다.

간단히 말해서:

 //this will work abc(param); function abc(){} //this would fail abc(param); var abc = function() {}

이 주제에 대해 더 자세히 알아보려면 이 링크를 강력히 추천합니다.



답변자 : Jack G


.

  1. 기능의 가용성(범위)

다음은 function add() 가 가장 가까운 블록으로 범위가 지정되기 때문에 작동합니다.

 try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } function add(a, b){ return a + b; }

add 할당되기 전에 변수가 호출되기 때문에 다음은 작동하지 않습니다.

 try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } var add=function(a, b){ return a + b; }

위 코드는 아래 코드와 기능면에서 동일합니다. add = undefined 를 명시적으로 지정하는 var add; 를 수행하기 때문에 불필요합니다. var add=undefined 와 정확히 동일합니다.

 var add = undefined; try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } add = function(a, b){ return a + b; }

var add= 가 표현식을 시작하고 다음 function add() 가 블록 대신 표현식이 되도록 하기 때문에 작동하지 않습니다. 명명된 함수는 자신과 주변 블록에만 표시됩니다. function add() 는 여기에서 표현식이므로 주변 블록이 없으므로 자신에게만 표시됩니다.

 try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } var add=function add(a, b){ return a + b; }

  1. (함수) .이름

함수 함수의 이름은 function thefuncname(){}이렇게 선언되었을 때의 funcname입니다.

 function foobar(a, b){} console.log(foobar.name);

 var a = function foobar(){}; console.log(a.name);

그렇지 않고 함수가 function(){} 으로 선언된 경우 함수 .name은 함수를 저장하는 데 사용되는 첫 번째 변수입니다.

 var a = function(){}; var b = (function(){ return function(){} }); console.log(a.name); console.log(b.name);

함수에 설정된 변수가 없으면 함수 이름은 빈 문자열( "" )입니다.

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

마지막으로, 함수가 할당된 변수는 초기에 이름을 설정하지만, 함수에 연속적으로 설정된 변수는 이름을 변경하지 않습니다.

 var a = function(){}; var b = a; var c = b; console.log(a.name); console.log(b.name); console.log(c.name);

  1. 성능

Google의 V8과 Firefox의 Spidermonkey에서는 몇 마이크로초의 JIST 컴파일 차이가 있을 수 있지만 궁극적으로 결과는 정확히 동일합니다. 이를 증명하기 위해 두 개의 빈 코드 조각의 속도를 비교하여 마이크로 벤치마크에서 JSPerf의 효율성을 살펴보겠습니다. JSPerf 테스트는 여기에서 찾을 수 있습니다 . 그리고 jsben.ch 테스트는 여기에서 찾을 수 있습니다 . 보시다시피, 아무 것도 없어야 할 때 눈에 띄는 차이가 있습니다. 당신이 정말로 저와 같은 성능 괴물이라면 스코프에서 변수와 함수의 수를 줄이고 특히 다형성(같은 변수를 사용하여 두 가지 다른 유형을 저장하는 것과 같은)을 제거하는 동안 더 가치가 있을 수 있습니다.

  1. 가변 가변성

var 키워드를 사용하여 변수를 선언할 때 이와 같이 변수에 다른 값을 재할당할 수 있습니다.

 (function(){ "use strict"; var foobar = function(){}; // initial value try { foobar = "Hello World!"; // new value console.log("[no error]"); } catch(error) { console.log("ERROR: " + error.message); } console.log(foobar, window.foobar); })();

그러나 const-statement를 사용하면 변수 참조가 변경되지 않습니다. 이는 변수에 새 값을 할당할 수 없음을 의미합니다. 그러나 이것이 변수의 내용을 불변으로 만들지 않는다는 점에 유의하십시오. const arr = [] 를 수행하면 여전히 arr[10] = "example" 수행할 수 있습니다. arr = "new value" 또는 arr = [] 와 같은 작업만 수행하면 아래와 같이 오류가 발생합니다.

 (function(){ "use strict"; const foobar = function(){}; // initial value try { foobar = "Hello World!"; // new value console.log("[no error]"); } catch(error) { console.log("ERROR: " + error.message); } console.log(foobar, window.foobar); })();

흥미롭게도 변수를 function funcName(){} var 로 선언하는 것과 같습니다.

 (function(){ "use strict"; function foobar(){}; // initial value try { foobar = "Hello World!"; // new value console.log("[no error]"); } catch(error) { console.log("ERROR: " + error.message); } console.log(foobar, window.foobar); })();

" "

"가장 가까운 블록"은 가장 가까운 "함수"(비동기 함수, 생성기 함수 및 비동기 생성기 함수 포함)입니다. 그러나 흥미롭게도 function functionName() {} 은 클로저 외부의 항목에 대한 비클로저 블록에 있을 때 var functionName = function() {} 처럼 작동합니다. 관찰하다.

  • 일반 var add=function(){}

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}'); } } catch(e) { console.log("Is a block"); } var add=function(a, b){return a + b}

  • 일반 function add(){}

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}') } } catch(e) { console.log("Is a block"); } function add(a, b){ return a + b; }

  • 기능

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}') } } catch(e) { console.log("Is a block"); } (function () { function add(a, b){ return a + b; } })();

  • 문(예: if , else , for , while , try / catch / finally , switch , do / while , with )

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}') } } catch(e) { console.log("Is a block"); } { function add(a, b){ return a + b; } }

  • var add=function() 화살표 함수

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}') } } catch(e) { console.log("Is a block"); } (() => { var add=function(a, b){ return a + b; } })();

  • 화살표 function add()

 try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn't exist console.log('Behaves like var add=function(a,b){return a+b}') } } catch(e) { console.log("Is a block"); } (() => { function add(a, b){ return a + b; } })();



답변자 : Sasha Firsov


코드 유지 비용 측면에서 명명된 함수가 더 바람직합니다.

  • 선언된 장소와는 별개입니다(그러나 여전히 범위에 의해 제한됨).
  • 조건부 초기화와 같은 실수에 더 강합니다(원하는 경우 계속 재정의할 수 있음).
  • 범위 기능과 별도로 로컬 기능을 할당하여 코드를 보다 쉽게 읽을 수 있습니다. 일반적으로 범위 내에서 기능이 먼저 실행되고 그 다음에 로컬 기능이 선언됩니다.
  • 디버거에서는 "익명/평가된" 함수 대신 호출 스택에서 함수 이름을 명확하게 볼 수 있습니다.

명명 된 기능에 대한 더 많은 PROS가 있다고 생각합니다. 그리고 명명된 함수의 장점으로 나열되는 것은 익명 함수의 단점입니다.

역사적으로, 익명 함수는 이름이 지정된 함수를 가진 멤버를 나열하는 언어로서의 JavaScript의 무능력에서 나타났습니다.

 { member:function() { /* How do I make "this.member" a named function? */ } }


답변자 : Rohan


Greg's Answer 도 충분하지만 Douglas Crockford의 비디오를 보고 방금 배운 것을 추가하고 싶습니다.

함수 표현:

 var foo = function foo() {};

기능 설명:

 function foo() {};

function 문은 function 값이 있는 var

그래서

 function foo() {};

확장

 var foo = function foo() {};

다음으로 확장됩니다.

 var foo = undefined; foo = function foo() {};

그리고 둘 다 코드의 맨 위로 호이스트됩니다.

비디오의 스크린샷



답변자 : Kafka


컴퓨터 과학 용어로 우리는 익명 함수와 명명된 함수에 대해 이야기합니다. 가장 중요한 차이점은 익명 함수가 이름에 바인딩되지 않으므로 이름이 익명 함수라는 것입니다. JavaScript에서는 런타임에 동적으로 선언된 첫 번째 클래스 객체입니다.

익명 함수 및 람다 미적분에 대한 자세한 내용은 Wikipedia에서 시작하는 것이 좋습니다. Anonymous Functions .



답변자 : Herc


나는 매우 구체적인 이유로 내 코드에서 변수 접근 방식을 사용합니다. 그 이론은 위에서 추상적인 방식으로 다루었지만 예제는 제한된 JavaScript 전문 지식을 가진 나와 같은 일부 사람들에게 도움이 될 수 있습니다.

160개의 독립적으로 디자인된 브랜딩으로 실행해야 하는 코드가 있습니다. 대부분의 코드는 공유 파일에 있지만 브랜딩 관련 항목은 각 브랜딩에 대해 하나씩 별도의 파일에 있습니다.

일부 브랜딩에는 특정 기능이 필요하고 일부는 필요하지 않습니다. 때로는 새로운 브랜딩 관련 작업을 수행하기 위해 새로운 기능을 추가해야 합니다. 공유 코드를 변경하게 되어 기쁩니다. 하지만 160개의 브랜딩 파일 세트를 모두 변경하고 싶지는 않습니다.

변수 구문을 사용하여 공유 코드에서 변수(기본적으로 함수 포인터)를 선언하고 간단한 스텁 함수를 할당하거나 null로 설정할 수 있습니다.

함수의 특정 구현이 필요한 한두 개의 브랜딩은 함수 버전을 정의하고 원하는 경우 이를 변수에 할당하고 나머지는 아무 작업도 수행하지 않습니다. 공유 코드에서 실행하기 전에 null 함수를 테스트할 수 있습니다.

위의 사람들의 의견에서 정적 함수를 재정의하는 것이 가능할 수도 있지만 변수 솔루션이 멋지고 명확하다고 생각합니다.



답변자 : Joel Purra


@EugeneLazutkin 은 자신에 대한 내부 참조로 shortcut() 를 사용할 수 있도록 할당된 함수의 이름을 지정 하는 예를 제공합니다. John Resig 는 Learning Advanced Javascript 튜토리얼에서 다른 객체에 할당된 재귀 함수를 복사하는 또 다른 예를 제공합니다. 여기에서 속성에 함수를 할당하는 것이 엄밀히 말하면 질문은 아니지만, 튜토리얼을 적극적으로 시도하는 것이 좋습니다. 오른쪽 상단 모서리에 있는 버튼을 클릭하여 코드를 실행하고 원하는 대로 편집하려면 코드를 두 번 클릭하십시오.

튜토리얼의 예: yell() 재귀 호출:

원래 닌자 개체가 제거되면 테스트가 실패합니다. (13페이지)

 var ninja = { yell: function(n){ return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); var samurai = { yell: ninja.yell }; var ninja = null; try { samurai.yell(4); } catch(e){ assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); }

재귀적으로 호출될 함수의 이름을 지정하면 테스트가 통과합니다. (14페이지)

 var ninja = { yell: function yell(n){ return n > 0 ? yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); var samurai = { yell: ninja.yell }; var ninja = {}; assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );


답변자 : Ingo Kegel


다른 답변에서 언급되지 않은 또 다른 차이점은 익명 기능을 사용하는 경우

 var functionOne = function() { // Some code };

다음과 같이 생성자로 사용하십시오.

 var one = new functionOne();

그러면 one.constructor.name 이 정의되지 않습니다. Function.name 은 비표준이지만 Firefox, Chrome, 기타 Webkit 파생 브라우저 및 IE 9+에서 지원됩니다.

와 함께

 function functionTwo() { // Some code } two = new functionTwo();

two.constructor.name 을 사용하여 생성자의 이름을 문자열로 검색할 수 있습니다.



답변자 : NullPoiиteя


첫 번째 함수(함수 doSomething(x))는 객체 표기법의 일부여야 합니다.

두 번째 var doSomething = function(x){ alert(x);} )는 단순히 익명의 함수를 만들어 변수 doSomething 할당하는 것입니다. 따라서 doSomething()이 함수를 호출합니다.

함수 선언함수 표현식 이 무엇인지 알고 싶을 수 있습니다.

함수 선언은 변수 할당 없이 명명된 함수 변수를 정의합니다. 함수 선언은 독립 실행형 구성으로 발생하며 비함수 블록 내에서 중첩될 수 없습니다.

 function foo() { return 3; }

ECMA 5(13.0)는 구문을 다음과 같이 정의합니다.
함수 식별자 ( FormalParameterList opt ) { FunctionBody }

위의 조건에서 함수 이름은 해당 범위와 상위 범위 내에서 볼 수 있습니다(그렇지 않으면 도달할 수 없음).

그리고 함수 표현식에서

함수 표현식은 더 큰 표현식 구문(일반적으로 변수 할당)의 일부로 함수를 정의합니다. 함수 표현식을 통해 정의된 함수는 이름을 지정하거나 익명으로 지정할 수 있습니다. 함수 표현식은 "function"으로 시작해서는 안 됩니다.

 // Anonymous function expression var a = function() { return 3; } // Named function expression var a = function foo() { return 3; } // Self-invoking function expression (function foo() { alert("hello!"); })();

ECMA 5(13.0)는 구문을 다음과 같이 정의합니다.
함수 식별자 opt ( FormalParameterList opt ) { FunctionBody }



답변자 : varna


나는 아래에 차이점을 나열하고 있습니다:

  1. 함수 선언은 코드의 아무 곳에나 배치할 수 있습니다. 코드에 정의가 나타나기 전에 호출되더라도 페이지의 다른 코드가 실행을 시작하기 전에 함수 선언이 메모리에 커밋되거나 호이스트 업되는 방식으로 실행됩니다.

    아래 기능을 살펴보세요.

     function outerFunction() { function foo() { return 1; } return foo(); function foo() { return 2; } } alert(outerFunction()); // Displays 2

    실행하는 동안 다음과 같이 보이기 때문입니다.

     function foo() { // The first function declaration is moved to top return 1; } function foo() { // The second function declaration is moved to top return 2; } function outerFunction() { return foo(); } alert(outerFunction()); //So executing from top to bottom, //the last foo() returns 2 which gets displayed

    함수 표현식을 호출하기 전에 정의하지 않으면 오류가 발생합니다. 또한 여기서 함수 정의 자체는 함수 선언과 같이 맨 위로 이동하거나 메모리에 커밋되지 않습니다. 그러나 우리가 함수를 할당한 변수는 호이스팅되고 undefined 가 할당됩니다.

    함수 표현식을 사용하는 동일한 함수:

     function outerFunction() { var foo = function() { return 1; } return foo(); var foo = function() { return 2; } } alert(outerFunction()); // Displays 1

    실행하는 동안 다음과 같이 보이기 때문입니다.

     function outerFunction() { var foo = undefined; var foo = undefined; foo = function() { return 1; }; return foo (); foo = function() { // This function expression is not reachable return 2; }; } alert(outerFunction()); // Displays 1
  2. 액세스할 수 없기 때문에 if 와 같은 비함수 블록에 함수 선언을 작성하는 것은 안전하지 않습니다.

     if (test) { function x() { doSomething(); } }
  3. 아래와 같은 명명된 함수 표현식은 버전 9 이전의 Internet Explorer 브라우저에서 작동하지 않을 수 있습니다.

     var today = function today() {return new Date()}


답변자 : Pawel Furmaniak


이러한 함수를 사용하여 객체를 생성하면 다음을 얻을 수 있습니다.

 var objectOne = new functionOne(); console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function var objectTwo = new functionTwo(); console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function


답변자 : Panos Kal.


성능 정보:

V8 새 버전은 몇 가지 내부 최적화를 도입했으며 SpiderMonkey 도 마찬가지였습니다.

이제는 표현과 선언 사이에 거의 차이가 없습니다.
이제 함수 표현 이 더 빨라진 것 같습니다 .

크롬 62.0.3202 크롬 테스트

파이어폭스 55 파이어폭스 테스트

크롬 카나리아 63.0.3225 크롬 카나리아 테스트


Anonymous 함수 표현식 Named 함수 표현식에 대해 더 나은 성능을 보이는 것으로 보입니다.


파이어폭스 파이어폭스 named_anonymous 크롬 카나리아 크롬 카나리아 named_anonymous 크롬 이름이 _익명인 Chrome



답변자 : Jackson


"명명된 함수가 스택 추적에 표시됨" 인수에 비추어 볼 때 최신 JavaScript 엔진은 실제로 익명 함수를 상당히 표현할 수 있습니다.

이 글을 쓰는 시점에서 V8, SpiderMonkey, Chakra 및 Nitro는 항상 이름으로 명명된 함수를 참조합니다. 식별자가 있는 경우 거의 항상 식별자로 익명 함수를 참조합니다.

SpiderMonkey는 다른 함수에서 반환된 익명 함수의 이름을 알아낼 수 있습니다. 나머지는 할 수 없습니다.

반복자 및 성공 콜백이 추적에 표시되기를 정말로 원한다면 이름도 지정할 수 있습니다.

 [].forEach(function iterator() {});

그러나 대부분의 경우 강조할 가치가 없습니다.

하네스( 바이올린 )

 'use strict'; var a = function () { throw new Error(); }, b = function b() { throw new Error(); }, c = function d() { throw new Error(); }, e = { f: a, g: b, h: c, i: function () { throw new Error(); }, j: function j() { throw new Error(); }, k: function l() { throw new Error(); } }, m = (function () { return function () { throw new Error(); }; }()), n = (function () { return function n() { throw new Error(); }; }()), o = (function () { return function p() { throw new Error(); }; }()); console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) { return values.concat(e[key]); }, [])).concat([m, n, o]).reduce(function (logs, func) { try { func(); } catch (error) { return logs.concat('func.name: ' + func.name + '\n' + 'Trace:\n' + error.stack); // Need to manually log the error object in Nitro. } }, []).join('\n\n'));

V8

 func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at ei (http://localhost:8000/test.js:17:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: j Trace: Error at j (http://localhost:8000/test.js:20:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: l Trace: Error at l (http://localhost:8000/test.js:23:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at http://localhost:8000/test.js:28:19 at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: n Trace: Error at n (http://localhost:8000/test.js:33:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: p Trace: Error at p (http://localhost:8000/test.js:38:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 test.js:42

거미 원숭이

 func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: ei@http://localhost:8000/test.js:17:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: j Trace: j@http://localhost:8000/test.js:20:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: l Trace: l@http://localhost:8000/test.js:23:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: m</<@http://localhost:8000/test.js:28:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: n Trace: n@http://localhost:8000/test.js:33:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: p Trace: p@http://localhost:8000/test.js:38:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1

차크라

 func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at ei (http://localhost:8000/test.js:17:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at j (http://localhost:8000/test.js:20:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at l (http://localhost:8000/test.js:23:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at Anonymous function (http://localhost:8000/test.js:28:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at n (http://localhost:8000/test.js:33:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at p (http://localhost:8000/test.js:38:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1)

니트로

 func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: i@http://localhost:8000/test.js:17:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: j Trace: j@http://localhost:8000/test.js:20:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: l Trace: l@http://localhost:8000/test.js:23:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: http://localhost:8000/test.js:28:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: n Trace: n@http://localhost:8000/test.js:33:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: p Trace: p@http://localhost:8000/test.js:38:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33


답변자 : Nitin9791


둘 다 함수를 정의하는 다른 방법입니다. 차이점은 브라우저가 이를 해석하고 실행 컨텍스트로 로드하는 방법입니다.

첫 번째 경우는 인터프리터가 해당 코드 행에 도달할 때만 로드되는 함수 표현식입니다. 따라서 다음과 같이 하면 functionOne 이 함수가 아니라는 오류가 발생합니다.

 functionOne(); var functionOne = function() { // Some code };

그 이유는 첫 번째 줄에서 functionOne에 값이 할당되지 않았으므로 정의되지 않았기 때문입니다. 함수로 호출하려고 하므로 오류가 발생합니다.

두 번째 줄에서 익명 함수의 참조를 functionOne에 할당합니다.

두 번째 경우는 코드가 실행되기 전에 로드되는 함수 선언입니다. 따라서 다음과 같이 하면 코드 실행 전에 선언이 로드될 때 오류가 발생하지 않습니다.

 functionOne(); function functionOne() { // Some code }


답변자 : Anoop Rai


JavaScript에서 함수를 생성하는 두 가지 방법이 있습니다.

  1. 함수 선언:

     function fn(){ console.log("Hello"); } fn();

    이것은 C 언어 계열의 여러 언어 및 표준에서 사용되는 매우 기본적이고 자명합니다. 정의한 함수를 선언하고 호출하여 실행했습니다.

    당신이 알아야 할 것은 함수는 실제로 JavaScript의 객체라는 것입니다. 내부적으로 우리는 위의 함수에 대한 객체를 생성하고 fn이라는 이름을 지정하거나 객체에 대한 참조가 fn에 저장됩니다. 함수는 JavaScript의 객체입니다. 함수의 인스턴스는 실제로 개체 인스턴스입니다.

  2. 함수 표현:

     var fn=function(){ console.log("Hello"); } fn();

    JavaScript에는 일급 함수가 있습니다. 즉, 문자열이나 숫자를 만들어 변수에 할당하는 것처럼 함수를 만들고 변수에 할당합니다. 여기서 fn 변수는 함수에 할당됩니다. 이 개념의 이유는 함수가 JavaScript의 객체이기 때문입니다. fn은 위 함수의 객체 인스턴스를 가리키고 있습니다. 함수를 초기화하고 변수에 할당했습니다. 함수를 실행하고 결과를 할당하는 것이 아닙니다.

참조: JavaScript 함수 선언 구문: var fn = function() {} 대 function fn() {}



답변자 : Alireza


그것들은 약간의 차이점이 있지만 매우 유사합니다. 첫 번째는 익명 함수에 할당된 변수(Function Declaration)이고 두 번째는 JavaScript에서 함수를 생성하는 일반적인 방법(Anonymous function Declaration)이며, 둘 다 사용법, 단점 및 장점이 있습니다. :

1. 함수 표현

 var functionOne = function() { // Some code };

함수 표현식은 더 큰 표현식 구문(일반적으로 변수 할당)의 일부로 함수를 정의합니다. 함수 표현식을 통해 정의된 함수는 이름을 지정하거나 익명으로 지정할 수 있습니다. 함수 표현식은 "function"으로 시작해서는 안 됩니다(따라서 아래의 자체 호출 예제 주위에 괄호).

함수에 변수를 할당한다는 것은 호이스팅이 없음을 의미합니다. JavaScript의 함수는 호이스트가 가능하다는 것을 알 수 있습니다. 이는 선언되기 전에 호출될 수 있다는 것을 의미하지만 변수에 액세스하기 전에 변수를 선언해야 하므로 이 경우에는 함수가 선언된 위치보다 먼저 함수에 액세스하고 함수를 작성하는 방법일 수도 있습니다. 다른 함수를 반환하는 함수의 경우 이러한 종류의 선언이 의미가 있을 수 있습니다. ECMA6 이상에서도 이것을 화살표 함수에 할당할 수 있습니다. 익명 함수를 호출하는 데 사용할 수 있습니다. 또한 이 선언 방식은 JavaScript에서 생성자 함수를 만드는 더 좋은 방법입니다.

2. 함수 선언

 function functionTwo() { // Some code }

함수 선언은 변수 할당 없이 명명된 함수 변수를 정의합니다. 함수 선언은 독립형 구조로 발생하며 비함수 블록 내에서 중첩될 수 없습니다. 변수 선언의 형제라고 생각하면 도움이 됩니다. 변수 선언이 "var"로 시작해야 하는 것처럼 함수 선언도 "function"으로 시작해야 합니다.

이것은 JavaScript에서 함수를 호출하는 일반적인 방법입니다. JavaScript에서 모든 함수가 호이스트되는 것처럼 선언하기 전에 이 함수를 호출할 수 있지만 'use strict'가 있으면 예상대로 호이스트되지 않습니다. 라인이 크지 않고 생성자 함수도 아닌 모든 일반 함수를 호출합니다.

또한 JavaScript에서 호이스팅이 작동하는 방식에 대한 자세한 정보가 필요하면 아래 링크를 방문하세요.

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting



답변자 : Tao


이것은 함수를 선언하는 두 가지 방법일 뿐이며, 두 번째 방법은 선언 전에 함수를 사용할 수 있습니다.



답변자 : SuperNova


new Function() 을 사용하여 함수의 본문을 문자열로 전달할 수 있습니다. 따라서 이것은 동적 기능을 만드는 데 사용할 수 있습니다. 또한 스크립트를 실행하지 않고 스크립트를 전달합니다.

 var func = new Function("x", "y", "return x*y;"); function secondFunction(){ var result; result = func(10,20); console.log ( result ); } secondFunction()


출처 : Here


출처 : http:www.stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname">

반응형