웹 프론트엔드 JS 튜토리얼 me_javascript 스킬을 통해 자바스크립트 함수와 함수 표현을 배워보세요

me_javascript 스킬을 통해 자바스크립트 함수와 함수 표현을 배워보세요

May 16, 2016 pm 03:32 PM
javascript 기능

1. 함수 선언 및 함수 표현

ECMAScript에서 함수를 생성하는 가장 일반적인 두 가지 방법은 함수 표현식과 함수 선언입니다. ECMA 사양에서는 함수 선언에 식별자(식별자)가 있어야 한다는 한 가지 사항만 명확하기 때문에 이 둘의 차이점은 약간 혼란스럽습니다. )(모든 사람이 흔히 함수 이름이라고 부르는 이름)이며 이 식별자는 함수 표현식에서 생략될 수 있습니다.

함수 선언: 함수 함수 이름(매개변수: 선택){함수 본문}

함수 표현식: 함수 함수 이름(선택 사항) (매개 변수: 선택 사항) { 함수 본문 }

그렇다면 함수명이 선언되지 않았다면 반드시 표현식이어야 한다고 볼 수 있는데, 함수명이 선언되어 있다면 함수 선언인지 함수 표현식인지 어떻게 판단할 수 있을까요? ECMAScript는 문맥에 따라 구별됩니다. function foo(){}가 할당 표현식의 일부인 경우 이는 함수 표현식입니다. function foo(){}가 함수 본문 내에 포함되거나 프로그램 맨 위에 있는 경우입니다. 함수 선언.

function foo(){} // 声明,因为它是程序的一部分
var bar = function foo(){}; // 表达式,因为它是赋值表达式的一部分

new function bar(){}; // 表达式,因为它是new表达式

(function(){
 function bar(){} // 声明,因为它是函数体的一部分
})();

로그인 후 복사

식과 선언 사이에는 매우 미묘한 차이가 있습니다. 우선, 선언이 코드의 마지막 줄에 있더라도 함수 선언이 구문 분석되고 평가됩니다. 동일한 범위의 표현식이 이전에 구문 분석/평가된 경우 다음 예를 참고하세요. 함수 fn은 경고 후에 선언되지만 경고가 실행될 때 fn은 이미 정의되어 있습니다.

alert(fn());

function fn() {
 return 'Hello world!';
}

로그인 후 복사

또 한 가지 주의할 점이 있습니다. 함수 선언은 조건문 내에서 사용할 수 있지만 표준화되어 있지 않습니다. 즉, 환경에 따라 실행 결과가 다를 수 있으므로 이 경우에는 그렇습니다. 함수 표현식을 사용하는 것이 가장 좋습니다. 조건문에는 블록 수준 범위 개념이 없기 때문입니다

// 千万别这样做!
// 因为有的浏览器会返回first的这个function,而有的浏览器返回的却是第二个

if (true) {
 function foo() {
 return 'first';
 }
}
else {
 function foo() {
 return 'second';
 }
}
foo();

// 相反,这样情况,我们要用函数表达式
var foo;
if (true) {
 foo = function() {
 return 'first';
 };
}
else {
 foo = function() {
 return 'second';
 };
}
foo();

로그인 후 복사

함수 선언의 실제 규칙은 다음과 같습니다.

함수 선언은 프로그램이나 함수 본문에만 나타날 수 있습니다. 구문상 블록({ … }) 내부(예: if, while 또는 for 문 내)에 나타날 수 없습니다. 블록은 명령문만 포함할 수 있고 함수 선언과 같은 소스 요소는 포함할 수 없기 때문입니다. 반면, 규칙을 자세히 살펴보면 표현식이 블록에 나타날 수 있는 유일한 방법은 표현식 문의 일부인 경우라는 것을 알 수 있습니다. 그러나 사양에는 표현식 문이 키워드 function으로 시작할 수 없다고 명시되어 있습니다. 이것이 실제로 의미하는 바는 함수 표현식이 명령문이나 블록에 나타날 수 없다는 것입니다(블록은 명령문으로 구성되기 때문입니다).

