JavaScript 이해하기
: 자바스크립트 초급, 그 이후
이종은

이종은
- Yo Studio
- JavaScript
- Titanium (tidev.kr / NIPA open frontier)
☝
________ is the one programming language
to learn if you can learn only one
JS가 싫은 이유
- 구린 부분이 있다
- DOM은 형편없다
- Java, C#, C++, Phython, Ruby.. 가 아니다
- 그런데도 많이 쓰인다
The World's Most Misunderstood Programming Language
Kyle Simpson
JS는 어떻게 동작하나요?
누구도 알려주지 않았다
왜 그런지 모르지만 저렇게 쓰면 되는구나
아! 그렇기 때문에 저렇게 써야 하는구나!
JS는 객체지향 언어다?
네! 5개 빼고 전부 객체이다.
객체
key - value 쌍의 모음
RUN
var obj = {
title : "Advanced JS",
attendee : 30,
isBad : function(){
return false;
}
}
원시값
primitive type
- string
- number
- boolean
- null
- undefined
Primitive Wrapper
string, number, boolean은 primitive wrapper를 통해 쉽게 객체로 변환
RUN
"I am a boy".length;
(3).toFixed(2);
true.toString();
복사
RUN
var p = 1;
var copyOfP = p;
p = 3;
console.log(copyOfP);
var myObject = {};
var copyOfMyObject = myObject;
myObject.foo = 'bar';
console.log(copyOfMyObject.foo);
비교 연산자 == vs ===
RUN
var one= 1, oneString = '1' , t = true;
console.log(one == oneString);
console.log(one == t);
console.log(oneString == t);
console.log(one === oneString);
console.log(one === t);
console.log(oneString === t);
객체 속성 접근방법
var obj = {
name : 'MyObject'
};
var a = 'name';
console.log(obj.name);
console.log(obj["name"]);
console.log(obj[a]);
여는 중괄호의 위치
RUN
function f1(){
return {
name: 'jong'
};
}
function f2(){
return
{
name: 'jong'
};
}
console.log(f1());
console.log(f2());
JS는 어떻게 동작하는가?
(Runtime Concept)
이론적인 모델, 실제로 구현은 엔진에 따라 다르게 많이 최적화되어 있음
RUN
function multiply(a,b){
return a*b;
}
function square(x){
return multiply(x,x);
}
square(2);
|
|
|
|
call stack
one thread == one call stack == one thing at a time
"Run-to-complete"
한번 시작하면 끝을 봐야한다!
중간에 의도적으로 sleep하고 다른 일을 할 수 없다.
JS Runtime은 동시에 두가지 연산을 못해요?
네, 정말입니다.
이벤트 핸들러
RUN
document.getElementById('myBtn').onclick = function(){
console.log('myBtn Click');
};
function g(){
console.log('g');
}
g();
|
|
|
 |
브라우저가 반응 없다가
갑자기 몰아서 응답할때는?
한동안 방응 없는 경우
RUN
document.getElementById('myBtn').onclick = function(){
console.log('myBtn Click');
};
function g(){
doSomething(); // 엄청 오래 걸리는 작업
}
g();
|
|
|
 |
RUN
setTimeout(function(){
},x)
x초 후 함수를 실행
타이머
RUN
function f(){
console.log('f - done');
}
function g(){
setTimeout(function(){
console.log('g - timeout')
},3000);
f();
}
g();
|
|
|
 |
RUN
setTimeout(function(){
},x)
x초 후 함수를 실행
하는 것이 아니라 x초 후에 Queue에 넣음
RUN
function f(){
console.log('f - done');
}
function g(){
$.ajax({
url: "test.html"
}).done(function() {
console.log('g - ajax - done')
});
f();
}
g();
|
|
|
 |
