Created by 이항희 / blog.javarouka.me
그 다음 많이 대중화된 5판(?)
핫이슈가 된 6판
오늘 다룰 것은 5판
ECMA International 에서 비공개 결정됨
Why?
언어 명세가 기존에 비해 복잡하고 많다
너무 급진적이고 격렬한 변화
이거 복잡해서 쓰겠나...실무자 이외의 그룹은 언어 개선안도 내지 마라
By Douglas Crockford
(JSON DataFormat Popularised, JSLint Contributor)JavaScript는 전문가에게 맡기기엔 너무나 소중하다
By Jeremy Ashkenas
(Backbone.js, Underscore, CoffeeScript Contributor)
결국 4판은 폐기되고
"ECMAScript Harmony" (ECMAScript 6판)
으로 일부 기능만 흡수되어 공개.
그 뒤 2009년 12월 5판이 공개.
편의성 위주와 그동안 부실했던 것을 보충하려는 것들 위주
모두 볼 순 없고 유용한 것들에 대해서
JSON 변환을 Native로 지원
그전에는 eval 등의 평가 함수나 별도의 서드파티 라이브러리를 사용해야만...
(function() {
var jsonString = "{ \"hello\": \"world\" }";
// eval 사용
// eval(json 문자열);
var jsn = eval("("+jsonString+")");
alert(JSON.stringify(jsn, null, ' '));
})();
RUN
(function() {
var jsonString = "{ \"hello\": \"world\" }";
// 동적 함수 사용
// new Function(json 문자열을 리턴하는 소스 문자열);
var jsn = new Function("return " + jsonString)();
alert(JSON.stringify(jsn, null, ' '));
})();
RUN
!function() {
var jsonString = "{ \"hello\": \"world\" }";
// Native JSON Object
var jsn = JSON.parse(jsonString)
alert(JSON.stringify(jsn, null, ' '));
}();
RUN
엄격한 코드 검사 및 수행 모드
여러 언어적 결함을 전부 오류 처리.
보다 견고한 프로그래밍을 가능하게 해줍니다.
// 전역에 적용
"use strict"
// 함수 스코프에만 적용
function iamStrict() {
"use strict"
};
눈에 띄는 몇가지만 소개해 보겠습니다.
// All Syntax Error!
var eval = 17;
var arguments = "hello";
++eval;
arguments++;
function x(eval) { }
function arguments() { }
// x 속성이 중복
var obj = { x: 1, x: 2 }; // Syntax Error!
// 인자 이름 중복 불가
function sum(a, a, b) { // Syntax Error!
return a + a + b;
}
implictVar = 10 // Syntax Error!
function fn() {
"use strict"
hello = "world"; // Syntax Error
}
// Syntax Error
with({ hello: "world" }) {
console.log(hello);
}
delete Object // Syntax Error
delete String // Syntax Error
delete Object.prototype // Syntax Error
delete Element // Syntax Error
delete undefined // Syntax Error
객체의 원본
JavaScript 객체는 전부 Object 생성자의 prorotype이 원본
Object.getPrototypeOf(obj)
!function() {
var today = new Date();
// ECMA Script 3nd -
alert("__proto__ # " + (today.__proto__ === Date.prototype));
alert("constructor.prototype # " + (today.constructor.prototype === Date.prototype));
// ECMA Script 5th +
alert("Object.getPrototypeOf # " + (Object.getPrototypeOf(today) === Date.prototype));
}();
RUN
!function() {
var javacafe = {};
var javacafe = new Object();
var JavacafeConstructor = function() {};
JavacafeConstructor.prototype = {
constructor: JavacafeConstructor
// etc ...
};
javacafe = new JavacafeConstructor();
}();
Object.create(prototype)!
!function() {
var step = Object.create({
"hello": "world",
"hi": "안녕"
});
alert(step.hi);
alert(step.hello);
}();
RUN
!function() {
var obj1 = {}, obj2 = new Object(), obj3 = Object.create(null);
var byLiteral = Object.getPrototypeOf(obj1),
byConst = Object.getPrototypeOf(obj2),
byCreate = Object.getPrototypeOf(obj3);
alert("byLiteral # " + byLiteral);
alert("byConst # " + byConst);
alert("byCreate # " + byCreate);
}();
RUN
불변 객체 생성
(function() {
// Object.freeze
var java = { study: "재미있어요" };
Object.freeze(java); // 객체 불변으로 만들기
java.study = "하기싫어요";
alert("java.study : " + java.study); // 변하지 않음
java.play = "놀러갑시다";
alert("java.play : " + java.play); // 새 속성 추가 불가
delete java.study;
alert("java.study : " + java.study); // 삭제도 불가
})();
RUN
객체의 모든 속성명을 얻고싶은데...
// 객체의 속성명 singer, leader, video 를 가져오고 싶다.
var PinkLUV = {
singer: "Apink",
leader: "Chorong, Park",
title: "LUV",
video: "www.youtube.com/watch?v=8dVjSvLzD1I"
}
for - in
!function() {
var PinkLUV = {
singer: "Apink",
leader: "Chorong, Park",
title: "LUV",
video: "www.youtube.com/watch?v=8dVjSvLzD1I"
},
keys = [];
for(var k in PinkLUV) {
if(!PinkLUV.hasOwnProperty(k)) continue;
keys.push(k);
}
alert(keys);
}();
RUN
Object.keys
!function() {
var PinkLUV = {
singer: "Apink",
leader: "Chorong, Park",
title: "LUV",
video: "www.youtube.com/watch?v=8dVjSvLzD1I"
};
alert(Object.keys(PinkLUV));
}();
RUN
(function() {
var Browser = {
get name() { return this.defaultBrowser; },
set name(v) { this.defaultBrowser = v + " 를 사용중입니다."; }
};
Browser.name = "Internet Explorer"; // set.
alert(Browser.name); // get.
Browser.name = "Chrome"; // set.
alert(Browser.name); // get.
})();
RUN
(function() {
Object.defineProperty(객체, 키이름, 디스크립터);
})();
!function() {
var Coupang = {
name: "쿠팡"
};
Object.defineProperty(Coupang, 'age', {
value: 4
});
alert(Coupang.name);
alert(Coupang.age);
// !!!!????
alert(JSON.stringify(Coupang));
alert(Object.keys(Coupang));
}();
RUN
!function() {
var Coupang = {};
Object.defineProperty(Coupang, 'name', {
value: "쿠팡",
writable: false
});
Coupang.name = "티켓몬스터";
alert(Coupang.name);
}();
RUN
try {
var Coupang = {};
Object.defineProperty(Coupang, 'name', {
value: "쿠팡", configurable: false
});
alert("keys > [ " + Object.keys(Coupang) + " ]");
Object.defineProperty(Coupang, 'name', {
value: "티켓몬스터", enumerable: true
});
alert(Object.keys(Coupang));
}
catch(ex) {
alert(ex);
}
RUN
try {
var Coupang = {};
Object.defineProperty(Coupang, 'name', {
value: "쿠팡", configurable: true, enumerable: true
});
alert("keys > [ " + Object.keys(Coupang) + " ]");
Object.defineProperty(Coupang, 'name', {
value: "티켓몬스터", enumerable: true
});
alert("Coupang.name > " + Coupang.name);
}
catch(ex) {
alert(ex);
}
RUN
function ECommerce() {
var name = "쿠팡";
Object.defineProperty(this, 'descriptionText', {
set: function(_name) { name = _name },
get: function() { return name + ", 한국의 E-커머스 회사입니다." }
});
}
var eCommerce = new ECommerce();
alert(eCommerce.descriptionText);
eCommerce.descriptionText = "티켓몬스터";
alert(eCommerce.descriptionText);
RUN
var javarouka = Object.create({}, {
name: {
value: "이항희",
enumerable: true
},
age: {
value: 36,
writable: true,
configurable: true
}
});
alert(javarouka.name + " / " + javarouka.age);
// try modify properties
javarouka.name = "JavaRouka";
javarouka.age = 29;
alert(javarouka.name + " / " + javarouka.age);
RUN
다양한 메서드 추가
인자로 준 요소가 해당 배열의 어느 인덱스인지 반환.
없다면 -1.
!function() {
var javarouka = { name: "이항희", job: "programer", gender: "male" },
sora = { name: "강소라", job: "actress", gender: "female" },
suzi = { name: "수지", job: "singer", gender: "female" };
var groups = [ javarouka, sora, suzi ];
var index = groups.indexOf(suzi);
alert("suzi's index " + index);
}();
RUN
하나라도 true를 반환하면 true.
!function() {
var groups = [
{ name: "이항희", job: "programer", gender: "male" },
{ name: "강소라", job: "actress", gender: "female" },
{ name: "수지", job: "singer", gender: "female" }
];
// 남자가 한명이라도 있는지?
var r = groups.some(function(v){ return v.gender === 'female'; });
alert("남자가 있나? " + r);
// 프로그래머가 한명이라도 있는지?
r = groups.some(function(v){ return v.job === 'programer'; });
alert("프로그래머가 있나? " + r);
}();
RUN
some 과 비슷하나 전부 true를 반환해야 true.
(function() {
var groups = [
{ name: "이항희", job: "programer", gender: "male" },
{ name: "강소라", job: "actress", gender: "female" },
{ name: "수지", job: "singer", gender: "female" }
];
// 전부 남자...?
var r = groups.every(function(v){ return v.gender === "male" });
alert("전부 남자? " + r);
})();
RUN
배열 요소를 순회하며 반환값으로 구성되는 새 배열을 반환.
(function() {
var groups = [
{ name: "이항희", job: "programer", gender: "male" },
{ name: "강소라", job: "actress", gender: "female" },
{ name: "수지", job: "singer", gender: "female" }
];
var r = groups.map(function(v){
return v.name + " : " + v.job;
});
alert(JSON.stringify(r, null, ' '));
})();
RUN
배열의 모든 요소에 대해 지정된 콜백을 호출.
콜백 함수의 반환 값은 다음 콜백 함수 호출시 인수로 제공된다.
!function() {
// 초기누적값은 옵션.
// 초기누적값이 없다면 첫 콜백 실행시 첫번째 요소를 사용하며 콜백 호출은 두번째부터.
arrayObj.reduce(callback[, 초기누적값])
// 각 콜백에 전달되는 인자
// 0. 전 콜백에서 반환된, 누적값 혹은 실행 시 준 초기값
// 1. 순회하는 현재 요소
// 2. 요소 인덱스
function callback(누적값, 현재값, 인덱스) { /* ... */ }
}();
!function() {
var groups = [
{ name: "이항희", job: "programer", gender: "male" },
{ name: "강소라", job: "actress", gender: "female" },
{ name: "수지", job: "singer", gender: "female" }
];
var genderCount = groups.reduce(function(accumulated, current) {
if(!( current.gender in accumulated )) accumulated[ current.gender ] = 0;
accumulated[ current.gender ] += 1;
return accumulated;
}, {});
alert(JSON.stringify(genderCount, null, ' '));
}();
RUN
String.trim Native Support
Immutable 'undefined' type
currentTimeMillis
(function() {
var requireTrim = " 이제 섹션 다 끝나갑니다~ ";
alert("["+requireTrim.trim()+"]"); // 아주 빠르다.
// 전 버전에서는 undefined 값을 마음대로 바꿀 수 있었지만
// 이제는 불가능
undefined = 1000;
alert(typeof undefined);
// 현재 타임스탬프 값 반환
alert(Date.now());
})();
RUN