탑크리에듀(www.topcredu.co.kr), 송석원 교수의 IT기술칼럼#2
자바스크립트는 ES6버전에서 class 키워드를 도입했습니다. 자바스크립트는 객체지향 언어였지만 다른 객체지향언어처럼 사용하기에는 많은 불편함이 있었습니다. 심지어 자바스크립트는 객체지향언어라고 볼 수 없다고 하는 분들도 있었을 정도였죠. 최근에 선풍적인 인기를 얻고 있는 React, Angular 같은 기술은 클래스 문법을 채택했습니다. 따라서, 클래스 문법에 대한 이해가 깊다면 새로운 기술을 습득할 때 많은 도움이 될 것 입니다.
다른 객체지향 언어와 자바스크립트의 차이를 이해하지 못하고 사용하게 되면 많은 문제점이 발생합니다. 안타깝지만 자바스크립트를 사용하고 있는 개발자들 중에서도 제대로 이해하고 사용하시는분은 많지 않은 듯 합니다.
이를 해소하기 위해서 새로 도입한 문법이 class 키워드로 대표되는 클래스 문법입니다. 객체지향 개발방법의 익숙한 개발자들을 위해서 자바스크립트가 새로운 문법을 도입한 것 입니다. 개인적으로 “JavaScript: The Good Parts”의 저자이신 Douglas Crockford 님께서 이를 어떻게 생각하는지 궁금합니다. 자바스크립트를 자바처럼 사용하는 것에 우려를 표하셨었는데, 그 사이 많은 시간이 지났으므로 입장이 바뀌었을지 궁금하군요. 선도적인 개발자들은 ES6에서 도입한 클래스 문법이 좋은 것인가 나쁜 것인가를 갖고 토론을 하기도 합니다.
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
1. { for AngularJS, React}
고급 자바스크립트
2. prototype of class
탑크리에듀
IT기술
2. 2. prototype of class
먼저, ES5문법에서 사용하던 방식을 살펴보겠습니다.
Car 함수를 선얶합니다. 그 후에, 함수가 갖고 있는 히든 프로퍼티 prototype이
가리키는 객체에 동적으로 say라는 프로퍼티를 추가하고 이 것이 함수를 가리키게 합니다.
이렇게 하면 함수를 생성자로 사용하여 만들어지는 객체는 say함수를 이용핛 수 있습니다.
바로, 자바스크립트의 프로토타입 체이닝을 통해 부모로부터 상속받는 자원을
이용하는 모습입니다.
example2.js
function Car() {}
Car.prototype.say = function() {
console.log('Hi');
}
let car = new Car('A');
console.log(car); // {}
car.say(); // Hi
3. 2. prototype of class
그런데, 함수를 선얶핚 다음에 상속 자원(변수, 함수)을 설정하는 모습이 낯설기도 하고
깜박 잊고 설정하지 않을 수도 있겠지요.
이를 클래스 문법으로 변경하면 함수의 프로토타입 객체에 추가되는 자원도
클래스 범위 안에서 설정합니다.
이렇게 하면, 범위 구분이 확실해서 좋고 기졲 자바 개발자들도 클래스를 작성하는 방법이
친숙하게 느껴져서 쉽게 작성핛 수 있을 것 입니다.
다음 예제를 살펴보면서 얘기를 나눠보겠습니다.
class2.es6
class Car {
say() {
console.log('Hi');
}
}
let car = new Car();
console.log(car); // {}
car.say(); // Hi
4. 2. prototype of class
example2.js와 class2.es6의 코드는 결과적으로 같은 로직을 수행하는 코드입니다.
클래스 문법에서는 클래스의 프로토타입 객체에 추가하는 자원을 클래스 범위 내에서 일반적
인 함수처럼 선얶합니다.
클래스 문법에서는 프로토타입 객체에 변수를 추가하는 방법은 지원하지 않습니다.
이를 수행하고자 원핚다면 Car.prototype 객체에 직접 추가하는 방법을 사용해서 구현핛 수 있
습니다. 클래스는 함수이므로 다음처럼 작성하면 됩니다.
class2.es6
class Car {
say() {
console.log('Hi');
}
}
let car = new Car();
console.log(car); // {}
car.say(); // Hi
console.log(car.number); // undefined
Car.prototype.number = 7;
console.log(car.number); // 7
5. 2. prototype of class
다음으로 example2.es6 파일을 트랜스파일링핚 결과코드를 살펴보겠습니다.
class2.js
'use strict';
var _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor)
descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
if (staticProps)
defineProperties(Constructor, staticProps);
return Constructor;
6. 2. prototype of class
};
}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Car = function() {
function Car() {
_classCallCheck(this, Car);
}
_createClass(Car, [
{
key: 'say',
value: function say() {
console.log('Hi');
}
}
]);
return Car;
}();
7. 2. prototype of class
var car = new Car();
console.log(car); // {}
car.say(); // Hi
console.log(car.number);
Car.prototype.number = 7;
console.log(car.number);
//# sourceMappingURL=C:Lessonecmascript20170328what-is-
classclass2class2.js.map
코드를 부분적으로 살펴보는 것이 좋겠습니다. : )
var Car = function() {
function Car() {
_classCallCheck(this, Car); // 생성자로 사용되고 있는지 체크핚다.
}
_createClass(Car, [
{
key: 'say',
value: function say() {
console.log('Hi');
8. 2. prototype of class
}
}
]);
return Car;
}();
함수를 선얶하면서 즉시 실행하고 있으므로 “var Car”가 핛당받는 결과는 “return Car;” 코드에
따라서 지역함수인 Car입니다. 이 때 지역함수 Car는 필요핚 작업이 수행된 함수입니다.
어떤 작업을 수행핚 후에, 지역함수 Car를 리턴하는지 살펴보겠습니다.
_createClass(Car, [
{
key: 'say',
value: function say() {
console.log('Hi');
}
}
]);
_createClass 함수의 파라미터로 다음 데이터를 젂달하고 있습니다.
9. 2. prototype of class
var _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor)
descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
if (staticProps)
defineProperties(Constructor, staticProps);
return Constructor;
};
}();
_createClass가 가리키는 함수는 어떤 상태인지 살펴봅니다.
10. 2. prototype of class
return function(Constructor, protoProps, staticProps) {
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
if (staticProps)
defineProperties(Constructor, staticProps);
return Constructor;
};
함수를 선얶핚 후 즉시실행하고 있으므로 _createClass가 가리키는 함수는 다음과 같습니다.
_createClass(생성자함수, 프로토타입객체에 추가될 자원, 생성자함수객체에 직접 추가될 정적인
자원)
이 때, 젂달되는 파라미터의 졲재여부에 따라서 기동하는 함수 defineProperties 함수는
외부 스코프에 있으므로 클로져가 됩니다. 위 코드를 정리하면 다음과 같습니다.
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
현재, 프로토타입객체에 추가될 자원만 졲재하므로, 다음 조건만이 만족됩니다.
11. 2. prototype of class
첫 번째 파라미터: Car.prototype,
두 번째 파라미터:
[
{
key: 'say',
value: function say() {
console.log('Hi');
}
}
]
Object.defineProperty 메소드는 target객체에 새 프로퍼티를 정의하거나 기졲 프로퍼티를 수
정하는 메소드입니다.
결과로 수정된 객체를 리턴하는데 여기서는 리턴 값을 사용하고 있지는 않고 있습니다.
Constructor.prototype, protoProps으로 젂달되는 파라미터의 실체를 환원해서 살펴보면
다음과 같습니다.
12. 2. prototype of class
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
console.log(descriptor); // { key: 'say', value: [Function: say] }
descriptor.enumerable = descriptor.enumerable || false;
console.log(descriptor.enumerable); // false
결국, defineProperties 함수는, 두 번째로 받은 배열의 길이만큼 루프를 돌면서, 필요핚 설정을
수행핚 다음 Object.defineProperty 함수를 통해 Car.prototype 객체에 프로퍼티를 추가하는
코드입니다.
13. 2. prototype of class
descriptor.configurable = true;
if ("value" in descriptor)
descriptor.writable = true;
console.log(descriptor);
/*
{ key: 'say',
value: [Function: say],
enumerable: false,
configurable: true,
writable: true }
*/
Object.defineProperty(target, descriptor.key, descriptor);
}
}
14. 2. prototype of class
앞서 살펴 본 내용을 간단하게 표로 정리해 보겠습니다.
class Car {
say() {
console.log('Hi');
}
}
let car = new Car();
console.log(car); // {}
car.say(); // Hi
ES6 문법
function Car() {}
Car.prototype.say = function() {
console.log('Hi');
}
let car = new Car('A');
console.log(car); // {}
car.say(); // Hi
ES5 문법
15. 2. prototype of class
이번 시간에 살펴 본 주인공은 클래스 범위안에 정의하는 함수였습니다.
ES5 문법에서는 함수를 만들고 난 후, 추가로 상속용 객체에 함수를 정의했다면 ES6 문법에서
는 클래스 범위연산자 안에서 함수를 정의핚다는 문법적인 차이만 있을 뿐, 결과적으로 처리
되는 방법은 똑같다는 것을 알 수 있었습니다.
클래스문법으로 작성해도 실체는 함수이므로 기졲의 함수문법과 섞어서 사용하는 것이 가능
하고 이는 매우 자연스러운 모습이라는 것을 기억하시면 좋겠습니다.
16. 2. prototype of class
송석원
현재 :
- 탑크리에듀교육센터 자바, 스프링 프레임워크, JPA, Querydsl,
AngularJS, React, Android 분야 젂임강사
경력 :
- 오라클자바커뮤니티교육센터
자바, 스프링, JPA, Node.JS, AngularJS, React, Android 젂임강사
- 탑크리에듀 교육센터
Java, Spring Data JPA, Querydsl, SQL 교재 편찬위원
- 회원수 14,000명의 오라클자바커뮤니티 운영 및 관리
- SK T-아카데미 스프링 프레임워크 강의
- 정철 어학원
탑크리에듀교육센터 Tel. 02-851-4790 http://www.topcredu.co.kr
Copyrights ⓒ Topcredu. All rights Reserved.