javascript function




var functionName=function(){} 대 function functionName(){} (20)

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

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

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

이는 첫 번째 변형에서 함수가 런타임에 변수 foo 에 할당되기 때문입니다. 두 번째 함수는 구문 분석시 해당 식별자 foo 함수가 할당됩니다.

더 많은 기술 정보

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

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

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

이전 개발자는 함수를 선언하는 두 가지 방법을 사용합니다. 이유가있을 경우 해결할 수 없습니다.

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

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

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


글로벌 문맥에 대해 말하자면, 둘 다 var 문과 FunctionDeclaration 은 전역 객체에서 삭제할 수없는 속성을 만들지 만 둘 다 값을 덮어 쓸 수 있습니다 .

두 가지 방법의 미묘한 차이점은 Variant 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'

FunctionExpression bar 의 할당은 런타임까지 수행됩니다.

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

 function test () {}
 test = null;

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

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

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

또한 선언되지 않은 할당은 엄격 모드 에서 ECMAScript 5에 대해 ReferenceError 를 발생시킵니다.

반드시 읽어야합니다 :

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


다른 의견 제시자는 이미 두 가지 변종의 의미상의 차이점을 이미 다루었습니다. 문체의 차이점을 지적하고자합니다. "할당"변형 만 다른 객체의 속성을 설정할 수 있습니다.

나는 종종 다음과 같은 패턴으로 자바 스크립트 모듈을 만든다 :

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

    exports.publicUtil = function() {
            ...
    };

    return exports;
})();

이 패턴을 사용하면 개인 함수가 선언을 사용하는 동안 공용 함수는 모두 할당을 사용합니다.

(선언문에는 문장 뒤에 세미콜론이 필요하며 선언문에서는 금지되어 있습니다.)


다음은 기능을 만드는 표준 양식에 대한 요약입니다. (원래 다른 질문으로 작성되었지만 정식 질문으로 옮겨지면서 적용되었습니다.)

자귀:

빠른 목록 :

  • 함수 선언

  • "익명" function 표현식 (이 용어에도 불구하고 때때로 이름을 가진 함수 작성)

  • 명명 된 function

  • 액세서 기능 초기화 프로그램 (ES5 +)

  • Arrow Function Expression (ES2015 +) (익명 함수 식과 마찬가지로 명시 적 이름을 사용하지 않지만 이름을 가진 함수를 만들 수 있음)

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

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

함수 선언

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

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

함수 선언은 선언입니다 . 이것은 진술이나 표현이 아닙니다. 따라서, 당신은 그것을 따르지 않습니다 ; (그렇게해도 무해 함).

함수 선언은 단계별 코드가 실행 되기 전에 실행이 컨텍스트에 들어가면 처리됩니다. 생성하는 함수에는 적절한 이름 (위의 예제에서 x 이 주어지며 그 이름은 선언이 나타나는 범위에 놓입니다.

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

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

ES2015가 나오기 전까지 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는 종종 자바 스크립트 구현을위한 버그의 원천이었습니다. 예를 들어, 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 * 2map() 호출에 숨어있는 것을 보시나요? 그것은 함수입니다.

화살표 기능에 대한 몇 가지 :

  1. 그들은 자신의 것을 가지고 있지 않습니다. 대신, 그들은 정의 된 컨텍스트 this 부분을 닫습니다 . (또한 arguments 과 관련하여 super 닫습니다.) 즉, 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() {
    }
};

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 에 대한 것입니다.


먼저 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 를 사용하는 것인데, 비교적 길며 엄격 모드에서는 지원되지 않습니다.)

자바 스크립트는 두 구문을 다르게 처리합니다. 함수 선언입니다.

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() 의 경우에는 - 대답은 다음과 같습니다. 브라우저에 따라 다릅니다.


은 자신에게 내부 참조로 사용할 수 있도록 지정된 함수의 이름을 지정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." );

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

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

// TypeError: functionOne is not a function
functionOne();

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

그리고, 함수 선언 :

// Outputs: "Hello!"
functionTwo();

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

이는 또한 함수 선언을 사용하여 조건부로 함수를 정의 할 수 없다는 것을 의미합니다.

