>  기사  >  웹 프론트엔드  >  JavaScript_javascript 기술에서 함수 선언과 함수 표현의 차이점에 대한 간략한 분석

JavaScript_javascript 기술에서 함수 선언과 함수 표현의 차이점에 대한 간략한 분석

WBOY
WBOY원래의
2016-05-16 16:07:261017검색

텐센트에서 인턴으로 면접을 했을 때 면접관이 저에게 이런 질문을 했던 기억이 납니다.

코드 복사 코드는 다음과 같습니다.

//다음 두 선언 방법의 차이점은 무엇입니까

함수 foo(){};

var bar = 함수 foo(){}; 

처음에는 함수 선언과 함수 표현식이라는 두 가지 선언 방법만 알고 있었는데 구체적인 차이점을 설명할 수 없었습니다. 최근에 우연히 이 주제에 관한 책을 보게 되었는데, 그 내용을 요약하고 싶었습니다.

ECMAScript에는 함수 객체를 생성하는 데 가장 일반적으로 사용되는 두 가지 방법, 즉 함수 표현식을 사용하거나 함수 선언을 사용하는 방법이 있습니다. 이와 관련하여 ECMAScript 사양에서는 함수 선언에는 항상 식별자(Identifier)가 있어야 하며, 이를 함수 이름이라고 부르며, 함수 표현식은 생략할 수 있음을 분명히 하고 있습니다.

함수 선언:

코드 복사 코드는 다음과 같습니다.

함수 식별자(FormalParameterList opt){ FunctionBody }

함수 선언 파싱 과정은 다음과 같습니다.

 1. 새로운 Function 객체를 생성하고, FormalParameterList는 매개변수를 지정하고, FunctionBody는 함수 본문을 지정합니다. 현재 실행 중인 환경의 범위 체인을 범위로 사용합니다.

 2. 값이 Result(1)인 현재 변수 객체에 대해 Identifier라는 속성을 생성합니다.

함수 표현:

(함수식은 익명함수식과 명명함수식으로 구분됩니다)

코드 복사 코드는 다음과 같습니다.

function Identifier opt(FormalParameterList opt){ FunctionBody } //여기에 명명된 함수 표현식이 있습니다

이름이 지정된 함수 표현식의 구문 분석 과정은 다음과 같습니다.

1. 새 개체 만들기
2. 스코프 체인의 상단에 Result(1)을 추가하세요
3. 새 Function 객체를 생성하고, FormalParameterList에 매개변수를 지정하고, FunctionBody에 함수 본문을 지정합니다. 현재 실행 중인 실행 환경의 범위 체인을 범위로 사용합니다.
4. Result(1)에 대해 Identifier라는 속성을 생성합니다. 해당 값은 Result(3)이고 읽기 전용이며 삭제할 수 없습니다.
5. 범위 체인에서 Result(1)
을 제거합니다. 6. 반품 결과(3)

공식 문서는 읽기가 매우 어렵습니다. 간단히 말해서 ECMAScript는 컨텍스트를 통해 둘을 구별합니다. function foo(){}가 할당 표현식의 일부인 경우 함수 표현식으로 간주됩니다. 그리고 function foo(){}가 함수 본문 내에 포함되어 있거나 프로그램의 최상위 수준에 있는 경우 함수 선언으로 구문 분석됩니다. 분명히 식별자가 생략되면 "표현식"은 표현식만 될 수 있습니다.

코드 복사 코드는 다음과 같습니다.

function foo(){}; // 프로그램의 일부이므로 선언

var bar = function foo(){}; // 할당 표현식(AssignmentExpression)의 일부이기 때문에 표현식

new function bar(){}; // 표현식, New 표현식(NewExpression)의 일부이기 때문입니다

(함수(){
Function bar(){}; // 함수 본문(FunctionBody)의 일부이기 때문에 선언
})();

또 다른 상황이 있습니다:

코드 복사 코드는 다음과 같습니다.

(함수 foo(){})

이 경우도 괄호로 묶인 함수인 함수 표현식입니다. 문맥상 ()는 그룹화 연산자를 구성하며 그룹화 연산자는 표현식만 포함할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

function foo(){}; // 함수 선언

(function foo(){}); // 함수 표현식: 그룹화 연산자에 포함됩니다

시도해보세요 {
(var x = 5); // 그룹화 연산자는 표현식만 포함할 수 있고 문은 포함할 수 없습니다. (var 여기서는 문입니다.)
}
잡기(err) {
// SyntaxError ("var x = 5"는 표현식이 아니라 명령문이기 때문에 - 표현식을 평가하면 값을 반환해야 하지만 명령문을 평가한다고 해서 반드시 값이 반환되는 것은 아닙니다. - 번역
}