2. 명명된 함수 표현식

물론 명명된 함수 표현식의 경우에는 이름이 있어야 합니다. 이전 예제 var bar = function foo(){}는 유효한 명명된 함수 표현식이지만 기억해야 할 것이 하나 있습니다. 사양에서는 식별자가 주변 범위 내에서 유효할 수 없다고 규정하고 있으므로 새로 정의된 함수의 범위 내에서만 유효합니다.

var f = function foo(){
 return typeof foo; // function --->foo是在内部作用域内有效
};
// foo在外部用于是不可见的
typeof foo; // "undefined"
f(); // "function"

로그인 후 복사

이것이 필수인데 명명된 함수 표현식은 어떻게 사용하나요? 이름이 왜요?

처음에 말했듯이, 이름을 지정하면 디버깅 프로세스가 더 편리해질 수 있습니다. 왜냐하면 디버깅할 때 호출 스택의 각 항목에 이를 설명하는 고유한 이름이 있으면 디버깅 프로세스가 훌륭해지기 때문입니다. , 느낌이 다릅니다.

팁:여기에 작은 질문이 있습니다. ES3에서 명명된 함수 표현식의 범위 객체는 Object.prototype의 속성도 상속합니다. 즉, 단순히 함수 표현식의 이름을 지정하면 Object.prototype의 모든 속성도 범위에 포함됩니다. 결과는 놀랄 수도 있습니다.

var constructor = function(){return null;}
var f = function f(){
 return construcor();
}
f(); //{in ES3 环境}

로그인 후 복사

이 프로그램은 null을 생성하는 것처럼 보이지만 실제로는 새로운 개체를 생성합니다. 명명된 함수 표현식은 해당 범위에서 Object.prototype.constructor(즉, Object의 생성자)를 상속하기 때문입니다. with 문과 마찬가지로 이 범위는 Object.prototype에 대한 동적 변경의 영향을 받습니다. 다행히 ES5에서는 이 버그가 수정되었습니다.

이 동작에 대한 합리적인 해결책은 함수 표현식과 동일한 이름을 가진 지역 변수를 생성하고 null 값을 할당하는 것입니다. 함수 표현식 선언을 잘못 끌어올리지 않는 환경에서도 var를 사용하여 변수를 다시 선언하면 변수 g가 여전히 바인딩되어 있습니다. 변수 g를 null로 설정하면 중복된 함수를 가비지 수집할 수 있습니다.

var f = function g(){
 return 17;
}
var g =null;

로그인 후 복사

3、调试器(调用栈)中的命名函数表达式

刚才说了,命名函数表达式的真正用处是调试,那到底怎么用呢?如果一个函数有名字,那调试器在调试的时候会将它的名字显示在调用的栈上。有些调试器(Firebug)有时候还会为你们函数取名并显示,让他们和那些应用该函数的便利具有相同的角色,可是通常情况下,这些调试器只安装简单的规则来取名,所以说没有太大价值,我们来看一个例子:不用命名函数表达式

function foo(){
 return bar();
}
function bar(){
 return baz();
}
function baz(){
 debugger;
}
foo();

// 这里我们使用了3个带名字的函数声明
// 所以当调试器走到debugger语句的时候,Firebug的调用栈上看起来非常清晰明了 
// 因为很明白地显示了名称
baz
bar
foo
expr_test.html()
로그인 후 복사

通过查看调用栈的信息,我们可以很明了地知道foo调用了bar, bar又调用了baz(而foo本身有在expr_test.html文档的全局作用域内被调用),不过,还有一个比较爽地方,就是刚才说的Firebug为匿名表达式取名的功能:

function foo(){
 return bar();
}
var bar = function(){
 return baz();
}
function baz(){
 debugger;
}
foo();

