여기서 "피트"라는 단어는 "함정"을 의미합니다. JavaScript의 "약한 언어" 특성으로 인해 사용 중에는 매우 느슨하고 유연하지만 이러한 함정에 빠지기 쉽습니다. 숨겨져 있으므로 JS를 배우고 적용하는 과정이 순조롭게 진행될 수 있도록 눈을 크게 뜨고 있어야 합니다
1. 전역변수
자바스크립트는 함수를 통해 범위를 관리합니다. 함수 내부에 선언된 변수는 함수 내부에서만 사용할 수 있고 함수 외부에서는 사용할 수 없습니다. 반면, 전역 변수는 함수 외부에서 선언되거나 선언되지 않고 단순히 사용되는 변수입니다.
"선언 없이 단순 사용"이란 var 키워드를 사용하지 않고 변수를 선언하는 것을 의미합니다. 우리는 이미 이것을 잘 알고 있습니다. 암시적으로 전역 변수를 생성하지 않는 방법은 변수를 선언할 때 var 키워드를 사용하는 것입니다.
그런데 var를 사용해도 괜찮다고 생각하시나요? 이 피트를 살펴보겠습니다.
function foo() {
var a = b = 0;
// 본문...
}
두 개의 지역 변수를 예상했을 수도 있지만 b는 실제 전역 변수입니다. 왜죠? 할당 작업은 오른쪽에서 왼쪽으로 진행되므로 다음과 같습니다.
function foo() {
var a = (b = 0);
// 본문...
}
그래서 b는 전역 변수입니다.
구멍 채우기: 변수 선언은 하나씩 하는 것이 가장 좋으며, 도매는 하지 마세요~_~;
2. 변수 선언
먼저 함정을 살펴보겠습니다:
myName = "global";
function foo() {
Alert(myName);
var myName = "local" ";
Alert(myName);
}
foo();
얼핏 보면 두 경고의 결과가 "전역" 및 "로컬"일 것으로 예상됩니다. "이지만 실제 결과는 "정의되지 않음" 및 "로컬"입니다. 왜 그럴까요? 변수가 동일한 범위(동일한 함수)에 있기 때문에 선언이 범위의 맨 위로 올라가서 먼저 구문 분석됩니다.
위 코드 조각의 실행 동작은 다음과 같습니다.
function foo() {
var myName;
경고(myName); // "정의되지 않음"
myName = "local";
경고(myName); // "local"
}
다른 피트를 사용하여 사전 구문 분석을 실제로 이해했는지 테스트하세요.
if (!("a" in window)) {
var a = 1;
}
alert (a);
변수 선언은 코드 상단으로 진행되며 아직 값이 할당되지 않았습니다. 다음으로 if 문을 입력합니다. 윈도우의 판단 조건 "a"가 성립되었으므로(a가 전역 변수로 선언됨) 판단 문 평가 결과가 false이므로 if 문이 직접 점프됩니다. a의 값은 정의되지 않았습니다.
var a; 🎜>console .log("a" in window); // true
if (!("a" in window)) {
var a = 1; // 실행하지 않음
}
alert(a); // "정의되지 않음"
변수 선언을 채우십시오. 변수 선언이 불가능한 변수의 경우 수동으로 배치하는 것이 가장 좋습니다. 현재 할당된 값은 먼저 선언한 후 값을 할당하는 방식을 채택할 수 있습니다.
3. 함수 선언
함수 선언도 범위의 최상위로 진행되어 표현식과 문보다 먼저 구문 분석되고 평가됩니다.
alert(typeof foo); // "function"
function foo() {
// 본문...
}
비교 가능:
코드 복사 코드는 다음과 같습니다.
alert(typeof foo); // "정의되지 않음"
var foo = function () {
// 본문...
};
이 진리를 깨달은 후에도 여전히 다음과 같은 함정에 빠지겠습니까?
function test() {
경고 ("1");
}
test();
function test() {
Alert("2");
}
테스트( );
위의 코드 조각을 실행하면 두 개의 팝업 창이 각각 "1"과 "2"가 아닌 이유는 무엇입니까? 간단합니다. test() 이전에 test 선언이 구문 분석되므로 후자가 전자를 재정의하므로 두 실행의 결과는 "2"입니다.
구멍 채우기: 대부분의 경우, 특히 일부 명령문 블록에서는 함수 선언 대신 함수 표현식을 사용합니다.
4. 함수 표현식
먼저 명명된 함수 표현식을 살펴보겠습니다. 물론 이름이 있어야 합니다. 예:
var bar = function foo() {
// body...
};
함수 이름은 해당 함수 내부에서만 표시된다는 점에 유의하세요. 다음과 같은 함정이 있습니다.
var bar = function foo() {
foo(); // 정상 작동
};
foo() // 오류: ReferenceError
구멍 채우기: 명명된 함수 표현식을 가능한 한 적게 사용하고(일부 재귀 및 디버깅 목적 제외) 외부에서 함수 이름을 사용하지 마십시오.
5. 함수 자체 실행
함수 표현식의 경우 뒤에 ()를 추가하면 자체 실행이 가능하며, 괄호 안에 매개변수를 전달할 수 있지만 함수 선언은 불가능합니다. . 함정:
// (1) 이것은 함수 호출이 아닌 그룹화 연산 기호일 뿐입니다!
// 따라서 여기 함수는 실행되지 않았으며 여전히 명령문입니다
function foo(x) {
Alert(x);
}(1);
다음 코드 조각은 각각 실행 중에 팝업 창에 "1"이 표시됩니다. (1) 앞의 모든 내용은 함수 표현식이므로 여기서 ()는 그룹화 연산자가 아니라 호출 실행을 나타내는 연산자입니다.
// 표준 익명 함수 표현식
var bar = function foo(x) {
Alert(x);
}(1);
// 이전 ()는 함수 선언을 표현식으로 변환합니다
(function foo(x) {
Alert(x);
})(1);
// 전체 ()는 표현식
(function foo(x) {
Alert(x)입니다. ;
}(1));
// 새로운 표현식
새로운 함수 foo(x) {
Alert(x);
}(1);
// &&, ||, !, , -, ~ 연산자(및 쉼표), 함수 표현식과 함수 선언의 구분
// 따라서 파서가 그 중 하나가 이미 표현식이고 나머지는 모두 기본값이라는 것을 알게 되면 to 표현식
true && function foo(x) {
Alert(x);
}(1);
채우기 구덩이: 이 구덩이 핵심은 다양한 함수 표현
6. 루프의 클로저
다음은 일반적인 함정을 보여줍니다.
문서 아래 링크를 클릭하면 해당 시퀀스의 번호를 표시합니다
< ;ul>
링크 #0 링크 #1 링크 #2 링크 #3 링크 #4
varlinks=document.getElementsByTagName("ul")[ 0].getElementsByTagName("a");
for (var i = 0, l =links.length; i < l; i ) {
links[i].onclick = 함수(e ) {
e.preventDefault();
Alert("링크 #을 클릭하세요." i);
}
}
解释一下无: 循环内的匿名函数表达式, 保持了对外毹变weight에 대한 当 Alert 被调用时, 俤时循环已结束,i被修改为 “5” 。
填坑:为了得到想要的结果,需要在每次循环中创建变weight i 的拷贝。以下演示正确的做法:
Document 아래 링크를 클릭하면 문서 개수가 표시됩니다. 해당 시퀀스