if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

위의 코드는 실제로 test 의 값에 상관없이 functionThree 정의 functionThree use strict 하지 않으면 오류가 발생합니다.


"명명 된 함수는 스택 추적에 표시됩니다"라는 주장에 비추어서, 최신 JavaScript 엔진은 실제로 익명의 함수를 표현할 수 있습니다.

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

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

정말 반복자와 성공 콜백이 추적에 나타나기를 원한다면, 그것들을 지정할 수도 있습니다 ...

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

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

하네스 ( Fiddle )

'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 e.i (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:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
[email protected]://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: j
Trace:
[email protected]://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: l
Trace:
[email protected]://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:
[email protected]://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: p
Trace:
[email protected]://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 e.i (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[email protected]://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
[email protected]://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: j
Trace:
[email protected]://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: l
Trace:
[email protected]://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: n
Trace:
[email protected]://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: p
Trace:
[email protected]://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

Hoisting 은 모든 변수 및 함수 선언을 현재 범위의 맨 위로 이동시키는 JavaScript 인터프리터의 동작입니다.

그러나 실제 선언 만 올립니다. 과제가있는 곳을 떠나서

  • 변수 / 함수는 페이지 내에서 전역 변수로 선언되어 해당 페이지의 아무 곳이나 액세스 할 수 있습니다.
  • 변수의 / 함수 안에 선언 된 함수는 로컬 범위를가집니다. 함수 본문 (범위) 내에서 사용 가능 / 액세스됨을 의미하지만 함수 본문 외부에서는 사용할 수 없습니다.

Variable

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';
}
  • 페이지 내에서 선언 된 함수는 전역 액세스 권한이있는 페이지의 상단으로 끌어 올려집니다.
  • 함수 블록 내에서 선언 된 함수는 블록의 상단으로 끌어 올려집니다.
  • 함수의 디폴트 반환 값은 ' undefined '이고, Variable 선언의 디폴트 값 역시 '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

실적 정보 :

최신 버전의 V8여러 후드 최적화 가 도입되었으며 그와 동시에 수행되었습니다 SpiderMonkey.

표현과 선언 사이에는 거의 차이점이 없습니다.
함수 표현식 이 빨라 졌습니다.

Chrome 62.0.3202

파이어 폭스 55

Chrome Canary 63.0.3225


Anonymous함수 표현식 Named 함수 표현식 에 대해 더 나은 성능을 갖는 것처럼 보입니다 .


Firefox 크롬 카나리아 크롬


JavaScript에서는 함수를 만드는 두 가지 방법이 있습니다.

  1. 함수 선언 :

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

    이것은 매우 기본적이고 자명하며 C 언어 계열의 여러 언어와 표준으로 사용됩니다. 우리는 정의 된 함수를 선언하고 그것을 호출하여 실행했습니다.

    당신이 알아야 할 것은 함수가 실제로 자바 스크립트의 객체라는 것입니다. 내부적으로 위의 함수를위한 객체를 생성하고 fn이라는 이름을 주거나 객체에 대한 참조를 fn에 저장합니다. 함수는 JavaScript의 객체입니다. 함수의 인스턴스는 실제로는 객체 인스턴스입니다.

  2. 함수 표현식 :

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

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

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


그것들은 약간의 작은 차이점과 꽤 유사합니다. 첫 번째 변수는 익명 함수 (Function Declaration)에 할당 된 변수이고 두 번째는 JavaScript (Anonymous function Declaration)에서 함수를 만드는 일반적인 방법입니다. 둘 다 용법, 단점 및 전문가가 있습니다. :

1. 함수식

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

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

함수에 변수를 지정하면 호이팅을 의미하지 않습니다. 자바 스크립트의 함수는 호이스트를 호출 할 수 있기 때문에 호명 할 수 있습니다. 선언되기 전에 호출 될 수 있으며, 변수는 변수에 액세스하기 전에 선언되어야하므로이 경우에는 함수를 선언하기 전에 함수에 접근 할 수 있습니다. 또한 함수를 작성하는 방법이 될 수 있습니다. 다른 함수를 반환하는 함수의 경우 이러한 종류의 선언은 ECMA6 & 위에서도 화살표 함수에 할당 할 수 있습니다. 익명 함수를 호출하는 데에도 사용할 수 있습니다.이 선언 방법은 JavaScript로 생성자 함수를 만드는 더 좋은 방법입니다.