// Call stack
baz
bar() //看到了么? 
foo
expr_test.html()

로그인 후 복사

然后,当函数表达式稍微复杂一些的时候,调试器就不那么聪明了,我们只能在调用栈中看到问号:

function foo(){
 return bar();
}
var bar = (function(){
 if (window.addEventListener) {
 return function(){
  return baz();
 };
 }
 else if (window.attachEvent) {
 return function() {
  return baz();
 };
 }
})();
function baz(){
 debugger;
}
foo();

// Call stack
baz
(?)() // 这里可是问号哦,显示为匿名函数(anonymous function)
foo
expr_test.html()

로그인 후 복사

另外,当把函数赋值给多个变量的时候,也会出现令人郁闷的问题:

function foo(){
 return baz();
}
var bar = function(){
 debugger;
};
var baz = bar;
bar = function() { 
 alert('spoofed');
};
foo();

// Call stack:
bar()
foo
expr_test.html()

로그인 후 복사

这时候,调用栈显示的是foo调用了bar,但实际上并非如此,之所以有这种问题,是因为baz和另外一个包含alert(‘spoofed')的函数做了引用交换所导致的。

归根结底,只有给函数表达式取个名字,才是最委托的办法,也就是使用命名函数表达式。我们来使用带名字的表达式来重写上面的例子(注意立即调用的表达式块里返回的2个函数的名字都是bar):

function foo(){
 return bar();
}
var bar = (function(){
 if (window.addEventListener) {
 return function bar(){
  return baz();
 };
 }
 else if (window.attachEvent) {
 return function bar() {
  return baz();
 };
 }
})();
function baz(){
 debugger;
}
foo();

// 又再次看到了清晰的调用栈信息了耶!
baz
bar
foo
expr_test.html()
로그인 후 복사

好的,整个文章结束,大家对javascript的认识又近了一步,希望大家越来越喜欢小编为大家整理的文章,继续关注跟我学习javascript的一系列文章。

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

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

golang 함수에서 새 함수를 동적으로 생성하기 위한 팁 golang 함수에서 새 함수를 동적으로 생성하기 위한 팁 Apr 25, 2024 pm 02:39 PM

Go 언어는 클로저와 리플렉션이라는 두 가지 동적 함수 생성 기술을 제공합니다. 클로저는 클로저 범위 내의 변수에 대한 액세스를 허용하며 리플렉션은 FuncOf 함수를 사용하여 새 함수를 생성할 수 있습니다. 이러한 기술은 HTTP 라우터를 사용자 정의하고 고도로 사용자 정의 가능한 시스템을 구현하며 플러그 가능한 구성 요소를 구축하는 데 유용합니다.

C++ 함수 이름 지정 시 매개변수 순서에 대한 고려 사항 C++ 함수 이름 지정 시 매개변수 순서에 대한 고려 사항 Apr 24, 2024 pm 04:21 PM

C++ 함수 이름 지정에서는 가독성을 높이고 오류를 줄이며 리팩토링을 용이하게 하기 위해 매개변수 순서를 고려하는 것이 중요합니다. 일반적인 매개변수 순서 규칙에는 작업-객체, 개체-작업, 의미론적 의미 및 표준 라이브러리 준수가 포함됩니다. 최적의 순서는 함수의 목적, 매개변수 유형, 잠재적인 혼동 및 언어 규칙에 따라 달라집니다.

Java로 효율적이고 유지 관리 가능한 함수를 작성하는 방법은 무엇입니까? Java로 효율적이고 유지 관리 가능한 함수를 작성하는 방법은 무엇입니까? Apr 24, 2024 am 11:33 AM

효율적이고 유지 관리 가능한 Java 함수를 작성하는 핵심은 단순함을 유지하는 것입니다. 의미 있는 이름을 사용하세요. 특별한 상황을 처리합니다. 적절한 가시성을 사용하십시오.

Excel 함수 수식의 전체 모음 Excel 함수 수식의 전체 모음 May 07, 2024 pm 12:04 PM

1. SUM 함수는 열이나 셀 그룹의 숫자를 합하는 데 사용됩니다(예: =SUM(A1:J10)). 2. AVERAGE 함수는 열이나 셀 그룹에 있는 숫자의 평균을 계산하는 데 사용됩니다(예: =AVERAGE(A1:A10)). 3. COUNT 함수, 열이나 셀 그룹의 숫자나 텍스트 수를 세는 데 사용됩니다. 예: =COUNT(A1:A10) 4. IF 함수, 지정된 조건을 기반으로 논리적 판단을 내리고 결과를 반환하는 데 사용됩니다. 해당 결과.

C++ 함수 기본 매개변수와 가변 매개변수의 장단점 비교 C++ 함수 기본 매개변수와 가변 매개변수의 장단점 비교 Apr 21, 2024 am 10:21 AM

C++ 함수에서 기본 매개변수의 장점에는 호출 단순화, 가독성 향상, 오류 방지 등이 있습니다. 단점은 제한된 유연성과 명명 제한입니다. 가변 매개변수의 장점에는 무제한의 유연성과 동적 바인딩이 포함됩니다. 단점은 더 큰 복잡성, 암시적 유형 변환 및 디버깅의 어려움을 포함합니다.

참조 유형을 반환하는 C++ 함수의 이점은 무엇입니까? 참조 유형을 반환하는 C++ 함수의 이점은 무엇입니까? Apr 20, 2024 pm 09:12 PM

C++에서 참조 유형을 반환하는 함수의 이점은 다음과 같습니다. 성능 개선: 참조로 전달하면 객체 복사가 방지되므로 메모리와 시간이 절약됩니다. 직접 수정: 호출자는 반환된 참조 객체를 다시 할당하지 않고 직접 수정할 수 있습니다. 코드 단순성: 참조로 전달하면 코드가 단순화되고 추가 할당 작업이 필요하지 않습니다.

사용자 정의 PHP 함수와 사전 정의된 함수의 차이점은 무엇입니까? 사용자 정의 PHP 함수와 사전 정의된 함수의 차이점은 무엇입니까? Apr 22, 2024 pm 02:21 PM

사용자 정의 PHP 함수와 사전 정의된 함수의 차이점은 다음과 같습니다. 범위: 사용자 정의 함수는 정의 범위로 제한되는 반면, 사전 정의된 함수는 스크립트 전체에서 액세스할 수 있습니다. 정의 방법: 사용자 정의 함수는 function 키워드를 사용하여 정의되는 반면, 사전 정의된 함수는 PHP 커널에 의해 정의됩니다. 매개변수 전달: 사용자 정의 함수는 매개변수를 수신하지만 사전 정의된 함수에는 매개변수가 필요하지 않을 수 있습니다. 확장성: 필요에 따라 사용자 정의 함수를 생성할 수 있으며 사전 정의된 함수는 내장되어 있어 수정할 수 없습니다.

C++ 함수 예외 고급: 사용자 정의된 오류 처리 C++ 함수 예외 고급: 사용자 정의된 오류 처리 May 01, 2024 pm 06:39 PM

C++의 예외 처리는 특정 오류 메시지, 상황별 정보를 제공하고 오류 유형에 따라 사용자 지정 작업을 수행하는 사용자 지정 예외 클래스를 통해 향상될 수 있습니다. 특정 오류 정보를 제공하려면 std::Exception에서 상속된 예외 클래스를 정의하세요. 사용자 정의 예외를 발생시키려면 throw 키워드를 사용하십시오. try-catch 블록에서 Dynamic_cast를 사용하여 발견된 예외를 사용자 지정 예외 유형으로 변환합니다. 실제 경우 open_file 함수는 FileNotFoundException 예외를 발생시킵니다. 예외를 포착하고 처리하면 보다 구체적인 오류 메시지가 제공될 수 있습니다.

See all articles