JavaScript는 ECMAScript 표준에 따라 설계되고 구현됩니다. 나중에 언급되는 JavaScript 구문은 실제로 ES5 표준을 구현한 것입니다.
먼저 기본 문법은 무엇일까요?
가장 기본적인 문법은 무엇인가요?
거의 모든 언어의 기본 구문은 데이터 유형, 연산자, 제어문, 함수 등 외에는 거의 차이가 없습니다. 여기에 간략한 목록이 있습니다.
5가지 기본 데이터 유형 및 1가지 복합 데이터 유형
JavaScript에는 5가지 기본 데이터 유형이 포함되어 있습니다. 유형은 정의되지 않음 / null / 부울 / 숫자 / 문자열입니다. 이는 5가지 기본 데이터 유형이며 다른 유형은 없습니다!
JavaScript에는 객체 유형인 1개의 복잡한 데이터 유형이 포함되어 있습니다. 객체 유형은 다른 모든 객체의 기본 클래스입니다.
참고: JavaScript는 부동 소수점 숫자와 정수를 구분하지 않으며 모두 숫자로 표시됩니다.
앞서 말씀드린 기본 데이터형 5가지와 여기서 복합 데이터형 1가지, 이게 다 데이터형이에요!
기본 연산자
이건 상식입니다. 무슨 일이 일어나고 있는지 알아두세요.
일반적으로 사용되는 연산자에는 산술 연산자, 관계 연산자, 부울 연산자, 할당 연산자 등이 있습니다.
제어문
이것은 if-else 및 기타 제어문이라고 부르는 것입니다.
if 문, switch 문, for 문, while 문, for-in 문 등 일반적으로 사용되는 문은 많지 않습니다.
기능
함수는 논리의 작은 부분을 캡슐화한 것입니다. 이론적으로 논리는 독립적일수록 좋습니다.
자바스크립트 기능은 다른 언어와 매우 다릅니다. JavaScript 함수는 매개변수와 반환값을 모두 사용할 수 있습니다.
또한 JavaScript 함수는 매개변수를 원하는 만큼 받아들일 수 있으며 이러한 매개변수는 인수 객체를 통해 액세스할 수 있습니다.
모든 언어의 기본 구문은 세부 사항의 일부 차이점을 제외하면 대략 위와 같습니다: 데이터 유형, 연산자, 제어 문, 함수, 모듈 등.
다음에서는 약간 더 복잡한 개념을 소개합니다.
변수, 범위, 메모리 문제
변수
JavaScript 변수는 두 가지 유형으로 나뉩니다. : 기본 유형 및 참조 유형. 기본 유형은 앞서 언급한 5가지 기본 데이터 유형이고, 참조 유형은 앞서 언급한 객체(Object)와 이를 기반으로 하는 기타 복합 데이터 유형이다.
✦ 기본형: 메모리의 실제 크기를 차지합니다. 값을 할당하면 메모리에 새 복사본이 생성됩니다. 스택 메모리에 저장됩니다.
✦ 참조 유형: 객체 자체가 아닌 객체를 가리키는 포인터입니다. 값을 할당할 때 객체를 가리키도록 새 포인터가 생성됩니다. 힙 메모리에 저장됩니다.
가변 메모리 할당
한마디로 기본 유형은 메모리에 있는 실제 값이고 참조 유형은 메모리에 있는 포인터입니다. 객체를 가리키는 경우 여러 참조 유형이 동시에 동일한 객체를 가리킬 수 있습니다.
그럼 특정 변수가 어떤 데이터 유형인지 확인하는 방법은 무엇입니까?
변수가 어떤 기본 유형인지 확인하려면 typeof 연산자를 사용하세요.
변수가 어떤 참조 유형인지 확인하려면 instanceof 연산자를 사용하세요.
이 점을 잊지 마세요!
범위
변수는 특정 범위에서 선언되며 범위에 따라 변수의 수명과 범위가 결정됩니다. 코드는 그 안에 있는 변수에 액세스할 수 있습니다.
JavaScript 범위에는 전역 범위와 함수 범위만 포함되며 블록 수준 범위는 포함되지 않습니다!
스코프를 중첩하여 스코프 체인을 형성할 수 있습니다. 스코프 체인의 존재로 인해 변수 검색은 위쪽으로 추적될 수 있습니다. 즉, 자식 함수는 부모 함수의 범위 => 조상 함수의 범위 => 전역 범위까지 접근할 수 있습니다. 함수는 클로저라고도 하며 나중에 소개됩니다.
var color = "blue"; functionchangeColor() { var anotherColor = "red"; function swapColors() { var tempColor = anotherColor;
anotherColor = color;
color = tempColor; / Color, anotherColor, tempColor는 여기서 접근할 수 있습니다
} // Color, anotherColor는 여기서 접근할 수 있지만 tempColor
는 접근할 수 없습니다. swapColors();
}// color,changeColor()만;
아래 그림과 같이 각 스코프와 중첩 스코프에서 접근 가능한 변수를 위쪽으로 추적할 수 있습니다.
스코프 체인
스코프의 개념은 단순해 보이지만 실제 사용하다 보면 문제점이 많다면, 꼼꼼히 분석해야 합니다.
메모리 문제
JavaScript 엔진에는 자동 가비지 수집 메커니즘이 있어 너무 많은 주의를 기울일 필요가 없습니다. 메모리 할당 및 가비지 수집 문제. 여기서는 더 이상 설명하지 않겠습니다!
참조 유형
앞서 언급했듯이 Object는 유일한 복합 데이터 유형이며 참조 유형은 다음에서 파생됩니다. 개체 유형이 상속됩니다.
✦ Array: 배열 유형
✦ Date: 날짜 유형
✦ RegExp: 정규 표현식 유형, 이에 대해 자세히 알아두면 이점이 있습니다!
✦ 잠깐...
그렇다면 가장 일반적으로 사용되는 함수는 어떤 데이터 유형인가요? 답은 함수형입니다!
야, 뭔가 발견한 것 같은데? 함수는 참조 유형이므로 JavaScript는 참조 유형에 속성과 메서드를 추가할 수 있습니다. 음, 함수도 마찬가지입니다! 여기가 JavaScript 기능이 강력하고 복잡해지는 곳입니다. 즉, 함수는 사용자 정의 메서드와 속성을 가질 수도 있습니다!
또한 JavaScript는 위에서 언급한 5가지 기본 유형 중 3가지인 Boolean, Number 및 String을 참조 유형으로 캡슐화합니다. 그러나 많이 사용되지는 않으므로 이해하기만 하면 됩니다.
그런데, 모든 코드가 실행되기 전에 두 개의 객체, 즉 Global과 Math가 스코프에 내장됩니다. 브라우저의 Global은 window입니다!
지금까지 JavaScript의 기본 개념을 소개했습니다. 함수와 범위는 상대적으로 복잡하지만 다른 개념은 상대적으로 간단합니다.
다음으로 JavaScript의 좀 더 복잡한 개념인 객체 지향을 소개하겠습니다.
객체지향 프로그래밍
JavaScript 자체에는 클래스 및 인터페이스 개념이 없습니다. 실현된 프로토타입을 기반으로 합니다.
단순화를 위해 두 가지 객체 지향 문제만 분석합니다.
✦ 클래스를 정의하는 방법은 무엇입니까?
✦ 클래스 상속 구현 방법
클래스 정의
별다른 얘기 없이 직접 알려드리겠습니다. 생성자 + 프로토타입을 사용하여 클래스를 정의합니다.
생성자를 사용하여 사용자 정의 유형을 만든 다음 new 연산자를 사용하여 클래스의 인스턴스를 만듭니다. 그러나 생성자의 메서드와 속성은 모든 예제에 존재하며 공유할 수 없으므로 소개합니다. 메소드 및 속성 공유를 구현하기 위한 프로토타입.
프로토타입
마지막으로 프로토타입에서 공유해야 할 메서드와 속성을 정의하고 인스턴스에 특정한 메서드와 속성을 생성자. 지금까지 생성자 + 프로토타입을 통해 클래스를 정의했습니다.
//생성자 함수 Person(이름, 나이, 직업) { this.name = name; this.job = job; this.friends = ["Shelby", "Court"];
}// 프로토타입 Person.prototype = {
constructor: Person,
sayName: function() { return this.name;
}
}// 인스턴스화 var person1 = new Person ("Nicholas", 29, "소프트웨어 엔지니어");var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
Alert (person1.friends); falsealert(person1.sayName === person2.sayName); //true 출력
상속 구현
이전 기사에서는 클래스를 정의하는 방법에 대해 설명한 다음 상위 클래스와 하위 클래스를 정의합니다.
상위 클래스에서 하위 클래스를 상속받는 방법은 무엇입니까? 더 이상 고민하지 않고 직접 말씀드리겠습니다. JavaScript는 프로토타입 체인을 통해 상속을 구현합니다!
프로토타입 체인을 구축하는 방법은 무엇입니까? 부모 클래스 인스턴스를 자식 클래스 생성자의 프로토타입에 할당하기만 하면 됩니다. 헷갈리지만 꼭 기억해두세요!
프로토타입 체인 상속
프로토타입 체인을 구축한 후 하위 클래스는 상위 클래스의 모든 속성과 메서드에 액세스할 수 있습니다. 수업 !
// 상위 클래스 function SuperType() { this.property = true;
}
SuperType.prototype.getSuperValue = function() { return this.property;
};// 하위 클래스 function SubType() { this.subproperty = false;
}//하위 클래스는 상위 클래스를 상속합니다 SubType.prototype = new SuperType();//하위 클래스에 새 메서드를 추가합니다 SubType.prototype.getSubValue = function( ) { return this.subproperty;
};//상위 클래스 메소드 재정의 SubType.prototype.getSuperValue = function() { return false;
};//인스턴스화 var 인스턴스 = new SubType();console . log(instance.getSuperValue()); //Output false
객체 지향 지식은 책으로 작성할 수 있습니다. 다음은 가장 기본적이고 일반적으로 사용되는 개념에 대한 간략한 소개입니다.
함수 표현식
JavaScript에서 함수를 정의하는 방법에는 함수 선언과 함수 표현식의 두 가지가 있습니다.
함수 표현식을 사용하면 함수에 이름을 지정할 필요가 없으므로 동적 프로그래밍, 즉 익명 함수가 달성됩니다. 익명 함수를 사용하면 JavaScript 함수가 더욱 강력하게 사용됩니다.
재귀
재귀는 매우 일반적인 알고리즘이며 전형적인 예는 계승입니다. 다른 얘기는 하지 말고 재귀의 모범 사례만 이야기해 보세요. 위 코드는
// 모범 사례, 함수 표현 var Factorial = (function f(num) { if (num <= 1) { return 1;
} else { return num * f(num - 1);
}
});// 단점: // 계승은 수정될 수 있으며 // 결과는 return num * 계승( num - 1) 오류 함수 Factorial(num) { if (num <= 1) { return 1;
} else { return num *factorial(num - 1);
}
}// 단점: // Arguments.callee, 사양에서는 함수 Factorial(num) 사용을 더 이상 사용하지 않습니다. { if (num <= 1) { return 1;
} else { return num *args.callee(num - 1);
}
}
많은 사람들이 여전히 인수.callee 메서드를 사용하고 있습니다. 이것이 가장 좋은 방법입니다.
글쎄요, 많은 사람들이 재귀를 작성하기 어렵다고 생각합니다. 사실 두 단계로 나누어 보면 훨씬 더 명확해질 것입니다.
✦ 경계 조건, 일반적으로 if-else입니다.
✦ 재귀 호출.
이 모드에 따라 몇 가지 고전적인 재귀를 연습하면 익숙해질 것입니다.
클로저
많은 사람들이 클로저가 복잡하고 함정에 빠지기 쉽다고 생각하는 경우가 많지만 그렇지 않습니다.
그럼 클로저란 무엇인가요? 함수가 다른 함수의 범위에 있는 변수에 접근할 수 있다면 전자는 클로저입니다. JavaScript 함수는 함수를 반환할 수 있으므로 당연히 클로저를 만드는 일반적인 방법은 함수 내에 다른 함수를 만드는 것입니다!
부모 함수에 자식 함수를 정의하면 클로저가 생성되고 자식 함수가 부모 함수의 범위에 액세스할 수 있습니다.
우리는 대개 종결에 속기 때문에 종결에 겁을 먹습니다. 특히 인터뷰 질문에 종결이 많이 나올 때는 더욱 그렇습니다.
앞서 클로저의 정의에 대해 언급했고, 클로저를 만드는 방법에 대해서도 언급했습니다. 그렇다면 클로저의 문제점과 해결 방법에 대해 이야기해 볼까요?
/* subFunc를 통해 함수 배열을 반환한 다음 별도로 실행을 호출합니다. */// 함수의 subFunc 배열을 반환하며, 이 함수는 superFunc의 변수에 대한 참조를 갖습니다. // 이는 일반적인 클로저입니다. / 그럼 모직물이 문제인가? // 다시 돌아가서 subFuncs의 함수를 실행하면 우리가 얻는 i는 실제로 항상 10입니다. 왜일까요? // subFuncs를 반환할 때 superFunc의 i=10이므로 // 따라서 subFuncs의 함수가 실행될 때 출력 i는 10입니다. // // 위 내용은 클로저의 가장 큰 함정입니다. 한 문장으로 이해하면: // 상위 함수 변수에 대한 하위 함수의 참조는 상위 함수가 function superFunc() 실행을 마친 후의 변수 상태입니다. { var subFuncs = new Array( ); for (var i = 0; i < 10; i++) {
subFuncs[i] = function() { return i;
};
} return subFuncs ;
}// 그렇다면 매력의 종결 구덩이를 어떻게 해결할 수 있을까요? // 실제로 원리는 매우 간단합니다. 클로저 피트의 본질은 다음과 같습니다. 상위 함수 변수에 대한 하위 함수의 참조는 상위 함수 실행이 완료된 후 변수의 상태입니다. // 그런 다음 해결 방법은 다음과 같습니다. 문제는 다음과 같습니다. 하위 함수가 상위 함수를 참조합니다. 변수 참조, 런타임 상태 사용 // 어떻게 할까요? //함수 표현을 기반으로 자체 실행만 추가합니다. function superFunc() { var subFuncs = new Array(); for (var i = 0; i < 10; i++) {
subFuncs[i] = function(num) { return function() { return num;
};
}(i);
JavaScript 함수의 특수성으로 인해 함수를 반환할 수 있습니다. 함수를 클로저로 반환하면 함수에서 참조하는 상위 함수 변수는 런타임 시 상태가 아니라 상위 함수 실행이 완료된 후의 상태입니다. 이것이 클로저의 가장 큰 함정입니다. 이 함정을 해결하기 위해 우리의 일반적인 방법은 함수 표현식이 자체 실행되도록 만드는 것입니다.
또한 클로저는 조상 함수의 범위를 참조하므로 클로저를 남용할 경우 메모리 문제가 발생합니다.
주로 캡슐화에 관한 것입니다...
캡슐화
클로저는 개인 변수를 캡슐화하거나 블록 수준 범위를 캡슐화할 수 있습니다.
➙ 블록 수준 범위 캡슐화JavaScript에는 블록 수준 범위 개념이 없고 전역 범위와 함수 범위만 있으므로 블록 수준 범위를 만들고 싶다면 클로저를 통해 시뮬레이션할 수 있습니다.
함수를 생성하고 즉시 호출하면 블록 수준 범위가 캡슐화됩니다. 이 함수는 내부의 코드를 즉시 실행할 수 있으며, 내부 변수는 실행 후 즉시 소멸됩니다.
function outputNumbers(count) { // 함수 범위에서 클로저를 사용하여 블록 수준 범위를 캡슐화합니다
// 이 경우 i는 외부에서 사용할 수 없으며 유사한 블록이 있습니다. -level 범위
(function() { for (var i = 0; i < count; i++) {
Alert(i);
})();
경고 (i); //오류 발생! }//전역 범위에서 클로저를 사용하여 블록 수준 범위를 캡슐화합니다.//이런 방식으로 코드 블록은 전역 범위를 오염시키지 않습니다(function() { var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) {
Alert("새해 복 많이 받으세요!");
}
})() ;// 네, 블록 수준 범위 캡슐화의 핵심은 함수 표현 + 자체 실행입니다! (function() { //블록 수준 범위입니다})();
➙ 개인 변수 캡슐화
JavaScript에는 개인 변수 개념이 없으므로 클로저를 사용할 수도 있습니다. 이를 달성하기 위해 공용 메소드는 변수를 숨기고 메소드를 노출하여 개인 변수를 캡슐화합니다.
(function() { //개인 변수 및 개인 함수
} } //Constructor
MyObject = function() {}; //공개/특권 메서드
privateVariable++; return privateFunction();
};
})();
결론적으로 말씀드리자면?
이것은 거의 기본 구문이며 JavaScript의 약간 더 고급 사용법입니다. 실제로 소위 고급은 엔지니어링 요구 사항에 대한 JavaScript의 "미성숙", 특히 객체 지향의 표현이지만 JavaScript 자체는 완벽한 지원이 아닙니다. 다행스럽게도 최신 ES6 표준은 많은 문제를 해결했으며, Babel과 함께 사용할 때 호환성에 대해 크게 걱정할 필요가 없습니다. 초보자라면 바로 ES6+Babel로 가길 권합니다.
✦ JavaScript의 기본은 주로 5가지 기본 데이터 유형, 1가지 복합 데이터 유형, 연산자, 제어문, 함수 등으로 구성됩니다.
✦ 기본 구문을 이해한 후에는 JavaScript 변수, 범위, 범위 체인도 학습해야 합니다.
✦ 공통 참조 유형을 확인하고 동시에 사용할 수 있습니다. 경험해본 사람으로서 더 많은 규칙을 배워서 코딩 실력을 크게 향상시킬 것을 제안합니다.
✦ 객체지향 프로그래밍을 하는 방법은 여러 가지가 있습니다. 생성자 + 프로토타입을 사용하여 클래스를 정의하고, 프로토타입 체인을 사용하여 상속을 구현하는 것만 기억하면 됩니다. 더 많은 확장 기능을 보려면 책을 읽어보세요.
✦ 함수 표현식은 재귀, 종결, 캡슐화 등 몇 가지 흥미로운 결과를 낳습니다. 재귀의 모범 사례, 종결의 정의와 함정, 적용 가능한 종결 시나리오를 기억하세요.
동적 언어인 JavaScript는 다른 언어와 상당히 다르기 때문에 많은 사람들이 JavaScript를 배우기가 어렵습니다. 그런데 지금 이전 글을 보면 비록 간략한 요약이긴 하지만 자바스크립트의 주요 내용이므로 너무 겁먹지 마세요.
한 가지 더, 초보자라면 바로 ES6+Babel로 가보시길 권합니다.
더 많은 JavaScript 지식과 관련 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!