2. 기능 선언

function functionTwo() {
    // Some code
}

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

이것은 JavaScript에서 함수를 호출하는 일반적인 방법입니다.이 함수는 JavaScript에서와 같이 모든 함수가 Hoisted로 선언되기 전에 호출 될 수 있습니다. 그러나 'strict use'를 사용하면 예상대로 호이스트되지 않습니다. 좋은 방법입니다. 라인이 크지 않고 생성자 함수도 아닌 모든 일반 함수를 호출합니다.

또한 JavaScript에서 호이 스팅이 어떻게 작동하는지에 대한 자세한 정보가 필요하면 아래 링크를 방문하십시오.

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


다른 답변에서 언급되지 않은 또 다른 차이점은 익명의 함수를 사용하면

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.


매우 구체적인 이유 때문에 변수 접근법을 사용합니다. 이론은 위의 추상적 인 방식으로 다루었지만 제한된 JavaScript 전문 지식을 가진 일부 사용자는 나를 좋아할 수 있습니다.

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

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

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

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

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


아래 나열된 두 가지 기능 선언 사이에는 세 가지 주목할만한 비교가 있습니다.

  1. 함수의 가용성 (범위)

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

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

function add(a, b){
  return a + b;
}

다음은 작동하지 않습니다 ( var add=superseeds 때문에 function add()).

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

var add=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;
}

  1. (함수) .name

이런 식으로 선언 할 때 함수의 이름 function thefuncname(){}thefuncname 입니다.

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. 공연

구글의 V8과 파이어 폭스의 스파이더 맨키에서는 수십 마이크로 초 JIST 컴파일 차이가있을 수 있지만 결과는 완전히 동일하다. 이를 증명하기 위해 두 개의 빈 코드 스 니펫의 속도를 비교하여 마이크로 벤치 마크에서 JSPerf의 효율성을 검토합시다. JSPerf 테스트는 여기에서 발견된다 . 그리고 jsben.ch 테스트가 여기에서 발견되었습니다 . 보시다시피, 없어야 할 때 눈에 띄는 차이가 있습니다. 만약 당신이 정말로 나 같은 퍼포먼스 괴물이라면, 범위 내에서 변수와 함수의 수를 줄이는 것과 동시에 다형성 (특히 두 변수를 저장하기 위해 같은 변수를 사용하는 것)을 제거하는 동안 가치가있을 것입니다.

"가장 가까운 차단"이란 무엇인가?

"가장 가까운 블록"은 가장 가까운 "함수"(비동기 함수, 생성기 함수 및 비동기 생성기 함수 포함)입니다. 그러나 흥미롭게도 a 는 클로저 외부의 항목에 대해 클로저 블록이 아닌 경우 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;
    }
})();


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

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

이러한 함수를 사용하여 객체를 만드는 경우 다음을 얻습니다.

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

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

function abc(){}

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

var abc = function() {};

주요 차이점은 그들이 어떻게 끌어 올리는가 (들어 올려서 선언 한 것)입니다. 첫 번째 예에서는 전체 함수 선언이 올라갑니다. 두 번째 예제에서는 var 'abc'만 올리고 값 (함수)은 정의되지 않으며 함수 자체는 선언 된 위치에 그대로 있습니다.

간단히 말하면 다음과 같습니다.

//this will work
abc(param);
function abc(){}

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

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


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

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

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

역사적으로 익명 함수는 JavaScript가 언어로 명명되지 않아서 명명 된 함수로 멤버를 나열 할 수 없었기 때문에 나타났습니다.

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

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

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

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

그 이유는 첫 번째 행에서 functionOne에 값이 지정되지 않으므로 정의되지 않았기 때문입니다. 우리는 그것을 함수로 부르려고 노력하고 있으므로 오류가 발생합니다.

두 번째 줄에서는 functionOne에 익명 함수 참조를 지정합니다.

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

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






idioms