전역 변수, 지역 변수
RUN
var g = 3;
function f(){
var h = 4;
}
어떻게 생겼는지 그려봅시다.
RUN
var msg = 'global';
var gmsg = 'wow';
function f(){
var msg = 'local';
return msg + gmsg;
}
f();
즉시 실행 함수
(function(){
})();
인자 전달
// 방법 1
(function(x){
})(a)
Return 값
// 방법 1
var result = (function(){
return 4;
})();
// 방법 2
var result = function(){
return 4;
}();
방법2는 뒤에 괄호를 눈여겨 보지 않으면 오해의 소지가 있다.
함수 선언문
RUN
f();
function f(){
console.log('please');
};
익명 함수 표현식
RUN
f();
var f = function (){
console.log('please');
};
RUN
function f(){
console.log(a);
return;
}
RUN
function f(){
console.log(a);
return;
var a=3;
}
선언문 vs. 표현식
// 기함수 선언문
function me(){
}
// 기명 함수 표현식
var a = function me(){
};
Q. global? local?
RUN
function foo() {
var a = b = 0;
}
gmsg는 어떻게 찾은거지?
RUN
var msg = 'global';
var gmsg = 'wow';
function f(){
var msg = 'local';
return msg + gmsg;
}
f();
찾는데 걸리는 시간
RUN
var msg = 'global';
var gmsg = 'wow';
function f(){
var msg = 'local';
for(var i=0;i<100000;i++){
msg+=gmsg;
}
return msg;
}
f();
- scope에 자동으로 들어가는 변수
- 해당 함수를 실행시킨 Object
RUN
function(){
console.log(this);
}
RUN
var value = 'global';
var obj = {
value : 'local',
foo : function(){
console.log( this.value );
}
}
obj.foo();
RUN
function MyObj(){
console.log(this);
}
var obj = new MyObj();
Q. 결과는?
RUN
var value = 'global';
var obj = {
value : 'local',
foo : function(){
console.log( this.value );
}
}
var foo2 = obj.foo;
foo2();
예외 : call, apply
RUN
var value = 'global';
var obj = {
value : 'local',
foo : function(){
console.log( this.value );
}
}
var foo2 = obj.foo;
foo2.call(obj);
foo2.apply(obj);
메모리 관리 기본 3단계
- 필요할 때 할당한다.
- 사용한다. (읽기, 쓰기)
- 필요없어지면 해제한다.
JS gabage collector
- 우리가 임의로 동작시킬 수 없다
- 브라우저가 알아서 한다
RUN
function f(){
var arr = new Array(1000);
}
f();
ref count의 한계
RUN
function f(){
var o = {};
var o2 = {};
o.a = o2;
o2.a = o;
return "azerty";
}
f();
mark and swipe
닿을 수 없는 오브젝트 = 더 이상 필요 없는 오브젝트
RUN
var outerValue = 'ninja';
var later;
function outerFunction(){
var innerValue = 'samurai';
function innerFunction(){
console.log(innnerValue);
console.log(outerValue);
}
later = innerFunction;
}
outerFunction();
later();
실습 1. 손으로 그려보면서 결과 예측
RUN
var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
nodes[i].addEventListener('click', function() {
console.log('You clicked element #' + i);
});
}
실습 2. 정상적으로 동작하도록
함수를 다른 함수의 인자로 전달 할 수 있다?
자바스립트에서 함수는 1급 클래스이다.
function find(callback){
var found;
// 무언가를 찾아서 found에 저장
if(found){
callback(found);
}
}
function hide(node){
node.style.display= "none";
}
find(hide);
callback HELL
RUN
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// value4를 다루는 작업 수행
});
});
});
});
promise
RUN
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// value4를 다루는 작업 수행
})
.catch(function (error) {
// 위 step에서 발생하는 모든 에러 처리
})
.done();
promise - Q
RUN
function requestOkText(url) {
return Q.Promise(function(resolve, reject, notify) {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
function onload() {
if (request.status === 200) {
resolve(request.responseText);
} else {
reject(new Error("Status code was " + request.status));
}
}
function onerror() {
reject(new Error("Can't XHR " + JSON.stringify(url)));
}
function onprogress(event) {
notify(event.loaded / event.total);
}
});
}
Object Oriented
(JS로 클래스)
글로벌을 더립히지 마라
RUN
function Parent() {}
function Child() {}
var some_var = 1;
var module1 = {};
module1.data = {a: 1, b: 2};
var module2 = {};
네임스페이스 패턴
RUN
var MYAPP = {};
MYAPP.Parent = function(){};
MYAPP.Child = function(){};
MYAPP.some_var = 1;
MYAPP.modules = {};
MYAPP.modules.module1 = {};
MYAPP.modules.module1.data = {a: 1, b: 2};
MYAPP.modules.module2 = {};
여러개의 파일에서..
RUN
//방법 1
var MYAPP = {};
//방법 2
if(typeof MYAPP === "undefined"){
var MYAPP = {};
}
//방법 2-1
var MYAPP = MYAPP || {};
실습 : 비공개로 만들기
RUN
// 객체생성 방법1
var myModule = {
name : 'literal',
getName : function(){
return this.name;
}
}
console.log(myModule.name);
|
|
RUN
// 객체생성 방법2
function Gadget(){
this.name = 'new Func';
this.getName = function (){
return this.name;
};
}
var toy = new Gadget();
console.log(toy.name);
|
실습 : 비공개로 만들기 (A1)
RUN
// 객체생성 방법1
var myModule = {
name : 'literal',
getName : function(){
return this.name;
}
}
console.log(myobj.name);
|
|
RUN
var myModule = (function(){
var name = 'literal';
return {
getName : function(){
return name;
}
}
})();
console.log(myModule.name);
console.log(myModule.getName());
|
실습 : 비공개로 만들기 (A2)
RUN
// 객체생성 방법2
function Gadget(){
this.name = 'new Func';
this.getName = function (){
return this.name;
};
}
var toy = new Gadget();
console.log(toy.name);
|
|
RUN
function Gadget(){
var name = 'new Func';
this.getName = function (){
return name;
};
}
var toy = new Gadget();
console.log(toy.name);
console.log(toy.getName());
|
메모리를 생각해보면..
RUN
function Gadget(){
var name = 'new Func';
this.getName = function (){
return name;
};
}
var toy = new Gadget();
var toy2 = new Gadget();
var toy3 = new Gadget();
var toy4 = new Gadget();
new 할때마다 getName이 메모리에 할당된다.
getName은 변하지 않고 모든 인스턴스가 똑같은 동작을 하는데?
function Gadget(){
var name = 'new Func';
this.getName = function (){
return name;
};
}
var toy = new Gadget();
var toy2 = new Gadget();
var toy3 = new Gadget();
var toy4 = new Gadget();
RUN
function MyObj(){
this.doSomething = function (){
console.log('done');
};
}
MyObj.prototype = {
doSomethingInProto : function (){
console.log('doneInProto');
}
}
var obj = new MyObj();
obj.doSomething();
obj.doSomethingInProto();
var obj2 = new MyObj();
RUN
function MyObj(){
this.doSomething = function (){
console.log('done');
};
}
MyObj.prototype = {
doSomething : function(){
console.log('doneInProto');
}
}
var obj = new MyObj();
obj.doSomething();
var obj2 = new MyObj();
strict mode
"use strict"
더 많은 예외를 발생시켜
코딩실수나 안전하지 않은 방식,
혼란스러운 방식 원천 차단
setInterval의 비밀?
RUN
var cnt = 0;
setInterval(function(){
cnt++;
console.log(cnt);
},1000);
참고 자료
인용에 해당할 경우는 각 페이지 하단 우측에 링크를 넣었습니다.
그외 참고자료는 아래와 같습니다.
감사합니다.