함수 선언과 함수 표현식의 유사점과 차이점에 대해 간략하게 이야기해 보겠습니다. 선언과 표현식의 동작에는 미묘하면서도 중요한 차이가 있습니다.

먼저 함수 선언을 분석하고 평가합니다. 그 전에 표현식을 분석하고 평가합니다. 선언이 소스 코드의 마지막 줄이더라도 동일한 범위의 첫 번째 표현식보다 먼저 평가됩니다. 예를 보면 이해하기가 더 쉽습니다. 다음 예에서는 경고 후에 fn 함수가 선언됩니다. 그러나 경고가 실행되면 fn이 이미 정의되어 있습니다.

코드 복사 코드는 다음과 같습니다.

Alert(fn()); //Helloworld를 출력합니다

함수 fn() {
'Helloworld!'를 반환합니다.
}


간단히 요약하자면 차이점이 무엇인가요?

1. 선언은 항상 범위 시작 부분에서 구문 분석됩니다. 2. 표현식은 마주칠 때만 평가됩니다.

함수 선언에는 또 다른 중요한 특징이 있습니다.

즉, 조건문을 통해 함수 선언을 제어하는 ​​동작이 표준화되어 있지 않으므로 환경에 따라 다른 결과를 얻을 수 있습니다. 즉,

코드 복사 코드는 다음과 같습니다.
// 절대 하지 마세요!
// 브라우저마다 다른 결과가 반환됩니다.

if (참) {
함수 foo() {
'첫 번째'를 반환합니다.
}
}
그렇지 않으면 {
함수 foo() {
'두 번째'를 반환합니다.
}
}
foo();


// 이 경우에는 함수 표현식을 사용해야 합니다.
var foo;
if (참) {
foo = 함수() {
'첫 번째'를 반환합니다.
};
}
그렇지 않으면 {
foo = 함수() {
'두 번째'를 반환합니다.
};
}
foo();

그렇다면 함수 선언을 사용하는 실제 규칙은 무엇입니까?

FunctionDeclaration은 Program 또는 FunctionBody에만 나타날 수 있습니다. 구문상 블록({ ... }) 내부(예: if, while 또는 for 문 내)에 나타날 수 없습니다. Block은 State만 포함할 수 있고 FunctionDeclaration과 같은 SourceElement는 포함할 수 없기 때문입니다.

반면에 생성 규칙을 자세히 살펴보면 표현식이 블록에 나타나는 유일한 방법은 이를 ExpressionStatement의 일부로 만드는 것임을 알 수 있습니다. 그러나 사양에는 ExpressionStatement가 키워드 function으로 시작할 수 없다고 명시되어 있습니다. 이것이 실제로 의미하는 바는 FunctionExpression이 명령문이나 블록에 나타날 수 없다는 것입니다(블록은 명령문으로 구성되어 있다는 점을 잊지 마십시오).

위의 제한으로 인해 함수가 블록에 나타날 때마다(위의 예와 같이) 실제로는 함수 선언이나 표현식이 아닌 구문 오류로 처리되어야 합니다.

 

 그렇다면 함수 선언이나 함수 표현식은 언제 사용해야 할까요? 함수 선언은 "프로그램 코드"에만 나타날 수 있습니다. 즉, 해당 정의는 변수나 속성에 할당되거나 다음 함수 호출에서 매개 변수로 전달될 수 없습니다. 예를 들어 함수 선언의 허용된 사용은 foo(), bar() 및 local()이 모두 함수 선언 모드를 통해 선언되는 것입니다.

코드 복사 코드는 다음과 같습니다.
//글로벌 환경
함수 foo() {}

함수 로컬() {
// 로컬 환경
함수 표시줄() {}
         반환 표시줄
}

함수 선언을 구문적으로 사용할 수 없는 경우 함수 표현식을 사용할 수 있습니다. 예: 함수를 매개변수로 전달하거나 객체 리터럴에서 함수를 정의합니다.


코드 복사 코드는 다음과 같습니다.

// 익명 함수 표현식입니다
callMe(함수 () {

//함수를 매개변수로 전달
})

// 명명된 함수 표현식입니다
callMe(function me() {

// 함수를 매개변수로 전달합니다. 함수 이름은 me
})

// 기타 함수 표현식
var myobject = {
말하기: 함수 () {

// 나는 함수 표현식이다
}
};
제 지식이 부족해서 틀린 부분이 있으면 정정해주세요.

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