SlideShare a Scribd company logo
1 of 38
Download to read offline
프론트엔드 스터디
CH.05. Closure, OOP
1. Closure와 가까워지기
2. 객체지향과 프로토타입
Closure
함수를 선언할때 만들어지는 유효범위
함수는 클로저를 통해서 자신이 선언될 때 속해 있던 유효
범위 내의 변수와 함수를 사용할 수 있고, 변수의 경우 그
값을 변경할 수도 있다.
흥미로운건 함수를 선언한 후에 언제든지, 심지어 함수가
속해 있던 유효 범위가 사라진 후에도 그 함수를 호출할 수
있는 경우가 생기게 된다
Closure – 간단한 클로저
var outerValue = 'outerValue';
function outerFunction() {
console.log(outerValue == 'outerValue');
}
outerFunction();
외부에 있는 변수와 함수가 모두 전역 유효 범위에 선언되어
있고, 실제로는 클로저에 해당하는 전역 유효 범위는 페이지가
로드되어 있는 한 사라지지 않기 때문에 그다지 흥미로운
코드는 아니다.
Closure – 간단하지 않은 클로저
var outerValue = 'outerValue';
var later;
function outerFunction() {
var innerValue = 'innerValue'
function innerFunction() {
console.log(outerValue);
// innerValue는 있을까?
console.log(innerValue);
}
later = innerFunction;
}
outerFunction();
later();
클로저는 함수가 선언된 시점의 유효
범위에 있는 모든 함수와 변수를 가지고
있으며, 필요할 때 그것들을 사용할 수 있다.
Closure – 심화
var outerValue = 'outerValue';
var later;
function outerFunction() {
// 함수 내에 변수를 하나 선언한다. 이 변수의 유효 범위는 함수 내부로 제한이 되고,
// 함수 외부에서는 접근할 수 없다.
var innerValue = 'innerValue'
// inner 함수에 매개변수를 추가한다.
function innerFunction(paramValue) {
console.log(outerValue);
console.log(innerValue);
console.log(paramValue); // 매개변수를 볼 수 있는지 테스트
console.log(tooLate); // 클로저가 함수가 선언된 이후에 정의된 변수를 볼 수 있는지 테스트
}
later = innerFunction;
}
console.log(tooLate); // outer closure에서는 tooLate를 쓸 수 없다.
// innerFunction을 정의한 후에 변수를 선언
var tooLate = 'tooLate';
outerFunction();
later('paramValue');
Closure – Closure를 사용하지 않고 값을 가지고 있을 때
var uniqueId = function(){
if(!arguments.callee.id){
arguments.callee.id = 0;
}
return arguments.callee.id++;
}
uniqueId(); // 0
uniqueId(); // 1
uniqueId(); // 2
// id를 0으로 초기화 할 수 있을까?
var uniqueId = function(){
if(!arguments.callee.id){
arguments.callee.id = 0;
}
return arguments.callee.id++;
}
uniqueId(); // 0
uniqueId(); // 1
uniqueId(); // 2
// id를 0으로 초기화 할 수 있을까?
uniqueId.id = 0;
uniqueId(); // 0
Closure – Closure를 사용하지 않고 값을 가지고 있을 때
Closure – Closure를 사용해서 값을 가지고 있을 때
var uniqueId = (function(){
var id = 0;
return function(){
return id++;
}
})();
uniqueId(); // 0
uniqueId(); // 1
uniqueId(); // 2
uniqueId(); // 3
// id를 0으로 초기화 할 수 있을까?
var uniqueId = (function(){
var id = 0;
return function(){
return id++;
}
})();
uniqueId(); // 0
uniqueId(); // 1
uniqueId(); // 2
uniqueId(); // 3
// 0으로 초기화
uniqueId.id = 0 // ?
uniqueId(); // 4
Closure – Closure를 사용했을 때
Closure의
id에는 접근할
수 없다
=> Closure를 통해 모듈화를 할 수 있다.
Closure – 응용 : Private 변수
function DtoObj(initVal) {
var val = initVal;
this.getVal = function () { // this는 새로 만들어진 객체를 가리킴
return val;
};
this.setVal = function(pVal) {
val = pVal;
}
}
var dto = new DtoObj(3);
// dto 객체의 내부 변수는 getter를 통해서만 접근하여 값을 받을 수 있다.
console.log(dto.getVal()); // 3
// dto 객체의 내부 변수는 setter를 통해서만 접근하여 값을 바꿀 수 있다.
dto.setVal(4);
console.log(dto.getVal()); // 4
dto.val = 5;
console.log(dto.getVal()); // 4
Closure – 응용 : success callback
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Closure 예제</title>
</head>
<body>
<button type="button" id="testButton">Go!</button>
<div id="testSubject"></div>
<script src="https://code.jquery.com/jquery-2.2.3.js"></script>
<script>
$('#testButton').click(function () {
var elem$ = $('#testSubject');
elem$.html('로딩 중...');
$.ajax({
url: '/test'
, success: function (data) {
console.dir(this.success);
elem$.html(JSON.stringify(data));
}
});
});
</script>
</body>
</html>
Closure 핵심 정리
1. 내부 함수는 외부 스코프에 선언된 변수를 참조할 수 있다.
2. 클로저는 자신을 생성한 함수보다 더 오래 지속된다.
3. 클로저는 내부적으로 외부 변수에 대한 참조를 저장하고,
저장된 변수를 읽고 갱신할 수 있다.
Javascript에는 자바, C++, C# 등의 class가 없다.
Prototype 기반 언어들에 영감을 받음.
(https://ko.wikipedia.org/wiki/프로토타입_기반_프로그
래밍)
JavaScript는 prototype 객체, 생성자 등을 통해
구현 가능
클래스 기반 vs 프로토타입 기반
function Func(x, y) {
this.x = x;
this.y = y;
}
var func = Func(1, 2);
this === ?
생성자 함수와 this
function Func(x, y) {
this.x = x;
this.y = y;
}
var func = new
Func(1, 2);
this === ?
this === func
=> 인스턴스를 바라본다
When Number is called as a function rather than as a constructor, it
performs a type conversion.
var num = 1;
var num2 = Number(1);
var num3 = new Number(1);
console.log(num === num2);
console.log(num === num3);
console.dir(num);
console.dir(num3);
new 키워드 필수
Number, String 등등에는 안써도 되던데?
Type 변환을 위한 메서드를 추가로 가지고 있을뿐.
new로 생성하지 않으면 instance가 없다.
var func = Func(1, 2);
// func === undefined
Spec.
function GoodWaffle() {
if(!(this instanceof GoodWaffle)) {
return new GoodWaffle();
}
this.tastes = 'yummy';
}
var waffle = new GoodWaffle();
var waffle2 = new GoodWaffle();
console.log(waffle instanceof GoodWaffle);
console.log(waffle2 instanceof GoodWaffle);
New를 강제하는 방법
GoodWaffle.call(new GoodWaffle);
var GoodWaffle = (function(){
var RealWaffle = function(){};
RealWaffle.prototype.xxx = xxx;
return function(){
return new RealWaffle();
}
})();
var waffle = new GoodWaffle();
var waffle2 = new GoodWaffle();
New를 강제하는 방법 -
더블쉐도우
function Person(name) {
this.name = name;
this.getName = function () {
return this.name;
}
this.setName = function (name) {
this.name = name;
}
}
var me = new Person("yb");
console.log(me.getName());
me.setName("new yb");
console.log(me.getName());
공통속성을 추가하는 경우
// Quiz : getName, setName 메서드는
Person에 추가 되었을까? 아니면 me에만 추가
되었을까?
중복되는 영역을 메모리에 올려놓고 사용
-> 메모리 낭비
var personA = new Person("personA");
var personB = new Person("personB");
var personC = new Person("personC");
불필요한 중복
personA.getName = function () {
return 'Hello, ' + this.name;
}
console.log(personA.getName());
console.log(personB.getName());
console.log(personC.getName());
변경이 발생했을 때
Hello, personA
personB
personC
변경된 사항이 적용되지 않는다.
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
Person.prototype.setName = function (name) {
this.name = name;
}
var personA = new Person("personA");
var personB = new Person("personB");
var personC = new Person("personC");
console.log(personA.getName());
console.log(personB.getName());
console.log(personC.getName());
공통속성을 추가하는 경우
– Prototype을 이용
Instance마다 개별적으로
가져야 할 프로퍼티
공통으로 가져야 할
프로퍼티
cf. Prototype을
사용하지 않은 경우
Prototype 참조
변경이 발생했을 때
Person.prototype.getName = function () {
return 'Hello, ' + this.name;
}
console.log(personA.getName());
console.log(personB.getName());
console.log(personC.getName());
Hello, personA
Hello, personB
Hello, personC
Prototype을 참조하고 있는
다른 모든 Instance에도 모두 적용
Prototype의 몇 가지 속성
name : name / hasOwnProperty : true
name : getName / hasOwnProperty : false
name : setName / hasOwnProperty : false
for (var obj in personA) {
console.log('name : ', obj, ' / hasOwnProperty : ' +
personA.hasOwnProperty(obj));
}
- 마치 자신의 속성처럼 열거할 수 있다.(for in 사용)
- hasOwnProperty() 메서드를 사용해 소유여부(자신이
소유하고 있는지, prototype으로 참조하는지)를 확인할
수 있다.
function Circle(r) {
this.r = r;
}
Circle.prototype.PI = 3.14;
Circle.prototype.getArea = function () {
return 2 * this.r * this.PI;
}
var r2 = new Circle(2);
console.log(r2.getArea());
var r3 = new Circle(3);
console.log(r3.getArea());
var r3Alien = new Circle(3);
r3Alien.PI = 4.74; // PI 재정의
console.log(r3Alien.getArea());
내부의 property가 있는 경우에 prototype을 참고하지 않는다.
이런 경우를 다른 property가 가렸다(shadows) 혹은
숨겼다(hides)라고 한다
- Prototype property가 참조되지 않을 수 있다.
Function.prototype.addMethod = function (name, func) {
if(!this.prototype[name]) {
this.prototype[name] = func;
}
}
function Person(name) {
this.name = name;
}
Person.addMethod('setName', function(name) {
this.name = name;
});
Person.addMethod('getName', function () {
return this.name;
});
var personA = new Person("personA");
var personB = new Person("personB");
var personC = new Person("personC");
크락포드옹 스탈
Overriding 을 방지할 수 있다
Function의 용도가 2가지
: 실행을 위한 함수, 생성자 함수
혼란을 피하기 위해 생성자 함수는 대문자로
시작하도록 권고
크락포드옹님 주의사항
function createObject(parentObj) {
function Func() {}
Func.prototype = parentObj;
return new Func();
}
Object.create() 와 동일
var personPrototype = {
getName : function() {
return this.name;
}
, setName : function (name) {
this.name = name;
}
};
var student =
createObject(personPrototype);
console.log(student.getName());
student.setName('student');
console.log(student.getName());
이런 방식으로 prototype을
구현한 것과 같이 생성 가능
Class 기반의 생성자처럼
생성하는 시점에
초깃값을 주고 싶다면?
상속을 구현
// 초기값을 넣고 싶은 경우
var personPrototypeFunc = function(name){
return {
name : name
, getName : function() {
return this.name;
}
, setName : function (name) {
this.name = name;
}
}
};
var student2 =
createObject(personPrototypeFunc('student2'));
console.log(student2.getName());
student2.setName('student2_changed');
console.log(student2.getName());
- 초기값을 주고 싶은 경우
재정의, 기능확장
function extend(obj, prop) {
if(!prop) {
prop = obj;
obj = this;
}
for (var i in prop) {
obj[i] = prop[i];
}
return obj;
}
var added = {
setAge : function (age) {
this.age = age;
}
, getAge : function () {
return this.age;
}
};
extend(student, added);
student.setAge(25);
console.log(student.getAge());
extend 메서드를 구현하거나
jQuery의 extend 메서드를 사용
슈퍼 클래스와 서브 클래스
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function () {
return '넓이 : ' + this.width * this.height;
}
// 아래 코드는 Rectangle 클래스를 어떻게 서브 클래스화 하는지 보여준다
function PositionedRectangle(x, y, w, h) {
// 생성자 체이닝
Rectangle.call(this, w, h);
this.x = x; // 사각형의 좌표를 저장한다.
this.y = y;
}
// Rectangle를 서브 클래스화 시키려면 명시적으로 프로토타입 객체를 생성해야 한다.
PositionedRectangle.prototype = new Rectangle();
// PositionedRectangle 객체의 constructor를 가지도록 기본값을 다시 할당한다.
PositionedRectangle.prototype.constructor = PositionedRectangle;
PositionedRectangle.prototype.getPosition = function () {
return 'x : ' + this.x + ' / y : ' + this.y;
}
// 3, 4에 위치한 2x2 사각형
var rect = new PositionedRectangle(3, 4, 2, 2);
console.log(rect.getPosition()); // x : 3 / y : 4
console.log(rect.area()); // 넓이 : 4
// rect 객체는 세 개 클래스의 인스턴스가 된다.
console.log(rect instanceof PositionedRectangle && rect instanceof Rectangle
&& rect instanceof Object); // true
클래스 방식의 상속패턴 완성
// 라이브러리로
var inherit = (function () {
var F = function () {};
return function (C, P) {
F.prototype = P.prototype;
C.prototype = new F();
C.uber = P.prototype;
C.prototype.constructor = C;
}
});
inherit(PositionedRectangle, Rectangle);
var positioned_rect = new PositionedRectangle(1, 2, 3, 4);
console.log(positioned_rect);
ES6 Class 사용
class Rectangle {
constructor(w, h) {
this.width = w;
this.height = h;
}
area() {
return '넓이 : ' + this.width * this.height;
}
}
class PositionedRectangle extends Rectangle {
constructor(x, y, w, h) {
super(w, h);
this.x = x; // 사각형의 좌표를 저장한다.
this.y = y;
}
getPosition() {
return 'x : ' + this.x + ' / y : ' + this.y;
}
}
console.log( positioned_rect.getPosition());
console.log( positioned_rect.area());
console.log(positioned_rect instanceof PositionedRectangle
&& positioned_rect instanceof Rectangle
&& positioned_rect instanceof Object);
생성자 체이닝
function PositionedRectangle(x, y, w, h) {
this.superclass(w, h);
this.x = x;
this.y = y;
}
// 상위 클래스 생성자에 대한 참조를 저장한다.
PositionedRectangle.prototype.superclass = Rectangle;
처음의 예제처럼 call이나 apply를 사용하지 않아도 된다.
생성자 함수에서 상위 클래스의 생성자 함수를 명시적으로
호출할때 아래와 같은 방법도 가능
메서드 재정의
서브 클래스에서 재정의하는 메서드는 기존 메서드에 있던 기능을
완전히 교체하기보다 확장시키는 것이 좋다.
// 메서드 재정의
Rectangle.prototype.toString = function () {
return '[' + this.width + ',' + this.height + ']';
}
PositionedRectangle.prototype.toString = function () {
return '(' + this.x + ',' + this.y + ')' + // PositionedRectangle 필드들
Rectangle.prototype.toString.apply(this); // 상위 클래스에 체이닝. 어떤 객체를
참조할지 지정하기 위해 apply()와 함께 호출.
};
console.log(rect.toString());
참고자료
- http://www.ecma-international.org/ecma-262/5.1/
- 자바스크립트 완벽 가이드 데이비드 플래너건
- 자바스크립트 핵심 가이드 더글라스 크락포드
- 인사이드 자바스크립트 송형주 고현준
- JavaScript Patterns 스토얀 스토파노프

