꼭 알아야 할 ES6+ 문법
파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
리액트를 공부하기위해 필요한 ES6+ 문법을 정리해본다.
필수 문법
- 상수/변수 선언 (const/let)
- Object 선언, 단축 속성, key 계산, 객체 복사
- Template Literals
- 배열/객체 비구조화 (Array/Object Destructuring)
- 전개 연산자 (Spread Operator)
- 함수와 인자 (Functions, Parameters, Named Parameters)
- Arrow Functions
- Promise와 async/await
- 클래스와 상속
- 모듈 시스템
- 고차 함수 (High Order Function)
1. 상수 / 변수 선언
var 대신에 const 혹은 let을 사용 → block scope
- const: 재할당 불가. 내부 속성은 수정 가능.
- let: Lexical Variable Scoping을 지원하는 변수 선언 문법
var div;
var container = document.getElementsByTagName('body')[0];
for(let i=0; i<5; i++) {
div = document.createElement('div’);
div.onclick = function() {
alert("clicked : #" + i); // var/let 사용 여부에 따라 alert 메시지가 달라집니다.
};
div.innerHTML = "#" + i;
container.appendChild(div);
}
⇒ let으로 작성할 경우, i가 새로 선언되지만, var로 작성할 경우에는 하나의 변수를 공유하므로 실제 클릭 이벤트 시 무조건 5로 출력된다.
최근 트렌드는 const위주로, 간간히 let을 사용한다.
2. Object 선언
2.1. Object 선언
JavaScript
// tom1 / tom2는 동일
let tom1 = {
name: "Tom",
age: 10,
region: "Seoul"
};
let tom2 = {
"name": "Tom",
"age": 10,
"region": "Seoul"
};
- Python
tom = {
"name": "Tom",
"age": 10,
"region": "Seoul"
}
2.2. Key 계산이 필요한 경우
JavaScript
const tom2 = {
"name": "Tom",
"age": 10,
"region": "Seoul",
["score" + "1"]: 100,
// key는 "scope1" (Array가 아님)
};
const key1 = "location";
const tom = {
name: "Tom",
[key1]: "Seoul"
};
Python
tom = {
"name": "Tom",
"age": 10,
"region": "Seoul",
"score" + "1": 100,
}
key1 = "location"
tom = {
"name": "Tom",
key1: "Seoul"
}
2.3. 단축 속성명
let name = "Tom";
let age = 10;
let tom1 = { // 이와 같이 클래스 없이도 객체를 만들 수 있다. -> tom1.print()
name: name,
age: age,
print: function() {
console.log(`name: ${this.name}, age: ${this.age}`);
}
};
let tom2 = { // 위와 동일한 객체 -> tom2.print()
name,
age,
print() {
console.log(`name: ${this.name}, age: ${this.age}`);
}
};
3. 객체 복사
// tom1 / tom2는 동일
let tom1 = {
name: "Tom",
age: 10,
region: "Seoul"
};
let tom2 = {
"name": "Tom",
"age": 10,
"region": "Seoul"
};
tom = {
"name": "Tom",
"age": 10,
"region": "Seoul"
}
const tom2 = {
"name": "Tom",
"age": 10,
"region": "Seoul",
["score" + "1"]: 100,
// key는 "scope1" (Array가 아님)
};
const key1 = "location";
const tom = {
name: "Tom",
[key1]: "Seoul"
};
tom = {
"name": "Tom",
"age": 10,
"region": "Seoul",
"score" + "1": 100,
}
key1 = "location"
tom = {
"name": "Tom",
key1: "Seoul"
}
let name = "Tom";
let age = 10;
let tom1 = { // 이와 같이 클래스 없이도 객체를 만들 수 있다. -> tom1.print()
name: name,
age: age,
print: function() {
console.log(`name: ${this.name}, age: ${this.age}`);
}
};
let tom2 = { // 위와 동일한 객체 -> tom2.print()
name,
age,
print() {
console.log(`name: ${this.name}, age: ${this.age}`);
}
};
JS는 Object/Array에 대해서는 대입시에 얕은 복사 (Shallow Copy)
t.js
const obj1 = { value1: 10 };
const obj2 = obj1; // 얕은 복사
const obj3 = JSON.parse(JSON.stringify(obj1)) // 깊은 복사
obj1.value1 += 1;
console.log(`obj1:`, obj1);
console.log(`obj2:`, obj2);
console.log(`obj3:`, obj3);
> node t.js
obj1: { value1: 11 }
obj2: { value1: 11 }
obj3: { value1: 10 }
⇒ obj2.value1도 변경되었음.
4. Template Literals
Multi-line string
String Interpolation
javascript
`string text ${expression}
string text`
python
"""string text
string text"""
f"""string text {expression}
string text"""
5. 배열 비구조화 (Array Destructuring)
리액트에서 자주 쓰는 문법
let [name] = ["Tom", 10, "Seoul"];
let [,age,] = ["Tom", 10, "Seoul"];
let [name, age, region, height] = ["Tom", 10, "Seoul"]
// height = undefined 할당 (파이썬에서는 ValueError 예외)
let [name, age, region, height=150] = ["Tom", 10, "Seoul"]
// height = 디폴트값 할당 (150)
function get_default_height() {
console.log("get_default_height() 호출")
return 150;
}
let [name, age, region, height=get_default_height()] = ["Tom", 10, "Seoul"]
// height에 실제 디폴트값 할당이 필요할때, get_default_height()가 호출됩니다.
6. 객체 비구조화 (Object Destructuring)
리액트에서 자주 쓰는 문법
const tom = {
name: "Tom",
age: 10,
region: "Seoul"
};
// 아래와 같이 할 수 있지만,
const age = tom.age;
const name = tom.name;
// 다음과 같이 객체에서 필요한 값들만 뽑아냅니다. (리액트에서 정말 자주 쓰는 문법)
const {age, name, height}= tom; // height는 undefined
const print_person1 = (person) => {
console.log(person.name);
};
const print_person2 = ({ name }) => {
console.log(name);
};
print_person1(tom);
print_person2(tom);
const people = [
{ name: 'Tom', age: 10, region: 'Seoul' },
{ name: 'Steve', age: 12, region: 'Pusan' }
];
for (const person of people) {
console.log(person.name, person.age);
}
for (const {name, age} of people) {
console.log(name, age);
}
const person = {
name: 'Tom',
age: 10,
region: {
country: '서울',
postcode: '06222',
}
};
const { name, region: { postcode }} = person; // region은 할당X
console.log(name, postcode);
7. 전개 연산자 (Spread Operator)
리액트에서 자주 쓰는 문법
let [name] = ["Tom", 10, "Seoul"];
let [,age,] = ["Tom", 10, "Seoul"];
let [name, age, region, height] = ["Tom", 10, "Seoul"]
// height = undefined 할당 (파이썬에서는 ValueError 예외)
let [name, age, region, height=150] = ["Tom", 10, "Seoul"]
// height = 디폴트값 할당 (150)
function get_default_height() {
console.log("get_default_height() 호출")
return 150;
}
let [name, age, region, height=get_default_height()] = ["Tom", 10, "Seoul"]
// height에 실제 디폴트값 할당이 필요할때, get_default_height()가 호출됩니다.
리액트에서 자주 쓰는 문법
const tom = {
name: "Tom",
age: 10,
region: "Seoul"
};
// 아래와 같이 할 수 있지만,
const age = tom.age;
const name = tom.name;
// 다음과 같이 객체에서 필요한 값들만 뽑아냅니다. (리액트에서 정말 자주 쓰는 문법)
const {age, name, height}= tom; // height는 undefined
const print_person1 = (person) => {
console.log(person.name);
};
const print_person2 = ({ name }) => {
console.log(name);
};
print_person1(tom);
print_person2(tom);
const people = [
{ name: 'Tom', age: 10, region: 'Seoul' },
{ name: 'Steve', age: 12, region: 'Pusan' }
];
for (const person of people) {
console.log(person.name, person.age);
}
for (const {name, age} of people) {
console.log(name, age);
}
const person = {
name: 'Tom',
age: 10,
region: {
country: '서울',
postcode: '06222',
}
};
const { name, region: { postcode }} = person; // region은 할당X
console.log(name, postcode);
7. 전개 연산자 (Spread Operator)
리액트에서는 수많은 값들을 불변객체로서 처리합니다 → 이때 전개연산자를 많이 쓰며, 구조가 복잡할 경우 immer 라이브러리를 쓰는 것이 코드 가독성에 도움이 됩니다.
let [name, ...rest] = ["Tom", 10, "Seoul"];
let names = ["Steve", "John"];
let students = ["Tom", ...names, ...names]; // ["tom", "steve", "john", "steve", "john"]
let printArgs = (...args) => {
console.log(args);
}
let tom = {
name: "Tom",
age: 10,
region: "Seoul"
};
let steve = {
...tom,
name: "Steve" // 속성 명이 중복일 경우 마지막 값이 남습니다.
}; // {name: "Steve", age: 10, region: "Seoul"}
8. 함수 / Default Parameters
모든 타입의 값들을 디폴트 파라미터로 지정할 수 있습니다.
모든 타입의 값들을 디폴트 파라미터로 지정할 수 있습니다.
⇒ 파이썬에서는 Immutable값들만 디폴트 파라미터로 지정 가능
function hello(name="Tom", age=10) {
console.log(`나는 ${name}. ${age}살이야.`)
}
const get_default_age = () => 10
function hello(name="Tom", age=get_default_age()) {
console.log(`나는 ${name}. ${age}살이야.`);
}
console.log(hello("steve"));
[node/python 비교] 디폴트 값에 함수를 적용 할 경우
nodejs
function get_default_height() {
console.log("get_default_height() 호출");
return 150;
}
function say_hello(name, height=get_default_height()) {
console.log(`name: ${name}, height: ${height}`);
}
say_hello("Tom", 160);
say_hello("John");
say_hello("Steve", 170);
say_hello("Suji");
> node t.js
name: Tom, height: 160
get_default_height() 호출
name: John, height: 150
name: Steve, height: 170
get_default_height() 호출
name: Suji, height: 150
python
def get_default_height():
print("get_default_height() 호출")
return 150
def say_hello(name, height=get_default_height()):
print(f"name: {name}, height: {height}")
say_hello("Tom", 160)
say_hello("John")
say_hello("Steve", 170)
say_hello("Suji")
> python t.py
get_default_height() 호출
name: Tom, height: 160
name: John, height: 150
name: Steve, height: 170
name: Suji, height: 150
9. 함수 / Named Parameters
객체 비구조화를 활용
javascript
function print_person1(name, age, region) {
console.log('1>', name, age, region)
}
print_person1('Tom', 10, 'Seoul');
function print_person2({ name, age, region }) {
console.log('2>', name, age, region)
}
print_person2({ name: 'Tom', age: 10, region: 'Seoul' });
python
def print_person(name, age, region):
print(name, age, region)
print_person('Tom', 10, 'Seoul')
print_person(name='Tom', age=10, region='Seoul')
# out -> ('Tom', 10, 'Seoul')
print_person(**{'name': 'tom', 'age': 10, 'region': 'seoul'})
# out -> ('tom', 10, 'seoul')
10. 함수 / Arrow Function
return을 사용하지 않아도, 계산된 값을 반환. 인자가 1개일 경우, 소괄호 생략 가능.
var hello1 = function(name, age) {
return `안녕. 나는 ${name}. ${age}이야.`;
};
let hello2 = (name, age) => `안녕. 나는 ${name}. ${age}이야.`; // 함수를 중괄호로 감싸지 않으면, return문을 쓰지 않아도 반환값으로 사용됩니다.
let hello3 = (name, age) => {
return `안녕. 나는 ${name}. ${age}이야.`;
}
this와 arguments를 바인딩하지 않습니다.
var tom = {
name: "Tom",
print1: function() {
console.log(`[print1-1] name : ${this.name}`);
(function() {
console.log(`[print1-2] name : ${this.name}`); // 본래 새로운 function을 생성하면 this도 바뀐다.
})();
},
print2: function() {
console.log(`[print2-1] name : ${this.name}`);
var me = this;
(function() {
console.log(`[print2-2] name : ${me.name}`); // 새로운 function을 생성하면 this도 바뀌기 때문에, me를 통해 this를 바인딩하였다. (꼼수!)
})();
},
print3: function() {
console.log(`[print3-1] name : ${this.name}`);
(() => {
console.log(`[print3-2] name : ${this.name}`); // this가 변경되지 않았다!
})();
}
};
tom.print1();
tom.print2();
tom.print3();
실행 결과
[print1-1] name : Tom
[print1-2] name : undefined
[print2-1] name : Tom
[print2-2] name : Tom
[print3-1] name : Tom
[print3-2] name : Tom
11. 함수 / 다양한 형태
const mysum1 = (x, y) => x + y; // 더한 값 반환
const mysum2 = (x, y) => ({x, y}); // 오브젝트 반환
const mysum3 = (x, y) => ({x: x, y: y}); // mysum2와 같음
const mysum4 = (x, y) => {
return {x: x, y: y};
}
const mysum5 = function(x, y) {
return {x: x, y: y};
};
function mysum6(x, y) {
return {x: x, y: y};
}
12. 콜백 지옥 : callbackhell.com
const mysum1 = (x, y) => x + y; // 더한 값 반환
const mysum2 = (x, y) => ({x, y}); // 오브젝트 반환
const mysum3 = (x, y) => ({x: x, y: y}); // mysum2와 같음
const mysum4 = (x, y) => {
return {x: x, y: y};
}
const mysum5 = function(x, y) {
return {x: x, y: y};
};
function mysum6(x, y) {
return {x: x, y: y};
}
비동기 프로그래밍을 위해 콜백(callback)을 많이 사용
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
13. 콜백 → Promise → async/await
콜백
const fs = require('fs');
fs.readdir('.', function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
}
else {
console.log(files);
}
});
// 위 fs.readdir이 끝나기 전에 수행
console.log("ENDED");
Promise
const fs = require('fs');
const fsPromises = fs.promises;
fsPromises.readdir('.')
.then(files => { // 정상 처리
console.log(files);
})
.catch(err => console.error(err)); // 에러 상황
// 위 fsPromises.readdir이 끝나기 전에 수행
console.log("ENDED");
async/await → ES8 (ECAM 2017)부터 지원
const fs = require('fs');
fs.readdir('.', function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
}
else {
console.log(files);
}
});
// 위 fs.readdir이 끝나기 전에 수행
console.log("ENDED");
const fs = require('fs');
const fsPromises = fs.promises;
fsPromises.readdir('.')
.then(files => { // 정상 처리
console.log(files);
})
.catch(err => console.error(err)); // 에러 상황
// 위 fsPromises.readdir이 끝나기 전에 수행
console.log("ENDED");
비동기 문법임에도 동기적으로 코드를 해석할 수 있다.
const fs = require('fs');
const fsPromises = fs.promises;
async function fn() {
try {
let files = await fsPromises.readdir('.');
console.log(files);
}
catch(err) {
console.error(err);
}
}
fn(); // async 함수 이기에, 완료 전에 다음 로직이 동작
console.log("ENDED");
14. 클래스와 상속
ES6 이전
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.print = function() { // 멤버함수 정의
console.log(this.name + ", " + this.age);
}
var tom = new Person("Tom", 10);
tom.print();
ES6 이후
class Person {
constructor(name, age) { // 생성자
this.name = name;
this.age = age;
}
print() { // 멤버함수
console.log(this.name + ", " + this.age);
}
}
const tom = new Person("Tom", 10);
tom.print();
class Developer extends Person {
constructor(name, age, field) {
super(name, age);
this.field = field;
}
print() {
super.print();
console.log(`field : ${this.field}`);
}
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.print = function() { // 멤버함수 정의
console.log(this.name + ", " + this.age);
}
var tom = new Person("Tom", 10);
tom.print();
class Person {
constructor(name, age) { // 생성자
this.name = name;
this.age = age;
}
print() { // 멤버함수
console.log(this.name + ", " + this.age);
}
}
const tom = new Person("Tom", 10);
tom.print();
class Developer extends Person {
constructor(name, age, field) {
super(name, age);
this.field = field;
}
print() {
super.print();
console.log(`field : ${this.field}`);
}
}
⇒ 문법이 다를 뿐, 여전히 prototype을 사용합니다.
15. 모듈 시스템
- 예전 웹 상의 자바스크립트에서는 html파일에서 script 태그를 통해서만 로딩 → 모두 전역 객체에 바인딩
- 2가지 모듈 시스템
- CommonJS Module : nodejs에서 주로 사용
- ES6 Module : 리액트에서 주로 활용
ES6 module
- React를 쓰실 때 사용할 모듈 시스템
- IE를 포함한 구형 브라우저에서는 미지원
- node 이후에 ES6 Module이 나왔기에, node에서는 왠만한 ES6문법은 지원하지만, 모듈은 ES6를 지원하지 않고, CommonJS만을 지원
- 문법: export, export default, import ... from
- CommonJS Module : nodejs에서 주로 사용
- ES6 Module : 리액트에서 주로 활용
추가:
CommonJS
- node에서 지원하는 일반적인 모듈 패턴
모듈 정의하기
commonjs module
my_module.js : 모듈 정의
const name = "tom";
const age = 10;
module.exports = {
name,
age,
region: "Seoul"
};
in_nodejs.js : 모듈 불러오기
const my_module = require("./my_module");
const { name } = require("./my_module");
console.log(my_module);
console.log(name);
es6 module
my_module_es6.js : 모듈 정의
const name = "tom";
const age = 10;
export default {
name,
age,
region: "Seoul"
};
export {
name,
};
in_react.js : 모듈 불러오기
import my_module from "./my_module"; // export default를 참조
import { name } from "./my_module"; // export를 참조
16. 고차 함수 (High Order Function)
함수를 인자로 받거나 반환이 가능하고, 다른 함수를 조작하는 함수.
함수/클래스 역시 모두 객체
javascript #1
function base_10(fn) {
function wrap(x, y) {
return fn(x, y) + 10;
}
return wrap;
}
function mysum(a, b) {
return a + b;
}
mysum = base_10(mysum);
console.log(mysum(1, 2));
javascript #2
const base_10 = fn => (x, y) => fn(x, y) + 10;
let mysum = (a, b) => a + b;
mysum = base_10(mysum);
console.log(mysum(1, 2));
비교) python
def base_10(fn):
def wrap(x, y):
return fn(x, y) + 10
return wrap
def mysum(x, y):
return x + y
mysum = base_10(mysum)
print(mysum(1, 2))
17. 참고) ES6 (ECMAScript2015) 문법 더 살펴보기
함수를 인자로 받거나 반환이 가능하고, 다른 함수를 조작하는 함수.
함수/클래스 역시 모두 객체
function base_10(fn) {
function wrap(x, y) {
return fn(x, y) + 10;
}
return wrap;
}
function mysum(a, b) {
return a + b;
}
mysum = base_10(mysum);
console.log(mysum(1, 2));
const base_10 = fn => (x, y) => fn(x, y) + 10;
let mysum = (a, b) => a + b;
mysum = base_10(mysum);
console.log(mysum(1, 2));
def base_10(fn):
def wrap(x, y):
return fn(x, y) + 10
return wrap
def mysum(x, y):
return x + y
mysum = base_10(mysum)
print(mysum(1, 2))
https://babeljs.io/docs/en/learn
Author And Source
이 문제에 관하여(꼭 알아야 할 ES6+ 문법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@joje/꼭-알아야-할-ES6-문법저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)