`Control+Shift+J`
`Command+Option+J`(Mac의 경우)를
눌러 DevTools를 엽니다.
===== Netscape --javascript(JAVA ..) =====
- prototype
- jquery
- React - facebook 서비스(라이브리성...)
- AngularJS - Angular1.0 - Google -- javascript
- Vue
- Angular 2 --> Angular -- typescript
* [[javascript:array|Array]]
* [[javascript:extend|Object extend]]
* [[javascript:regexp|RegExp 전화번호]]
* [[javascript:regexp|RegExp Password]]
* [[javascript:class|Class와 this]]
* [[javascript:callbackAndThis|callback function과 this]]
* [[javascript:void|void undefined]]
===== ECMAScript 2015 =====
ES6 === ES2015
(ES2016,ES2017..)
ES2015
개선된 JavaScript문법\\
ES6 browser compatibility의 훌륭한 지원.\\
ES6를 기반으로 한 JavaScript생태계의 확산.\\
[[https://kangax.github.io/compat-table/es6/|브라우저 호환성]]
==== language 기본 ====
* var
* function scope
* let
* block scope like for a general programming language
* const
* 재할당을 하지 못한다.
* 배열의 push등은 가능하다.
* immutable array를 만들어서 사용할 수 있다.
*
const list = ["apple","orange","watermelon"];
const list2 = [].concat(list, "banana");
console.log(list2);
console.log(list === list2);
* string에 추가 method
* startsWith
* endsWith
* includes
* for of - 순회하기
*
var data = [1,2,234];
data.forEach(function(value,idx){
console.log(value);
});
data.forEach(function(value){
console.log(data[a]);
}
for(let idx in data) {
console.log(data[idx]);
}
Array.prototype.getIndex = function(){}
// for in 에서 문제발생
// Object의 function도 같이 순회한다.
for(let value of data) {
console.log(value);
}
let str = 'asdf 111';
for(let value of str) { // character단위로 순회한다.
console.log(value);
}
* || ?? operator
* let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
* spread operator, 펼침연산자
*
let pre = ["apple","orange", 100];
let newData = [...pre];
console.log(pre === newData);
*
let pre=[100,200,"hello",null];
let newData = [0,1,2,3, ...pre, 4];
* Argument로 넘겨 줌
function sum(a,b,c){
return a+b+c;
}
let pre = [100,200,300];
console.log(sum.apply(null, pre));
console.log(sum(...pre));
=== ES2015 from method ===
function addMark(){
let newData = [];
for(let i=0; i < arguments.length; i++) {
newData.push(arguments[i] + "!");
}
console.log(newData);
}
addMark(1,2,3,4,5);
argument.map활용 --> Error남... 배열같지만 배열이 아닌 것들이 javascript에는 존재한다.
function addMark(){
//let newData = arguments.map(function(value){ //--> Error
let newarray = Array.from(arguments);
let newData = newarray.map(function(value){
return value + "!";
});
console.log(newData);
}
addMark(1,2,3,4,5);
==== 예제1 ====
JS Bin
- apple
- orange
- banana
- strawberry
=== 문제 ===
function print() {
/*
filter, includes, from을 사용해서 문자열'e'가 포함된
노드로 구성된 배열을 만들어서 반환하기
*/
}
print();
=== 풀이 ===
function print() {
/*
filter, includes, from을 사용해서 문자열'e'가 포함된
노드로 구성된 배열을 만들어서 반환하기
*/
let list = document.querySelectorAll("li");
console.log(toString.call(list));
let listArray = Array.from(list);
console.log(toString.call(listArray));
let eArray = listArray.filter(function(v){
//return v.includes("e"); // Error . v는 node
return v.innerText.includes("e");//
});
return eArray;
}
console.log(print());
==== Object ====
function을 이용한 Object생성
function getObj(){
const name = "crong";
const getName = function() {
return name;
}
const setName = function(newName) {
name = newName;
}
const printName = function() {
console.log(name);
}
// return {
// getName: getName,
// setName: setName
// }
return { getName, setName }
}
var obj = getObj();
console.log(obj.getName());
==== Destructuring ====
=== Array ====
let data = ["crong","honux","jk","jinny"];
let [jisu,,jung] = data;
console.log(jisu, jung);
=== Object ===
let obj = {
name : "crong",
address : "korea",
age : 10
}
obj["name"];
obj.name;
;
obj = $.extend(obj,
{
name2 : "asdfa";
}
)
obj["name"];
obj["name2"];
obj.name2;
let {name:myName, age:myAge} = obj; // myName, myAge변수에 할당함.
console.log(myName, myAge);
=== 활용 JSON파싱 ===
var news = [
{ "title":"sbs",
"imgurl":"http://asdfasdf",
"newslist":[
]
},
{ "title":"mbc",
"imgurl":"http://asdfasdf",
"newslist":[
]
}
];
let [,mbc] = news;
let {title, imgurl} = mbc;
console.log(title,imgurl);
let [,{title,imgurl}] = news;
console.log(title,imgurl);
function getNewsList([,newslist]){
console.log(newslist);
}
getNewsList(news);
=== Event ===
document.querySelector("div").addEventListener("click",fucntion(evt){
console.log(evt);
});
document.querySelector("div").addEventListener("click",fucntion({target}){
console.log(target.tagName);
});
document.querySelector("div").addEventListener("click",fucntion({type}){
console.log(type);
});
==== SET ====
자료구조 Set - 중복없이 유일한 값을 저장하려고 할때, 이미 존재하는지 체크할 때 유용.
let mySet = new Set();
console.log(toString.call(mySet));
mySet.add("crong");
mySet.add("hary");
mySet.add("chrong");
console.log(mySet.has("crong"));
mySet.forEach(function(v){
console.log(v);
});
mySet.delete("crong");// set에서 삭제
=== WeakSet ===
참조를 가지고 있는 객체만 지정이 가능하다.
객체형태를 중복없이 저장하려고 할때 유용하다.
let arr = [1,2,3,4];
let ws = new WeekSet();
ws.add(arr);
ws.add(111); // error
ws.add("111"); // error
ws.add(null); // error
ws.add(fuction(){});
console.log(ws);
let arr = [1,2,3,4];
let arr2 = [5,6,7,8];
let obj = {arr, arr2};
let ws = new WeekSet();
ws.add(arr);
ws.add(arr2);
ws.add(obj);
arr = null;
arr2 = null;
console.log(ws);
console.log(ws.has(arr), ws.has(arr2));
==== map & WeakMap ====
Array --> set,weakset
Object --> map, weakmap
map은 key/value의 구조(dictionary)
let wm = new WeakMap();
let myfun = function(){};
// 이 함수가 얼마나 실행됐는지를 알려고 할때
wm.set(myfun,0);
console.log(wm);
let count = 0;
for(let i=0;i<10;i++){
count = wm.get(myfun); // get value
count++;
wm.set(myfun, count);
}
console.log(wm.get(myfun)); // 10
myfun = null;
console.log(wm.get(myfun)); // undefined
console.log(wm.has(myfun)); // false
=== WeakMap 활용 --> private ===
function Area(height, width){
this.height = height;
this.width = width;
}
Area.prototype.getArea = function(){
return this.height * this.width;
}
lget myarea = new Area(10,20);
console.log(myarea.getArea());
console.log(myarea.height);
=== weakmap의 전역변수를 이용 ===
const wm = new WeakMap();
function Area(height,width){
wm.set(this, {height, width});
}
Area.prototype.getArea = function(){
const {height, width} = wm.get(this);
return height * width;
}
lget myarea = new Area(10,20);
console.log(myarea.getArea());
console.log(myarea.height);
//
console.log(wm.has(myarea));// true;
myarea = null;
console.log(wm.has(myarea));// false;
// Garbage Collection
==== 실습.Destructuring and Set 활용 ====
=== lotto번호만들기. ===
- 유일한값을 추출하는 과정에서 Set을 사용합니다.
- getRandomNumber함수에 변수를 전달하는 과정에서 destructuring을 사용해봅시다.
const SETTING = {
name : "LUCKY LOTTO!",
count : 6,
maxNumber : 45
}
function getRandomNumber(maxNumber) {
// 랜덤한 유일한 숫자값을 추출
}
=== Answer ===
const SETTING = {
name : "LUCKY LOTTO!",
count : 6,
maxNumber : 45
}
function getRandomNumber(maxNumber) {
// 랜덤한 유일한 숫자값을 추출
}
==== Template처리 ====
json으로 응답을 받고,
javascript object로 변환한 후에 어떠한 데이터처리 조작을 한 후에 dom에 추가!
데이터 + HTML문자열의 결합이 필요하기 때문에
const data = [
{
name : 'coffee-bean',
order : true,
items : ['americano', 'milk', 'green-tea']
},
{
name : 'starbucks',
order : false,
}
];
const template = `welcome ${data[0].name} !!`
console.log(template);
=== Tagged template literals ===
const data = [
{
name : 'coffee-bean',
order : true,
items : ['americano', 'milk', 'green-tea']
},
{
name : 'starbucks',
order : false,
}
];
// Tagged template literals
function fn(tags, name, items) {
//console.log(tags);
if(typeof items === "undefined") {
items = "주문가능한 상품이 없습니다.";
}
return (tags[0] + name + tags[1] + items + tags[2]);
}
const template = fn`welcome ${data[0].name}!!
주문가능항목
${data[0].items}`;
//console.log(template);
data.forEach(v => {
let template = fn`welcome ${v.name}!!
주문가능항목
${v.items}`;
console.log(template);
document.querySelector('#message').innerHTML += template;
});
==== Arrow Function ====
setTimeout(function(){
console.log("settimeout");
}, 1000);
let newArr = [1,2,3,4,5].map(function(value, index, object) {
return value * 2;
});
let newArr3 = [1,2,3,4,5].map( (v) => (v * 3));
let newArr4 = [1,2,3,4,5].map( v => v * 4);
=== this context of Arrow function ===
const myObj = {
runTimeout() {
setTimeout(function(){
this.printData(); // this는 window( in browser).
// bind(this)를 통해서 myObj로 bind
}.bind(this), 200);
},
printData(){
console.log('hi codesquad!');
}
}
myObj.runTimeout();
== arrow function에서 this ==
const myObj = {
runTimeout() {
setTimeout(()=>{
this.printData();
}, 200);
},
printData(){
console.log('hi codesquad!');
}
}
myObj.runTimeout();
== DOM Event도 같은 방식 ==
const el = document.querySelector("p");
const myObj = {
register() {
el.addEventListener("click", (evt) => {
this.printData(evt.target); // bind없이 this
});
},
printData(el) {
console.log('clicked!!', el.innerText);
}
}
myObj.register();
==== default parameters ====
function sum(value, size=1){
return value * size;
}
console.log(sum(3));
=== object ===
function sum(value, size={value:1}){
return value * size.value;
}
console.log(3, {value:0}));
==== rest parameters ====
function checkNum(){
const argArray = Array.prototype.slice.call(arguments);
console.log(argArray);
console.log(toString.call(arguments));
const result = argArray.every((v) => typeof v === "number");
console.log(result);
}
const result = checkNum(10,2,3,"55");
const result = checkNum(10,2,3,4,5,"55");
rest parameters
function checkNum(...argArray){
const result = argArray.every((v) => typeof v === "number");
console.log(result);
}
===== ES6 class =====
function Health(name){
this.name = name;
}
Health.prototype.showHealth = function(){
console.log(this.name + "님 안녕하세요");
}
==== constructor ====
class Health {
constructor(name, lastTime) {
this.name = name;
this.lastTime = lastTime;
}
showHealth() {
console.log("안녕하세요" + this.name);
}
}
const myHealth = new Health("crong");
==== Object assign 메서드 ====
ES5에 추가됨
const healthObj = {
showHealth : function() {
console.log("오늘은 운동시간 : " + this.healthTime);
}
}
const myHealth = Object.create(healthObj);
myHealth.healthTime = "11:20";
myHealth.name = "mama";
console.log(myHealth);
=== Object Assign ===
const healthObj = {
showHealth : function() {
console.log("오늘은 운동시간 : " + this.healthTime);
}
}
const myHealth = Object.assign(Object.create(healthObj),{
name : "mama",
lastTime : "11:20"
});
myHealth.healthTime = "11:20";
myHealth.name = "mama";
console.log(myHealth);
=== Object assign으로 immutable객체 만들기 ===
const previousObj = {
name : "mama",
lastTime : "11:20"
}
const myHealth = Object.assign({}, previousObj, {
"lastTime" : "12:30"
});
console.log("myhealth is ", myHealth);
=== setPrototypeOf ===
명확하고 단순한 것을 유지함.
const healthObj = {
showHealth : function() {
console.log("오늘 운동시간 : " + this.healthTime);
}
}
const myHealth = {
name : "mama",
lastTime : "11:20"
}
const newobj = Object.setPrototypeOf(myHealth, healthObj);
console.log("myhealth is ", myHealth);
console.log("newobj is ", newobj);
=== Object setPrototypeOf로 객체간 prototype chain생성하기 ===
//parent
const healthObj = {
showHealth : function() {
console.log("오늘 운동시간 : " + this.healthTime);
},
setHealth : function(newTime) {
this.healthTime = newTime;
}
}
// child obj
const healthChildObj = {
getAge : function() {
return this.age;
}
}
const lastHealthObj = Object.setPrototypeOf(healthChildObj, healthObj);
const childObj = Object.setPrototypeOf({
age: 22
}, healthChildObj);
console.log("childObj is ", childObj);
==== Module(export & import)의 이해 ====
아직은 Browser 에서는 사용 못 하고 있음.
import log, { getTime, getCurrentHour } from './myLogger';
log('my first test data');
log(`getTime is ${getTime()}`);
log(`current hour is ${getCurrentHour()}`);
export function log(data){
console.log(data);
}
export const getTime = () => {
return Date.now();
}
export const getCurrentHour = () => {
return (new Date).getHours();
}
==== Proxy ====
const myObj = { name:'mama', changedValue:0 };
const proxy = new Proxy(myObj, {
get: function(target, property, receiver){
console.log('get Value')
// if(property in target) ... 없는 프러퍼티에 대해서 Error처리를 할 수 있다.
//return target[property];
return Reflect.get(target, property, receiver);
},
set: function(target, property, value, receiver){
console.log('set value');
console.log('target : ', target);
console.log('value :', value);
target['changedValue']++;
target[property] = value;
return true;
}
});
console.log('myObj : ', myObj);
console.log('proxy : ', proxy);
proxy.name = 'crong';
console.log('proxy : ', myObj);
===== 기타정보들 =====
==== IIFE[Immediately Invoked Function Expression] ====
“Iffy”라고 발음.
즉시호출함수표현...
기초 지식은 많이 있겠지만, JavaScript에서는 function도 하나의 data type 이다. 따라서 파라메터로 넘겨주는 것이 가능하다.
또한 JavaScript에서는 function의 이름을 생략할 수 있다.
(function(d){
let myday = new Date(d);
myday.setFullYear(myday.getFullYear() + 1);
return myday;
})('2018.08.10');
function f(a){
asdfasdfgo 일...
}
;
f('asdf');
f(
(function(d){
let myday = new Date(d);
myday.setFullYear(myday.getFullYear() + 1);
return myday;
})('2018.08.10')
);
f('asd')
==== About DATE ====
=== 날짜 포맷(yyyymmdd)출력하기(datepicker) ===
(function(p_date){
let startDate = new Date(p_date);
startDate.setDate(startDate.getDate() + 1);
return $.datepicker.formatDate('yy.mm.dd', startDate);
})("2018.09.12")
말일 구하기
(function(day){
let lastday = new Date(day.substring(0,4), day.substring(4,6)-1+1, 0);
return $.datepicker.formatDate('yymmdd', lastday);
})(getStdDate())
=== 날짜 더하기 ===
((new Date()).getFullYear() + 1) + ".12.31"
=== 요일명 ===
var d = new Date()
d.toLocaleDateString('ko-KR', {weekday: 'long'})
==== 클로저(Closure) ====
=== jQuery에서 사용하는 클로저 ===
$(function() {
var selections = [];
$(".niners").click(function() { // 이 클로저는 selections 변수에 접근합니다.
selections.push(this.prop("name")); // 외부 함수의 selections 변수를 갱신함
});
});
=== Private구현방법. ===
예제는 더글라스 크락포드(Douglas Crockford)에 의해 처음 시연되었습니다:
function celebrityID() {
var celebrityID = 999;
// 우리는 몇개의 내부 함수를 가진 객체를 리턴할것입니다.
// 모든 내부함수는 외부변수에 접근할 수 있습니다.
return {
getID: function() {
// 이 내부함수는 갱신된 celebrityID변수를 리턴합니다.
// 이것은 changeThdID함수가 값을 변경한 이후에도 celebrityID의 현재값을 리턴합니다.
return celebrityID;
},
setID: function(theNewID) {
// 이 내부함수는 외부함수의 값을 언제든지 변경할 것입니다.
celebrityID = theNewID;
}
}
}
var mjID = celebrityID(); // 이 시점에, celebrityID외부 함수가 리턴됩니다.
mjID.getID(); // 999
mjID.setID(567); // 외부함수의 변수를 변경합니다.
mjID.getID(); // 567; 변경된 celebrityID변수를 리턴합니다.
=== 비꼬기 ===
클로저가 갱신된 외부함수의 변수에 접근함으로써, 외부 함수의 변수가 for문에 의해 변경될 경우 의도치 않은 버그가 발생할 수 있습니다.
function celebrityIDCreator(theCelebrities) {
var i;
var uniqueID = 100;
for (i=0; i
위의 예제에서, 익명의 내부함수가 실행될 시점에 i의 값은 3입니다(배열의 크기만큼 증가한 값). 숫자 3은 uniqueID에 더해져 모든 celebritiesID에 103을 할당합니다. 그래서, 기대(100,101,102)와 달리 모든 리턴된 배열의 id=103이 됩니다.
이런 결과가 나타난 이유는, 앞서 언급했듯이 클로저는(이 예제에서 내부의 익명함수) 외부 변수에 대해 값이 아닌 참조로 접근하기 때문입니다. 즉, 클로저는 최종 갱신된 변수(i)에 대해서만 접근할 수 있으므로, 외부 함수가 전체 for문을 실행하고 리턴한 최종 i의 값을 리턴하게 됩니다. 100+3=103.
=== IIFE사용하여 수정하기 ===
이런 부작용을 고치기 위해서 “즉시 호출된 함수 표현식(Immediately Invoked Function Expression. IIFE)”를 사용할 수 있습니다.
function celebrityIDCreator(theCelebrities) {
var i;
var uniqueID = 100;
for (i=0; i
==== 화살표함수와 this ====
ES5에서 가장 헷갈리는것이 바로 this의 범위이다. 클로저가 생성한 컨텍스트로 인해 this가 this가 아닌 상황이 발생하여 “that = this, self = this”와 같은 패턴을 사용해야만 했다.
var self = this
$('.btn').click(function(event){
self.sendData()
})
또는 “.bind(this)”를 사용해 this를 현재 컨텍스트와 수동으로 바인딩하기도 했었다.
$('.btn').click(function(event){
this.sendData()
}.bind(this))
화살표 함수를 사용하면 이러한 번거로움을 해소할 수 있다.
$('.btn').click((event) =>{
this.sendData()
})
화살표 함수는 함수 표현식을 간략하게 표기하도록도 해주지만 this의 범위를 함수를 감싸는 코드와 동일하게 유지해줌으로써 기존의 클로저로 인한 번거로움을 많이 해소해 준다.
{{http://chanlee.github.io/categories/|ChanLee}}