More Related Content

What's hot

Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리ETRIBE_STG
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료욱진 양
 
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리은숙 이
 
자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초진수 정
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기Yongha Yoo
 
Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Circulus
 
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)Circulus
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수유진 변
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)Sung-hoon Ma
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Circulus
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리Circulus
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSCirculus
 
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Park Jonggun
 
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자Circulus
 
파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229Yong Joon Moon
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)NAVER D2
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229Yong Joon Moon
 

What's hot (20)

Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
 
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리
 
자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
 
Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저
 
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
Startup JavaScript 5 - 객체(Date, RegExp, Object, Global)
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
Javascript
JavascriptJavascript
Javascript
 
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초
 
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자
 
iOS 메모리관리
iOS 메모리관리iOS 메모리관리
iOS 메모리관리
 
파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229
 

Similar to 프론트엔드스터디 E05 js closure oop

Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개Dong Jun Kwon
 
자바스크립트 패턴 3장
자바스크립트 패턴 3장자바스크립트 패턴 3장
자바스크립트 패턴 3장Software in Life
 
Javascript - Function
Javascript - FunctionJavascript - Function
Javascript - Functionwonmin lee
 
JavaScript Patterns - Chapter 3. Literals and Constructors
JavaScript Patterns - Chapter 3. Literals and ConstructorsJavaScript Patterns - Chapter 3. Literals and Constructors
JavaScript Patterns - Chapter 3. Literals and ConstructorsHyuncheol Jeon
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumerChang Yoon Oh
 
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원탑크리에듀(구로디지털단지역3번출구 2분거리)
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304Yong Joon Moon
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initializationEunjoo Im
 
