May 29, 2020 ( last updated : May 28, 2020 )
ES2015
ES2016
ES2017
ES2018
ES2019
ES2020
javascript
https://github.com/gmm117/gmm117.github.io
ES2015
ES2016
ES2017
ES2018
ES2019
ES2020
HTML Fragments
More String Implovements
Array
For ... of
classes
fetch
Symbol/Map
우리가 흔히 말하는 자바스크립트.
배열에 forEach, map, filter, reduce, some, every와 같은 메소드 지원 Object에 대한 getter / setter 지원
var person = {
firstName: 'Hong',
lastName: 'SeungAh',
get fullName() {
return this.firstName + ' ' + this.lastName;
},
set fullName (name) {
var words = name.toString().split(' ');
this.firstName = words[0] || '';
this.lastName = words[1] || '';
}
}
person.fullName = 'Hong SeungAh';
console.log(person.firstName); // Hong
console.log(person.lastName); // SeungAh
// defineProperty 속성추가가능
var person = {
firstName: 'Hong',
lastName: 'SeungAH'
};
Object.defineProperty(person, 'fullName', {
get: function() {
return this.firstName + ' ' + this.lastName;
},
set: function(name) {
var words = name.split(' ');
this.firstName = words[0] || '';
this.lastName = words[1] || '';
}
});자바스크립트 strict 모드 지원 (더 깐깐한? 문법 검사를 한다.) JSON 지원 ( 과거에는 XML을 사용하다가, json이 뜨면서 지원하게 됨 )
function sayHello(name) {
if (!name) {
let errorMessage = '"name" parameter should be non empty String.';
alert(errorMessage);
}
console.log('Hello, ' + name + '!');
console.log(errorMessage); // ReferenceError
}
// 값 수정
let foo = 'foo';
foo = 'foo2'; // OK - 값 수정이 가능하다.
const bar = 'bar';
bar = 'bar2'; // Type error - bar 변수는 상수이므로 값 수정이 불가능하다.
// 선언, 초기화
const baz2; // Type error - const로 선언한 변수는 선언과 동시에 초기화 해야한다.
let baz; // OK - let으로 선언한 변수는 선언과 동시에 초기화할 필요 없다.
baz = 'baz';
// const 변수의 프로퍼티 값 수정
const foo2 = {
bar2: 'bar'
};
foo2.bar2 = 'bar2'; // OK - foo2의 프로퍼티는 수정이 가능하다.const sum = (a, b) => {
return a + b;
};const MakeUser = {
userName : 'hong',
sayHello : function() {
console.log(`hello, this is ${this.userName}`);
}
}
// class와 그냥 객체의 차이점은 new로 할당할 경우에만 instance를 생성한다는 것이다.(MakeUser를 객체를 만들어서 리턴한 것이다.)
class User {
constructor(name) {
this.userName = name;
}
sayHello() {
console.log(`hello, this is ${this.userName}`);
}
};
const user1 = new User('hong');
const user2 = new User('seungah');
const user3 = MakeUser;
console.log(user1.sayHello());
console.log(user2.sayHello());
console.log(user3.sayHello());class User {
constructor({name}) {
this.userName = name;
}
sayHello() {
console.log(`hello, this is ${this.userName}`);
}
};
// 자식 생성자가 있는경우 super 키워드가 없으면 상속받은 부모 생성자 호출이 불가능하다.
class Admin extends User {
constructor({name, superAdmin}) {
super({name});
this.superAdmin = superAdmin;
}
sayAdmin() {
console.log(`admin, this is ${this.userName} superAdmin : ${this.superAdmin}`);
}
}
const admin = new Admin({name : 'hong', superAdmin: true});
admin.sayHello();
admin.sayAdmin();class Counter {
this.plusButton.addEventListener("click", this.increase);
this.minusButton.addEventListener("click", this.descrease);
// ctrl eventHandler callback 호출의 this는 ctrl자체를 가리킨다.(여기선 button)
// 수정전
increase() {
consoloe.log(this);
}
descrease() {
consoloe.log(this);
}
// 수정후(lexical scope this를 가지고 있습니다.??)
increase = () => {
consoloe.log(this);
}
descrease = () => {
consoloe.log(this);
}
}// before ES2015
var dog = {
name: 'Lycos',
bark: function () {
console.log('Woof! Woof!')
}
};
dog.bark(); // 'Woof! Woof!';
var iPhone = '아이폰';
var iPad = '아이패드';
var iMac = '아이맥';
var appleProducts = {
iPhone: iPhone,
iPad: iPad,
iMac: iMac
};
// after ES2015
const dog = {
name: 'Lycos',
bark() {
console.log('Woof! Woof!')
}
};
dog.bark(); // 'Woof! Woof!';
const iPhone = '아이폰';
const iPad = '아이패드';
const iMac = '아이맥';
const appleProducts = {iPhone, iPad, iMac};// before es2015
let sayHello1 = (aName="hong") => "hello " + aName;
console.log(sayHello1());
// after es2015
let sayHello2 = (aName="hong") => `hello ${aName}`;
console.log(sayHello2());
console.log(`hello ${100*100}`);
const add = (prev, next) => prev + next;
console.log(`prev plus next : ${add(3,4)}`);// 비구조화 할당
const settings = {
noti : {
follow : true,
alerts : true,
unfollow : false
},
color : {
theme : "dark"
}
};
const {
noti : {
data = "init",
unfollow
} = {},
color : {
theme
}
} = settings;
console.log(unfollow, theme, data);const days = ["Mon", "Tue", "Wen", "Thu", "Fri", "Sat"];
// 이전
// const Mon = days[0];
// const Tue = days[1];
// const Wen = days[2];
// const Thu = days[3];
// const Fri = days[4];
// const Sat = days[5];
// const Sun = days[6];
// 이후
const [Mon, Tue, Wen, Thu, Fri, Sat, Sun = "Sun"] = days;
console.log(Mon, Tue, Wen, Thu, Fri, Sat, Sun);const sayName = (name = 'World') => {
console.log(`Hello, ${name}!`);
}
sayName(); // "Hello, World!"function sayHello(aName = "hong") {
return "Hello " + aName;
}
console.log(sayHi());// Spread object/Array unpack
const number = [1, 2, 3, 4];
const alpha = ['a', 'b', 'c'];
console.log([...number, ...alpha]);
//[1, 2, 3, 4, "a", "b", "c"]const bestfriends = (one, ...friendsRest) => console.log(`my best friends : ${one}, friends rest : ${friendsRest}`);
bestfriends('kim', 'choi', 'seyoung');// object 삭제 & 정리할경우 유용
const user = {
name : 'hong',
age : 36,
password : '**123'
};
const ignorepwd = ({password, ...rest}) => rest;
console.log(ignorepwd(user));
// object를 만들어서 return 할 경우 () 감싸줘야한다.
const setCountry = ({country="kr", ...rest}) => ({country, ...rest}); // ({country, ...rest}) spread 문법사용
console.log(setCountry(user));함수의 흐름을 특정 구간에 멈춰놓았다가 다시 실행할 수 있다. 결과값을 여러번 내보낼 수 있다. Generator 문법이 나오면서 redux-saga, rsjx등 여러 라이브러리가 나오게 되었음
function* gen() {
yield 1;
yield 2;
yield 3;
yield 4;
}
const g = gen();
console.log(g.next().value); // 1
console.log(g.next().value); // 2
console.log(g.next().value); // 3
console.log(g.next().value); // 4
console.log(g.next().value); // undefined
// next를 수행하면서 각각 여러 동작들을 순서에 맞게 처리가능
function* listPeople() {
// 1. 동작
yield 'hong';
// 2. 동작
yield 'kim';
// 3. 동작
yield 'choi';
// 4. 동작
yield 'park';
};
function* friendTeller() {
for(const friend of friends) {
yield friend;
}
}
const friends = ['hong', 'kim', 'choi', 'park'];
const friendLooper = friendTeller();
const listG = listPeople();
listG.next();
//{value: "hong", done: false}
listG.next();
//{value: "kim", done: false}
listG.next();
//{value: "choi", done: false}
listG.next();
//{value: "park", done: false}
listG.next();
//{value: undefined, done: true}// async function
const newPromise = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'I am new Promise');
});
console.log(newPromise);
setInterval(console.log, 1000, newPromise);const newPromise = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'I am new Promise');
});
// resolve : then, reject : catch 호출이며 단 하나만 호출이 된다.
newPromise
.then(value => console.log(value))
.catch(err => console.log(`error ${err}`)); const newPromise = new Promise((resolve, reject) => {
resolve(2);
});
const timesTwo = number => number * 2;
newPromise
.then(timesTwo)
.then(timesTwo)
.then(timesTwo)
.then(timesTwo)
.then(timesTwo)
.then(timesTwo)
.then(lastnumber => console.log(lastnumber));const f1 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, "first");
});
const f2 = new Promise((resolve, reject) => {
setTimeout(resolve, 5000, "secode");
});
const f3 = new Promise((resolve, reject) => {
setTimeout(resolve, 7000, "third");
});
// Promise.all 시간과 상관없이 순서에 맞게 값을 제공해준다.
const fall = Promise.all([f1, f2, f3]);
fall.then(values => console.log(values));
// Promise.race f1,f2,f3중 가장먼저 resolve, reject 되는 내용의 결과값을 제공해준다.
const frace = Promise.race([f1, f2, f3]);
fall.then(values => console.log(values));Named export는 한 파일에서 여러 번 할 수 있다. Named export를 통해 내보낸 것 들은 추후 다른 모듈에서 내보낼 때와 같은 이름으로 import 해야 한다.
export const student = 'Park';
export const student2 = 'Ted';
const student3 = 'Abby';
export {student3};
import {student, student2, student3} from 'students.js';
import {student as park, student2 as ted, student3 as abby} from 'students.js';
import * as students from 'students.js';반면에 Default export는 한 스크립트 파일당 한 개만 사용할 수 있다. 그리고 export default의 뒤에는 표현식만 허용되므로 var, let, const등의 키워드는 사용하지 못한다.
이렇게 내보낸 객체들은 모듈들에서 접근할 수 있다. 그렇다면 지금부터는 모듈에서 export 한 객체들을 가져오는 import문을 살펴보자.
export default 'Jack'
import jack from 'studentJack';배열 내장 함수 includes가 추가되었습니다. 아이템이 존재하는지 boolean 값으로 반환
Array.prototype.includes(searchElement, ?fromindex);
// before ES2016
console.log([1, 2, 3].indexOf(4)); // -1
// after ES2016
console.log([1, 2, 3].includes(2)); // true
console.log([1, 2, 3].includes(4)); // false
console.log([1, 2, NaN].includes(NaN)); // true
console.log([1, 2, -0].includes(+0)); // true
console.log([1, 2, +0].includes(-0)); // true
console.log(["a", "b", "c"].includes("a")); // true
console.log(["a", "b", "c"].includes("a", 1)); // false다른 프로그래밍 언어들에서 일반적으로 사용되는 문법을 도입하였다. x ** y는 x의 y제곱을 의미하며, 이는 Math.pow(x, y)와 완전히 동일하다.
number ** number
// before ES2016
console.log(Math.pow(2, 3)); // true
// after ES2016
console.log(2 ** 3); // 8 ( === 2 * 2 * 2 )
let a = 3;
a **= 4;
console.log(a); // 81 ( === a * a * a * a )
10 ** -1; // 0.1
2.5 ** 2; // 6.25
3 ** 2.5; // 15.588457268119896
2 ** 3 ** 2; // 512
2 ** (3 ** 2); // 512
(2 ** 3) ** 2; // 64최대 길이보다 짧은 문자열에 대해서 그 여백에 지정한 문자열을 반복하여 채우는 메소드이다. padStart는 문자열의 좌측에 여백을 지정하며, padEnd는 그 반대이다. 두 메소드 모두 maxLength보다 긴 문자열에 대해서는 동작하지 않는다.
String.prototype.padStart(maxLength[, padString]) String.prototype.padEnd(maxLength[, padString])
'abc'.padStart(10); // " abc" (두번째 파라미터 생략시 빈 문자열로 채운다)
'abc'.padStart(10, '12'); // "1212121abc"
'abc'.padStart(5, '1234567'); // "12abc"
'abcde'.padStart(3, '12'); // "abcde"
'abc'.padEnd(10); // "abc " (두번째 파라미터 생략시 빈 문자열로 채운다)
'abc'.padEnd(10, '12'); // "abc1212121"
'abc'.padEnd(5, '1234567'); // "abc12"
'abcde'.padEnd(3, '12'); // "abcde"Object.values(object) Object.entries(obj)
const obj = {a:1, b:2, c:3}
console.log(Object.keys(obj)); // [ "a", "b", "c" ]
console.log(Object.values(obj)); // [ 1, 2, 3 ]
console.log(Object.entries(obj)); // [ ["a", 1], ["b", 2], ["c", 3] ]getOwnPropertyDescriptor는 인자로 객체와 속성명을 전달해 해당 속성의 속성 설명자를 반환하는 메소드입니다.
Object.getOwnPropertyDescriptor(obj, prop)
getOwnPropertyDescriptors는 속성명을 전달하지 않고 객체만 전달함으로 객체내의 모든 속성에 대한 속성 설명자를 반환합니다.
Object.getOwnPropertyDescriptor(obj)
const obj1 = {name: "Jhon", age: 24};
console.log(Object.getOwnPropertyDescriptor(obj1, "name"));
// Object {value: "Jhon", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptors(obj1));
// Object {
// name: {value: "Jhon", writable: true, enumerable: true, configurable: true},
// age: {value: 24, writable: true, enumerable: true, configurable: true}
// }함수의 마지막 매개변수와 인자에도 콤마를 넣을 수 있습니다.
const foo = (a, b, c,) => {}
// promise를 사용하게 되면 사용자가 얻고자하는 값이 여러개 일경우 then/then/then을 호출하게 되어서 코드가 복잡해진다.
const getMoviesPromise = () => {
fetch("https://yts.am/api/v2/list_movies.json")
.then(response => response.json())
.then(result => console.log(result))
.catch(err => console.log(err));
};
const getMoviesAsync = async( ) => {
const response = await fetch("https://yts.lt/api/v2/list_movies.json");
const json = await response.json();
console.log(json);
};
getMoviesAsync();const getMoviesAsync = async () => {
try {
const response = await fetch("https://yts.lt/api/v2/list_movies.json");
const json = await response.json();
console.log(json);
} catch(e) {
console.log(`Error ${e}`);
} finally {
console.log("we are done");
}
};
getMoviesAsync();const getMoviesAsync = async () => {
try {
const [moviesRespose, suggestionResponse] = await Promise.all([
fetch("https://yts.lt/api/v2/list_movies.json"),
fetch("https://yts.lt/api/v2/movie_suggestions.json")
]);
const [movies, suggestion] = await Promise.all([
moviesRespose.json(),
suggestionResponse.json()
]);
console.log(movies);
console.log(suggestion);
} catch(e) {
console.log(`Error ${e}`);
} finally {
console.log("we are done");
}
};
getMoviesAsync();기존의 배열에서 사용하던 rest/spread를 객체에서도 사용가능하게 되었습니다.
// Spread
const obj1 = {one, two, ... others};
console.log(obj); // {one: 1, two: 2, three: 3, four: 4, five: 5}
const person1 = {
name : 'hong',
age : 33
};
const person2 = {
name1 : 'park',
age1: 33
};
console.log({...person1, ...person2});
// {name: "hong", age: 33, name1: "park", age1: 33}
const friends = ['choi', 'kim'];
const newfriends = [...friends, 'seyoung'];
console.log(newfriends);
// ["choi", "kim", "seyoung"]
const choi = {
username : 'choi'
};
console.log({...choi, password:'***123***'});
//{username: "choi", password: "***123***"}
// Rest
const { one, two, ...others } = { one: 1, two: 2, three: 3, four: 4, five: 5 }
console.log(one, two, others); // 1 2 {three: 3, four: 4, five: 5}
const user1 = {
NAME : 'hong',
age : 36,
password : '**123'
};
// const 변수를 새로만들듯이 새로운 변수를 세팅
const rename = ({NAME:name, ...rest}) => ({name, ...rest});
console.log(rename(user1));then, catch, finally에서 Promise는 기존에 then과 catch만 가능했으나 이제 finally도 추가되었습니다.
// resolve, reject이 호출되더라도 finally를 무조건 한번은 타도록 되어있음
const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, "before finally");
})
.then(value => console.log(value))
.catch(err => console.log(err))
.finally(() => console.log("call finally"));비동기 이터러블 객체를 순회하는 것이 가능해졌습니다.
for await (const req of requests) {
console.log(req)
}문자열의 앞이나 뒤의 공백을 제거한다. 앞을 제거하는 trimStart와 뒤를 제거하는 trimEnd가 있다.
const s = " hello world";
const e = "! ";
console.log(s + e + ';');
// " hello world! ;"
console.log(s.trimStart() + e.trimEnd() + ';');
// "hello world!;"catch 매개변수 없이도 catch 블록을 사용할 수 있습니다.
// Before ES2019
try {
// some code
}
catch (err) {
// error handling code
}
// After ES2019
try {
// some code
}
catch {
// error handling code
}객체를 entries로 배열로 만들었다면 fromEntries로 다시 객체로 만들 수 있다는 이야기입니다. entires를 이해했다면 간단하게 아래 예제를 통해 알 수 있습니다.
const obj1 = {name: "Jhon", age: 24};
const entries = Object.entries(obj1);
console.log(entries); // [["name", "Jhone"], ["age", 24]]
const fromEntries = Object.fromEntries(entries);
console.log(fromEntries); // {name: "Jhon", age: 24}flat 메소드는 배열안의 배열을 쉽게 합칠 수 있게 됩니다.
const arr = [1,2,3];
const map = arr.map(v => [v]);
const flatMap = arr.flatMap(v=> [v]);
console.log(map); // [[1], [2], [3]]
console.log(map.flat()); // [1, 2, 3]
console.log(flatMap); // [1, 2, 3]예전에는 브라우저의 전역객체는 window였고 Node.js의 전역객체는 global이었습니다. 둘이 달라서 분기처리를 해줘야 했던 경우가 많았는데 이제는 globalThis라는 것으로 통일되었습니다. 물론 기존 window나 global도 존재합니다.
// 브라우저에서는
globalThis === window; // true
// 노드에서는
globalThis === global; // true자바스크립트에서 가장 많이 보는 에러가 cannot read property X of undefined 또는 cannot read property Y of undefined입니다.
// 이를 방지하기 위해서
if (a) {
if (a.b) {
console.log(a.b.c);
}
}
// 또는
console.log(a && a.b && a.b.c);
// optional chaining a.b가 없는경우 undefined 리턴됨
console.log(a?.b?.c);null이나 undefined일 때만 b를 반환합니다.
0 || 'A'; // A
0 ?? 'A'; // 0
0 ? 0 : 'A'; // A
0 ?? 'A'; // 0파일 import를 동적으로 할 수 있게 되었습니다.
import config from './config.js';
if(response) {
age = config.age;
}
if(response) {
import('./config.js') // promise를 동적으로 리턴
.then(config => {
age = config.age;
console.log(config);
}
}Promise.all()은 모든 작업이 성공(reslove)해야 실행되는 특징과 달리 Promise.allSettled()은 도중에 실패(reject)되더라도 모든 실행을 할 수 있습니다.
const p1 = new Promise((resolve, reject) => resolve("p1, resolved"));
const p2 = new Promise((resolve, reject) => resolve("p2, resolved"));
const p3 = new Promise((resolve, reject) => reject("p3, rejected"));
Promise.all([p1, p2, p3])
.then(response => console.log(response))
.catch(err => {
console.log(err);
});
/*
console.log(response)
{status: "fulfilled", value: "p1, resolved"}
{status: "fulfilled", value: "p2, resolved"}
{status: "rejected", reason: "p3, rejected"}
*/
Promise.allSettled([p1, p2, p3])
.then(response => console.log(response))
.catch(err => {
console.log(err);
});
/*
console.log(err);
p3, rejected
*/https://gomugom.github.io/ecmascript-proposals-1-intro/ https://junhobaik.github.io/es2016-es2020/ https://ui.toast.com/fe-guide/ko_ES5-TO-ES6/ https://www.zerocho.com/category/ECMAScript/post/5eae7480e70c21001f3e7956
// JS6이전
let text1 = "HELLO HONG";
let body = document.body;
let div = document.createElement('div');
let h1 = document.createElement('h1');
h1.innerText = text1;
div.appendChild(h1);
body.innerHTML = div.innerHTML;
// JS6이후
let text1 = "HELLO HONG";
let body = document.body;
let div = `
<div>
<h1>${text1}</h1>
</div>
`
body.innerHTML = div;
const isEmail = email => email.includes("@");
console.log(isEmail("gmm117@naver.com"));
const lastNumber = '2519';
console.log(`${'*'.repeat(3)}-${'*'.repeat(4)}-${lastNumber}`);
const name = "hong";
console.log(name.startsWith("o"));
console.log(name.endsWith("g"));
Array.of(1, 2, 3, false, "hong");
// Array.from => array-like object(HTMLCollection등등) 를 array 만들어줌
const friendEmails = [
"a@gmail.com",
"b@naver.com",
"c@daum.net"
];
const target = friendEmails.find(friend => friend.includes("gmail.com"));
console.log(target);
const targetIdx = friendEmails.findIndex(friend => friend.includes("gmail.com"));
console.log(targetIdx);
friendEmails.fill("*".repeat(5), 0, 2);
console.log(friendEmails);
// value : 배열을 채울 값, start 시작인덱스, end 끝인덱스(숫자의 -1인덱스))
const friends = ['kim', 'choi', 'seyoung', 'duhyun'];
// 잘못된 length의 array에 접근시 undefined가 나오는 문제는 생긴다.(ex: i<20)
for(let i=0; i<friends.length; ++i) {
console.log(`my best friends ${i}, ${friends[i]}`);
}
const myFriends = (friend, i) => console.log(`my best friends ${i}, ${friend}`)
friends.forEach(myFriends);
// const, let 선언 가능(forEach에 비해서)
//
for(const friend of friends) {
console.log(`my best friends ${friend}`);
}
for(const str of "Helloo this is string") {
console.log(`${str}`);
}
// fetch의 return값을 promise를 리턴하도록 되어있음
fetch("https://yts.am/api/v2/list_movies.json")
.then(response => response.json())
.then(result => console.log(result))
.catch(err => console.log(err))
// uniquie함을 보장해준다.
const info = {
[Symbol('hong')] : {
age : 35
},
[Symbol('hong')] : {
age : 30
},
hello : "bye"
};
// key에 대한 privacy 보장
Object.keys(info);
Object.getOwnPropertySymbols(info); // private을 보장하지 않는다.
// Sets
// 중복된 값을 저장하지 않는다.
const userset = new Set([1, 2, 3, 4, 5, 6, 7, 7,7,7,8]);
userset.has(9);
userset.delete(4);
userset.clear();
userset.add('hi');
userset.size
userset.keys(); // return iterator
// weakset은 number, text 저장 불가능(단지 objects와 함께 동작)
// weakset은 has,add,delete 정도만 가지고 있는 작은 set이다.
// weakset에 넣은 objects를 가리키는 것이 없다면 garbage collection에 의해서 지워진다(약하게 붙들려 있다고 가정)
const weakSet = new WeakSet();
weakSet.add({hi:true});
// map도 weakmap 존재
const map = new Map();
map.set("age", 35);
map.entries();
map.has("age");
map.get("age");
map.set("age", 1111); // 덮어쓰기 가능
// 속성조회,할당등에 대한 행위에 대한 사용자의 커스텀 동작을 정의할 떄 사용
const userObj = {
username : 'hong',
age : 36,
password : 1234
};
const userObj = {
username : 'hong',
age : 36,
password : 1234
};
const userFilter = {
get : (target, prop, recevier) => {
return prop === "password" ? `${"*".repeat(5)}` : target[prop];
},
set : () => {
console.log("call set function");
}
};
const filteredUser = new Proxy(userObj, userFilter);
undefined
filteredUser.password
// "*****"
filteredUser.age
// 36
filteredUser.username
// "hong"
배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);
const oneTwoThree = [1, 2, 3];
// 초기값 세팅 O
result = oneTwoThree.reduce((acc, cur, i) => {
console.log(acc, cur, i);
return acc + cur;
}, 0);
// 0 1 0
// 1 2 1
// 3 3 2
result; // 6
// 초기값 세팅 X
result = oneTwoThree.reduce((acc, cur, i) => {
console.log(acc, cur, i);
return acc + cur;
});
// 1 2 1
// 3 3 2
result; // 6
Javascript 정리
// 숨기고 싶은 값이지만 브라우저에서 secretUsers에 접근이 가능하다.
const secretUsers = ['hong', 'kim', 'choi', 'seyoung'];
console.log(secretUsers);
// IIFE(Immediately-Invoked Function Expressions) 적용
(/*function()*/() => {
const secretUsers = ['hong', 'kim', 'choi', 'seyoung'];
console.log(secretUsers);
})()
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- type:module로 인해서 import,export 구현가능 -->
<script type="module" src="app.js"></script>
<script type="module" src="app2.js"></script>
</body>
</html>
// app.js
let users = ['hong', 'kim', 'choi'];
export const addUsers = (user) => users = [...users, user];
export const getUsers = () => users;
export const deleteUsers = (user) => users = users.filter(aUser => aUser !== user);
//app2.js
import {addUsers, getUsers} from "./app.js"
console.log(getUsers());
addUsers("seyoung");
console.log(getUsers());
Originally published May 29, 2020
Latest update May 28, 2020
Related posts :