Gpg gems1 1.3
Gpg gems1 1.3Gpg gems1 1.3
Gpg gems1 1.3david nc
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장tedypicker
 
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple OverviewKim Hunmin
 
Javascript Closure
Javascript ClosureJavascript Closure
Javascript Closure지수 윤
 
[JS] Function.prototype.bind
[JS] Function.prototype.bind[JS] Function.prototype.bind
[JS] Function.prototype.bindJinhyuck Kim
 

Similar to 프론트엔드스터디 E05 js closure oop (20)

Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
 
자바스크립트 패턴 3장
자바스크립트 패턴 3장자바스크립트 패턴 3장
자바스크립트 패턴 3장
 
Javascript - Function
Javascript - FunctionJavascript - Function
Javascript - Function
 
javascript03
javascript03javascript03
javascript03
 
JavaScript Patterns - Chapter 3. Literals and Constructors
JavaScript Patterns - Chapter 3. Literals and ConstructorsJavaScript Patterns - Chapter 3. Literals and Constructors
JavaScript Patterns - Chapter 3. Literals and Constructors
 
Tdd 4장
Tdd 4장Tdd 4장
Tdd 4장
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Xe hack
Xe hackXe hack
Xe hack
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumer
 
자바스크립트 클래스의 프로토타입(prototype of class)
자바스크립트 클래스의  프로토타입(prototype of class)자바스크립트 클래스의  프로토타입(prototype of class)
자바스크립트 클래스의 프로토타입(prototype of class)
 
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
 
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
[IT기술칼럼#2] 고급자바스크립트 for AngularJS, React_고급자바스크립트,AngularJS,React전문교육학원
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initialization
 
Gpg gems1 1.3
Gpg gems1 1.3Gpg gems1 1.3
Gpg gems1 1.3
 
Kotlin with fp
Kotlin with fpKotlin with fp
Kotlin with fp
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장
 
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple Overview
 
Javascript Closure
Javascript ClosureJavascript Closure
Javascript Closure
 
[JS] Function.prototype.bind
[JS] Function.prototype.bind[JS] Function.prototype.bind
[JS] Function.prototype.bind
 

프론트엔드스터디 E05 js closure oop

  • 2. 1. Closure와 가까워지기 2. 객체지향과 프로토타입
  • 3. Closure 함수를 선언할때 만들어지는 유효범위 함수는 클로저를 통해서 자신이 선언될 때 속해 있던 유효 범위 내의 변수와 함수를 사용할 수 있고, 변수의 경우 그 값을 변경할 수도 있다. 흥미로운건 함수를 선언한 후에 언제든지, 심지어 함수가 속해 있던 유효 범위가 사라진 후에도 그 함수를 호출할 수 있는 경우가 생기게 된다
  • 4. Closure – 간단한 클로저 var outerValue = 'outerValue'; function outerFunction() { console.log(outerValue == 'outerValue'); } outerFunction(); 외부에 있는 변수와 함수가 모두 전역 유효 범위에 선언되어 있고, 실제로는 클로저에 해당하는 전역 유효 범위는 페이지가 로드되어 있는 한 사라지지 않기 때문에 그다지 흥미로운 코드는 아니다.
  • 5. Closure – 간단하지 않은 클로저 var outerValue = 'outerValue'; var later; function outerFunction() { var innerValue = 'innerValue' function innerFunction() { console.log(outerValue); // innerValue는 있을까? console.log(innerValue); } later = innerFunction; } outerFunction(); later(); 클로저는 함수가 선언된 시점의 유효 범위에 있는 모든 함수와 변수를 가지고 있으며, 필요할 때 그것들을 사용할 수 있다.
  • 6. Closure – 심화 var outerValue = 'outerValue'; var later; function outerFunction() { // 함수 내에 변수를 하나 선언한다. 이 변수의 유효 범위는 함수 내부로 제한이 되고, // 함수 외부에서는 접근할 수 없다. var innerValue = 'innerValue' // inner 함수에 매개변수를 추가한다. function innerFunction(paramValue) { console.log(outerValue); console.log(innerValue); console.log(paramValue); // 매개변수를 볼 수 있는지 테스트 console.log(tooLate); // 클로저가 함수가 선언된 이후에 정의된 변수를 볼 수 있는지 테스트 } later = innerFunction; } console.log(tooLate); // outer closure에서는 tooLate를 쓸 수 없다. // innerFunction을 정의한 후에 변수를 선언 var tooLate = 'tooLate'; outerFunction(); later('paramValue');
  • 7. Closure – Closure를 사용하지 않고 값을 가지고 있을 때 var uniqueId = function(){ if(!arguments.callee.id){ arguments.callee.id = 0; } return arguments.callee.id++; } uniqueId(); // 0 uniqueId(); // 1 uniqueId(); // 2 // id를 0으로 초기화 할 수 있을까?
  • 8. var uniqueId = function(){ if(!arguments.callee.id){ arguments.callee.id = 0; } return arguments.callee.id++; } uniqueId(); // 0 uniqueId(); // 1 uniqueId(); // 2 // id를 0으로 초기화 할 수 있을까? uniqueId.id = 0; uniqueId(); // 0 Closure – Closure를 사용하지 않고 값을 가지고 있을 때
  • 9. Closure – Closure를 사용해서 값을 가지고 있을 때 var uniqueId = (function(){ var id = 0; return function(){ return id++; } })(); uniqueId(); // 0 uniqueId(); // 1 uniqueId(); // 2 uniqueId(); // 3 // id를 0으로 초기화 할 수 있을까?
  • 10. var uniqueId = (function(){ var id = 0; return function(){ return id++; } })(); uniqueId(); // 0 uniqueId(); // 1 uniqueId(); // 2 uniqueId(); // 3 // 0으로 초기화 uniqueId.id = 0 // ? uniqueId(); // 4 Closure – Closure를 사용했을 때 Closure의 id에는 접근할 수 없다 => Closure를 통해 모듈화를 할 수 있다.
  • 11. Closure – 응용 : Private 변수 function DtoObj(initVal) { var val = initVal; this.getVal = function () { // this는 새로 만들어진 객체를 가리킴 return val; }; this.setVal = function(pVal) { val = pVal; } } var dto = new DtoObj(3); // dto 객체의 내부 변수는 getter를 통해서만 접근하여 값을 받을 수 있다. console.log(dto.getVal()); // 3 // dto 객체의 내부 변수는 setter를 통해서만 접근하여 값을 바꿀 수 있다. dto.setVal(4); console.log(dto.getVal()); // 4 dto.val = 5; console.log(dto.getVal()); // 4
  • 12. Closure – 응용 : success callback <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Closure 예제</title> </head> <body> <button type="button" id="testButton">Go!</button> <div id="testSubject"></div> <script src="https://code.jquery.com/jquery-2.2.3.js"></script> <script> $('#testButton').click(function () { var elem$ = $('#testSubject'); elem$.html('로딩 중...'); $.ajax({ url: '/test' , success: function (data) { console.dir(this.success); elem$.html(JSON.stringify(data)); } }); }); </script> </body> </html>
  • 13. Closure 핵심 정리 1. 내부 함수는 외부 스코프에 선언된 변수를 참조할 수 있다. 2. 클로저는 자신을 생성한 함수보다 더 오래 지속된다. 3. 클로저는 내부적으로 외부 변수에 대한 참조를 저장하고, 저장된 변수를 읽고 갱신할 수 있다.
  • 14. Javascript에는 자바, C++, C# 등의 class가 없다. Prototype 기반 언어들에 영감을 받음. (https://ko.wikipedia.org/wiki/프로토타입_기반_프로그 래밍) JavaScript는 prototype 객체, 생성자 등을 통해 구현 가능 클래스 기반 vs 프로토타입 기반
  • 15. function Func(x, y) { this.x = x; this.y = y; } var func = Func(1, 2); this === ? 생성자 함수와 this function Func(x, y) { this.x = x; this.y = y; } var func = new Func(1, 2); this === ?
  • 16. this === func => 인스턴스를 바라본다
  • 17. When Number is called as a function rather than as a constructor, it performs a type conversion. var num = 1; var num2 = Number(1); var num3 = new Number(1); console.log(num === num2); console.log(num === num3); console.dir(num); console.dir(num3); new 키워드 필수 Number, String 등등에는 안써도 되던데? Type 변환을 위한 메서드를 추가로 가지고 있을뿐. new로 생성하지 않으면 instance가 없다. var func = Func(1, 2); // func === undefined Spec.
  • 18. function GoodWaffle() { if(!(this instanceof GoodWaffle)) { return new GoodWaffle(); } this.tastes = 'yummy'; } var waffle = new GoodWaffle(); var waffle2 = new GoodWaffle(); console.log(waffle instanceof GoodWaffle); console.log(waffle2 instanceof GoodWaffle); New를 강제하는 방법 GoodWaffle.call(new GoodWaffle);
  • 19. var GoodWaffle = (function(){ var RealWaffle = function(){}; RealWaffle.prototype.xxx = xxx; return function(){ return new RealWaffle(); } })(); var waffle = new GoodWaffle(); var waffle2 = new GoodWaffle(); New를 강제하는 방법 - 더블쉐도우
  • 20. function Person(name) { this.name = name; this.getName = function () { return this.name; } this.setName = function (name) { this.name = name; } } var me = new Person("yb"); console.log(me.getName()); me.setName("new yb"); console.log(me.getName()); 공통속성을 추가하는 경우 // Quiz : getName, setName 메서드는 Person에 추가 되었을까? 아니면 me에만 추가 되었을까?
  • 21. 중복되는 영역을 메모리에 올려놓고 사용 -> 메모리 낭비 var personA = new Person("personA"); var personB = new Person("personB"); var personC = new Person("personC"); 불필요한 중복
  • 22. personA.getName = function () { return 'Hello, ' + this.name; } console.log(personA.getName()); console.log(personB.getName()); console.log(personC.getName()); 변경이 발생했을 때 Hello, personA personB personC 변경된 사항이 적용되지 않는다.
  • 23. function Person(name) { this.name = name; } Person.prototype.getName = function () { return this.name; } Person.prototype.setName = function (name) { this.name = name; } var personA = new Person("personA"); var personB = new Person("personB"); var personC = new Person("personC"); console.log(personA.getName()); console.log(personB.getName()); console.log(personC.getName()); 공통속성을 추가하는 경우 – Prototype을 이용 Instance마다 개별적으로 가져야 할 프로퍼티 공통으로 가져야 할 프로퍼티
  • 24. cf. Prototype을 사용하지 않은 경우 Prototype 참조
  • 25. 변경이 발생했을 때 Person.prototype.getName = function () { return 'Hello, ' + this.name; } console.log(personA.getName()); console.log(personB.getName()); console.log(personC.getName()); Hello, personA Hello, personB Hello, personC Prototype을 참조하고 있는 다른 모든 Instance에도 모두 적용
  • 26. Prototype의 몇 가지 속성 name : name / hasOwnProperty : true name : getName / hasOwnProperty : false name : setName / hasOwnProperty : false for (var obj in personA) { console.log('name : ', obj, ' / hasOwnProperty : ' + personA.hasOwnProperty(obj)); } - 마치 자신의 속성처럼 열거할 수 있다.(for in 사용) - hasOwnProperty() 메서드를 사용해 소유여부(자신이 소유하고 있는지, prototype으로 참조하는지)를 확인할 수 있다.
  • 27. function Circle(r) { this.r = r; } Circle.prototype.PI = 3.14; Circle.prototype.getArea = function () { return 2 * this.r * this.PI; } var r2 = new Circle(2); console.log(r2.getArea()); var r3 = new Circle(3); console.log(r3.getArea()); var r3Alien = new Circle(3); r3Alien.PI = 4.74; // PI 재정의 console.log(r3Alien.getArea()); 내부의 property가 있는 경우에 prototype을 참고하지 않는다. 이런 경우를 다른 property가 가렸다(shadows) 혹은 숨겼다(hides)라고 한다 - Prototype property가 참조되지 않을 수 있다.
  • 28. Function.prototype.addMethod = function (name, func) { if(!this.prototype[name]) { this.prototype[name] = func; } } function Person(name) { this.name = name; } Person.addMethod('setName', function(name) { this.name = name; }); Person.addMethod('getName', function () { return this.name; }); var personA = new Person("personA"); var personB = new Person("personB"); var personC = new Person("personC"); 크락포드옹 스탈 Overriding 을 방지할 수 있다
  • 29. Function의 용도가 2가지 : 실행을 위한 함수, 생성자 함수 혼란을 피하기 위해 생성자 함수는 대문자로 시작하도록 권고 크락포드옹님 주의사항
  • 30. function createObject(parentObj) { function Func() {} Func.prototype = parentObj; return new Func(); } Object.create() 와 동일 var personPrototype = { getName : function() { return this.name; } , setName : function (name) { this.name = name; } }; var student = createObject(personPrototype); console.log(student.getName()); student.setName('student'); console.log(student.getName()); 이런 방식으로 prototype을 구현한 것과 같이 생성 가능 Class 기반의 생성자처럼 생성하는 시점에 초깃값을 주고 싶다면? 상속을 구현
  • 31. // 초기값을 넣고 싶은 경우 var personPrototypeFunc = function(name){ return { name : name , getName : function() { return this.name; } , setName : function (name) { this.name = name; } } }; var student2 = createObject(personPrototypeFunc('student2')); console.log(student2.getName()); student2.setName('student2_changed'); console.log(student2.getName()); - 초기값을 주고 싶은 경우
  • 32. 재정의, 기능확장 function extend(obj, prop) { if(!prop) { prop = obj; obj = this; } for (var i in prop) { obj[i] = prop[i]; } return obj; } var added = { setAge : function (age) { this.age = age; } , getAge : function () { return this.age; } }; extend(student, added); student.setAge(25); console.log(student.getAge()); extend 메서드를 구현하거나 jQuery의 extend 메서드를 사용
  • 33. 슈퍼 클래스와 서브 클래스 function Rectangle(w, h) { this.width = w; this.height = h; } Rectangle.prototype.area = function () { return '넓이 : ' + this.width * this.height; } // 아래 코드는 Rectangle 클래스를 어떻게 서브 클래스화 하는지 보여준다 function PositionedRectangle(x, y, w, h) { // 생성자 체이닝 Rectangle.call(this, w, h); this.x = x; // 사각형의 좌표를 저장한다. this.y = y; } // Rectangle를 서브 클래스화 시키려면 명시적으로 프로토타입 객체를 생성해야 한다. PositionedRectangle.prototype = new Rectangle(); // PositionedRectangle 객체의 constructor를 가지도록 기본값을 다시 할당한다. PositionedRectangle.prototype.constructor = PositionedRectangle; PositionedRectangle.prototype.getPosition = function () { return 'x : ' + this.x + ' / y : ' + this.y; } // 3, 4에 위치한 2x2 사각형 var rect = new PositionedRectangle(3, 4, 2, 2); console.log(rect.getPosition()); // x : 3 / y : 4 console.log(rect.area()); // 넓이 : 4 // rect 객체는 세 개 클래스의 인스턴스가 된다. console.log(rect instanceof PositionedRectangle && rect instanceof Rectangle && rect instanceof Object); // true
  • 34. 클래스 방식의 상속패턴 완성 // 라이브러리로 var inherit = (function () { var F = function () {}; return function (C, P) { F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; } }); inherit(PositionedRectangle, Rectangle); var positioned_rect = new PositionedRectangle(1, 2, 3, 4); console.log(positioned_rect);
  • 35. ES6 Class 사용 class Rectangle { constructor(w, h) { this.width = w; this.height = h; } area() { return '넓이 : ' + this.width * this.height; } } class PositionedRectangle extends Rectangle { constructor(x, y, w, h) { super(w, h); this.x = x; // 사각형의 좌표를 저장한다. this.y = y; } getPosition() { return 'x : ' + this.x + ' / y : ' + this.y; } } console.log( positioned_rect.getPosition()); console.log( positioned_rect.area()); console.log(positioned_rect instanceof PositionedRectangle && positioned_rect instanceof Rectangle && positioned_rect instanceof Object);
  • 36. 생성자 체이닝 function PositionedRectangle(x, y, w, h) { this.superclass(w, h); this.x = x; this.y = y; } // 상위 클래스 생성자에 대한 참조를 저장한다. PositionedRectangle.prototype.superclass = Rectangle; 처음의 예제처럼 call이나 apply를 사용하지 않아도 된다. 생성자 함수에서 상위 클래스의 생성자 함수를 명시적으로 호출할때 아래와 같은 방법도 가능
  • 37. 메서드 재정의 서브 클래스에서 재정의하는 메서드는 기존 메서드에 있던 기능을 완전히 교체하기보다 확장시키는 것이 좋다. // 메서드 재정의 Rectangle.prototype.toString = function () { return '[' + this.width + ',' + this.height + ']'; } PositionedRectangle.prototype.toString = function () { return '(' + this.x + ',' + this.y + ')' + // PositionedRectangle 필드들 Rectangle.prototype.toString.apply(this); // 상위 클래스에 체이닝. 어떤 객체를 참조할지 지정하기 위해 apply()와 함께 호출. }; console.log(rect.toString());
  • 38. 참고자료 - http://www.ecma-international.org/ecma-262/5.1/ - 자바스크립트 완벽 가이드 데이비드 플래너건 - 자바스크립트 핵심 가이드 더글라스 크락포드 - 인사이드 자바스크립트 송형주 고현준 - JavaScript Patterns 스토얀 스토파노프