ݺߣ

ݺߣShare a Scribd company logo
스파르탄 스터디
CH.04. 객체지향, 함수형 프로그래밍
자바, 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 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마다 개별적으로
가져야 할 프로퍼티
공통으로 가져야 할
프로퍼티
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() 메서드를 사용해 소유여부를 확인
할 수 있다.
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;
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(Parent, Child) {
var F = function() {};
return function(Parent, Child) {
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.super = Parent.prototype;
return new Child();
}
}();
var student2 = inherit(Person, Student);
console.dir(student2);
생성자 체이닝
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());
재정의 된 메서드 호출하기
서브 클래스에서 재정의하는 메서드는 종종 기존 메서드에 있던
기능을 완전히 교체하기보다 확장시킨다.
// 메서드 재정의
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());
Functional Programming
함수의 조합으로 작업을 수행한다.
작업에 필요한 데이터와 상태는 변하지 않는다.
오로지 함수만 변한다.
명령형 프로그래밍(Imperative Programming)
<-> 함수형 프로그래밍(Functional Programming)
명령을 순서대로 기술하는 것은 겉모양이 함수여도 Procedure에
가깝다.
함수형 프로그래밍의 함수는 독립적으로 작동하는 순수함수(Pure
function)
명령형 프로그래밍
function sum(arr) {
var len = arr.length;
var i = 0, sum = 0;
for (; i < len; i++) {
sum += arr[i];
}
return sum;
}
var arr = [1, 2, 3, 4];
console.log(sum(arr));
function multiply(arr) {
var len = arr.length;
var i = 0, sum = 1;
for (; i < len; i++) {
sum *= arr[i];
}
return sum;
}
var arr = [1, 2, 3, 4];
console.log(multiply(arr));
유사한 로직이지만 매번 새로 구현해야 한다.
함수형 프로그래밍
function reduce(func, arr, memo) {
var len = arr.length, i= 0, accum = memo;
for (; i < len; i++) {
accum = func(accum, arr[i]);
}
return accum;
}
var arr = [1, 2, 3, 4];
var sum = function(x, y) {
return x+y;
}
var multiply = function(x, y) {
return x*y;
}
console.log(reduce(sum, arr, 0));
console.log(reduce(multiply, arr, 1));
추상화, 모듈화를 통한
재사용이 가능하다.
핵심요소
함수 = 일급객체
 값으로 사용 가능하고 전달할 수 있다.
클로저
=> 함수의 실행이 끝난 후에도 존재하고, 모듈
화를 가능하게 해준다.
함수 실행 소요시간
function getCostTime(func, param, repeatTime) {
var start = new Date().getTime();
if(repeatTime) {
for (var i = 0; i < repeatTime; i++) {
func(param);
}
} else {
func(param);
}
var elapsed = new Date().getTime() - start;
console.log('소요시간 : ' + elapsed + ' ms');
return elapsed;
}
getCostTime(function(){
for (var i = 0; i < 1000000000; i++) {
}
});
Memoization
var fact = function () {
var cache = {'0' : 1};
var func = function (n) {
var result = 0;
if(typeof(cache[n]) === 'number') {
result = cache[n];
} else {
result = cache[n] = n * func(n-1);
}
console.log(n + '! = '+ result);
return result;
}
return func;
}();
console.log(fact(10));
console.log(fact(20));
Memoization - Prototype에 선언
Function.prototype.memoization = function
(key) {
var arg =
Array.prototype.slice.call(arguments, 1);
this.data = this.data || {};
return this.data[key] !== undefined ?
this.data[key]: this.data[key] =
this.apply(this, arg);
}
function myCalculate1(input) {
return input * input;
}
function myCalculate2(input) {
return input * input / 4;
}
myCalculate1.memoization(1, 5);
myCalculate1.memoization(2, 4);
myCalculate2.memoization(1, 6);
myCalculate2.memoization(2, 7);
console.log(myCalculate1.memoization(1));
console.log(myCalculate1.memoization(2));
console.log(myCalculate2.memoization(1));
console.log(myCalculate2.memoization(2));
피보나치 수열
var fibo = function() {
var cache = {'0' : 0, '1' : 1};
var func = function (n) {
if(typeof(cache[n]) === 'number') {
result = cache[n];
} else {
result = cache[n] = func(n-1) + func(n-2);
}
return result;
};
return func;
}();
console.log(fibo(10));
피보나치 수열
var cacher = function (cache, func) {
var calculate = function (n) {
if(typeof(cache[n]) === 'number') {
result = cache[n];
} else {
result = cache[n] = func(calculate, n);
}
return result;
}
return calculate;
};
var fact = cacher({'0' : 1}, function (func, n) {
return n*func(n-1);
});
var fibo = cacher({'0' : 0, '1' : 1}, function (func, n) {
return func(n-1) + func(n-2);
});
//console.log(fact(10));
console.log(fibo(5));
Curry – 새로운 함수 정의
function calculate(a, b, c) {
return a * b + c;
}
function curry(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));
}
}
var new_func1 = curry(calculate, 1);
console.log(new_func1(2, 3));
var new_func2 = curry(calculate, 1, 3);
console.log(new_func2(3));
Bind - 새로운 함수 정의
var print_all = function (arg) {
for (var i in this) { console.log(i + " : " + this[i]); }
for (var j in arguments) { console.log(j + " : " +
arguments[j]); }
}
var myobj = {name: "zzoon"};
var myfunc = print_all.bind(myobj);
myfunc();
var myfunc1 = print_all.bind(myobj, 'yb', 'others');
myfunc1('insidejs');
Wrapper 함수 구현
function wrap(object, method, wrapper) {
var fn = object[method];
return object[method] = function () {
return wrapper.apply(this, [fn].concat(Array.prototype.slice.call(arguments)));
};
}
Function.prototype.original = function (value) {
this.value = value;
console.log("value : " + this.value);
}
var Mywrap = wrap(Function.prototype, "original", function (orig_func, value) {
this.value = 20;
orig_func(value);
console.log("wrapper value : " + this.value);
});
var obj = new Mywrap('yb');
each 함수 구현
function each(obj, fn, args) {
if(obj.length == undefined) {
for (var i in obj) {
fn.apply(obj[i], args || [i, obj[i]]);
}
} else {
for (var i = 0; i < obj.length; i++) {
fn.apply(obj[i], args || [i, obj[i]]);
}
}
return obj;
}
each([1, 2, 3], function (idx, num) {
console.log(idx + " : " + num);
});
map 함수 구현
Array.prototype.map = function (callback) {
var obj = this;
var value, mapped_value;
var A = new Array(obj.length);
for (var i = 0; i < obj.length; i++) {
value = obj[i];
mapped_value = callback.call(null, value);
A[i] = mapped_value;
}
return A;
};
var arr = [1, 2, 3];
var new_arr = arr.map(function (value) {
return value * value;
});
console.log(new_arr);
reduce 함수 구현
Array.prototype.reduce = function (callback, memo) {
var obj = this;
var value, accumulated_value = 0;
for (var i = 0; i < obj.length; i++) {
value = obj[i];
accumulated_value = callback.call(null, accumulated_value, value);
}
return accumulated_value;
};
var arr = [1, 2, 3];
var accumulated_val = arr.reduce(function (a, b) {
return a + b;
})
console.log(accumulated_val);
참고자료
- http://www.ecma-international.org/ecma-262/5.1/
- 자바스크립트 완벽 가이드 데이비드 플래너건
- 자바스크립트 핵심 가이드 더글라스 크락포드
- 인사이드 자바스크립트 송형주 고현준
- JavaScript Patterns 스토얀 스토파노프

More Related Content

What's hot (20)

Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
ETRIBE_STG
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
자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초
진수 정
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
유진 변
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
Circulus
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
욱진 양
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
Yongha Yoo
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Circulus
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자
Circulus
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초
Park Jonggun
Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수
Park Jonggun
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리
은숙 이
iOS 메모리관리
iOS 메모리관리iOS 메모리관리
iOS 메모리관리
Changwon National University
프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기
Jongwook Choi
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
NAVER D2
Java lambda
Java lambdaJava lambda
Java lambda
Hyosang Hong
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
MIN SEOK KOO
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
ETRIBE_STG
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
자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초
진수 정
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
유진 변
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
Circulus
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
욱진 양
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
Yongha Yoo
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리Startup JavaScript 3 - 조건문, 반복문, 예외처리
Startup JavaScript 3 - 조건문, 반복문, 예외처리
Circulus
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자
Circulus
Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초Start IoT with JavaScript - 1.기초
Start IoT with JavaScript - 1.기초
Park Jonggun
Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수
Park Jonggun
헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리
은숙 이
프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기
Jongwook Choi
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
NAVER D2
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
MIN SEOK KOO

Similar to 스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍 (20)

[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분거리)
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple Overview
Kim Hunmin
Javascript - Function
Javascript - FunctionJavascript - Function
Javascript - Function
wonmin lee
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initialization
Eunjoo Im
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
yongwoo Jeon
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
HyeonSeok Choi
자바스크립트 클래스의 프로토타입(prototype of class)
자바스크립트 클래스의  프로토타입(prototype of class)자바스크립트 클래스의  프로토타입(prototype of class)
자바스크립트 클래스의 프로토타입(prototype of class)
탑크리에듀(구로디지털단지역3번출구 2분거리)
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
Dong Jun Kwon
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10
hungrok
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
Wonjun Hwang
12장 상속 (고급)
12장 상속 (고급)12장 상속 (고급)
12장 상속 (고급)
유석 남
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
KWANGIL KIM
ECMA Script 5 & 6
ECMA Script 5 & 6ECMA Script 5 & 6
ECMA Script 5 & 6
sewoo lee
Ai C#세미나
Ai C#세미나Ai C#세미나
Ai C#세미나
Astin Choi
Xe hack
Xe hackXe hack
Xe hack
sejin7940
[JS] Function.prototype.bind
[JS] Function.prototype.bind[JS] Function.prototype.bind
[JS] Function.prototype.bind
Jinhyuck Kim
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
Hyuncheol Jeon
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple Overview
Kim Hunmin
Javascript - Function
Javascript - FunctionJavascript - Function
Javascript - Function
wonmin lee
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initialization
Eunjoo Im
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
yongwoo Jeon
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
Dong Jun Kwon
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10
hungrok
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
키트웍스발표자료깶경수ڳܲԳپDzԲDzԲ240920.
Wonjun Hwang
12장 상속 (고급)
12장 상속 (고급)12장 상속 (고급)
12장 상속 (고급)
유석 남
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
KWANGIL KIM
[JS] Function.prototype.bind
[JS] Function.prototype.bind[JS] Function.prototype.bind
[JS] Function.prototype.bind
Jinhyuck Kim
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
Hyuncheol Jeon

스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍

  • 2. 자바, C++, C# 등의 class가 없다. Prototype 기반 언어들에 영감을 받음. (https://ko.wikipedia.org/wiki/프로토타입_기반_프로 그래밍) JavaScript는 prototype 객체, 생성자 등을 통해 구현 가능 클래스 기반 vs 프로토타입 기반
  • 3. 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 === ?
  • 4. this === func => 인스턴스를 바라본다
  • 5. 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.
  • 6. 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에만 추가 되었을까?
  • 7. 중복되는 영역을 메모리에 올려놓고 사용 -> 메모리 낭비 var personA = new Person("personA"); var personB = new Person("personB"); var personC = new Person("personC"); 불필요한 중복
  • 8. personA.getName = function () { return 'Hello, ' + this.name; } console.log(personA.getName()); console.log(personB.getName()); console.log(personC.getName()); 변경이 발생했을 때 Hello, personA personB personC 변경된 사항이 적용되지 않는다.
  • 9. 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마다 개별적으로 가져야 할 프로퍼티 공통으로 가져야 할 프로퍼티
  • 11. 변경이 발생했을 때 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에도 모두 적용
  • 12. 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() 메서드를 사용해 소유여부를 확인 할 수 있다.
  • 13. 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; console.log(r3Alien.getArea()); 내부의 property가 있는 경우에 prototype을 참고하지 않는다. 이런 경우를 다른 property가 가렸다(shadows) 혹은 숨겼다 (hides)라고 한다 - Prototype property가 참조되지 않을 수 있다.
  • 14. 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 을 방지할 수 있다
  • 15. Function의 용도가 2가지 실행, 생성자 혼란을 피하기 위해 생성자 함수는 대문자로 시작하도록 권고 크락포드옹님 주의사항
  • 16. 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 기반의 생성자처럼 생성하는 시점에 초깃값을 주고 싶다면? 상속을 구현
  • 17. // 초깃값을 넣고 싶은 경우 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()); - 초깃값을 주고 싶은 경우
  • 18. 재정의, 기능확장 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 메서드를 사용
  • 19. 슈퍼 클래스와 서브 클래스 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
  • 20. 클래스 방식의 상속패턴 완성 // 라이브러리로 var inherit = function(Parent, Child) { var F = function() {}; return function(Parent, Child) { F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.super = Parent.prototype; return new Child(); } }(); var student2 = inherit(Person, Student); console.dir(student2);
  • 21. 생성자 체이닝 function PositionedRectangle(x, y, w, h) { this.superclass(w, h); this.x = x; this.y = y; } // 상위 클래스 생성자에 대한 참조를 저장한다. PositionedRectangle.prototype.superclass = Rectangle; 처음의 예제처럼 call이나 apply를 사용하지 않아도 된다. 생성자 함수에서 상위 클래스의 생성자 함수를 명시적으로 호출할때 아래와 같은 방법도 가능
  • 22. 재정의 된 메서드 호출하기 서브 클래스에서 재정의하는 메서드는 종종 기존 메서드에 있던 기능을 완전히 교체하기보다 확장시킨다. // 메서드 재정의 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());
  • 23. 재정의 된 메서드 호출하기 서브 클래스에서 재정의하는 메서드는 종종 기존 메서드에 있던 기능을 완전히 교체하기보다 확장시킨다. // 메서드 재정의 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());
  • 24. Functional Programming 함수의 조합으로 작업을 수행한다. 작업에 필요한 데이터와 상태는 변하지 않는다. 오로지 함수만 변한다. 명령형 프로그래밍(Imperative Programming) <-> 함수형 프로그래밍(Functional Programming) 명령을 순서대로 기술하는 것은 겉모양이 함수여도 Procedure에 가깝다. 함수형 프로그래밍의 함수는 독립적으로 작동하는 순수함수(Pure function)
  • 25. 명령형 프로그래밍 function sum(arr) { var len = arr.length; var i = 0, sum = 0; for (; i < len; i++) { sum += arr[i]; } return sum; } var arr = [1, 2, 3, 4]; console.log(sum(arr)); function multiply(arr) { var len = arr.length; var i = 0, sum = 1; for (; i < len; i++) { sum *= arr[i]; } return sum; } var arr = [1, 2, 3, 4]; console.log(multiply(arr)); 유사한 로직이지만 매번 새로 구현해야 한다.
  • 26. 함수형 프로그래밍 function reduce(func, arr, memo) { var len = arr.length, i= 0, accum = memo; for (; i < len; i++) { accum = func(accum, arr[i]); } return accum; } var arr = [1, 2, 3, 4]; var sum = function(x, y) { return x+y; } var multiply = function(x, y) { return x*y; } console.log(reduce(sum, arr, 0)); console.log(reduce(multiply, arr, 1)); 추상화, 모듈화를 통한 재사용이 가능하다.
  • 27. 핵심요소 함수 = 일급객체  값으로 사용 가능하고 전달할 수 있다. 클로저 => 함수의 실행이 끝난 후에도 존재하고, 모듈 화를 가능하게 해준다.
  • 28. 함수 실행 소요시간 function getCostTime(func, param, repeatTime) { var start = new Date().getTime(); if(repeatTime) { for (var i = 0; i < repeatTime; i++) { func(param); } } else { func(param); } var elapsed = new Date().getTime() - start; console.log('소요시간 : ' + elapsed + ' ms'); return elapsed; } getCostTime(function(){ for (var i = 0; i < 1000000000; i++) { } });
  • 29. Memoization var fact = function () { var cache = {'0' : 1}; var func = function (n) { var result = 0; if(typeof(cache[n]) === 'number') { result = cache[n]; } else { result = cache[n] = n * func(n-1); } console.log(n + '! = '+ result); return result; } return func; }(); console.log(fact(10)); console.log(fact(20));
  • 30. Memoization - Prototype에 선언 Function.prototype.memoization = function (key) { var arg = Array.prototype.slice.call(arguments, 1); this.data = this.data || {}; return this.data[key] !== undefined ? this.data[key]: this.data[key] = this.apply(this, arg); } function myCalculate1(input) { return input * input; } function myCalculate2(input) { return input * input / 4; } myCalculate1.memoization(1, 5); myCalculate1.memoization(2, 4); myCalculate2.memoization(1, 6); myCalculate2.memoization(2, 7); console.log(myCalculate1.memoization(1)); console.log(myCalculate1.memoization(2)); console.log(myCalculate2.memoization(1)); console.log(myCalculate2.memoization(2));
  • 31. 피보나치 수열 var fibo = function() { var cache = {'0' : 0, '1' : 1}; var func = function (n) { if(typeof(cache[n]) === 'number') { result = cache[n]; } else { result = cache[n] = func(n-1) + func(n-2); } return result; }; return func; }(); console.log(fibo(10));
  • 32. 피보나치 수열 var cacher = function (cache, func) { var calculate = function (n) { if(typeof(cache[n]) === 'number') { result = cache[n]; } else { result = cache[n] = func(calculate, n); } return result; } return calculate; }; var fact = cacher({'0' : 1}, function (func, n) { return n*func(n-1); }); var fibo = cacher({'0' : 0, '1' : 1}, function (func, n) { return func(n-1) + func(n-2); }); //console.log(fact(10)); console.log(fibo(5));
  • 33. Curry – 새로운 함수 정의 function calculate(a, b, c) { return a * b + c; } function curry(func) { var args = Array.prototype.slice.call(arguments, 1); return function () { return func.apply(null, args.concat(Array.prototype.slice.call(arguments))); } } var new_func1 = curry(calculate, 1); console.log(new_func1(2, 3)); var new_func2 = curry(calculate, 1, 3); console.log(new_func2(3));
  • 34. Bind - 새로운 함수 정의 var print_all = function (arg) { for (var i in this) { console.log(i + " : " + this[i]); } for (var j in arguments) { console.log(j + " : " + arguments[j]); } } var myobj = {name: "zzoon"}; var myfunc = print_all.bind(myobj); myfunc(); var myfunc1 = print_all.bind(myobj, 'yb', 'others'); myfunc1('insidejs');
  • 35. Wrapper 함수 구현 function wrap(object, method, wrapper) { var fn = object[method]; return object[method] = function () { return wrapper.apply(this, [fn].concat(Array.prototype.slice.call(arguments))); }; } Function.prototype.original = function (value) { this.value = value; console.log("value : " + this.value); } var Mywrap = wrap(Function.prototype, "original", function (orig_func, value) { this.value = 20; orig_func(value); console.log("wrapper value : " + this.value); }); var obj = new Mywrap('yb');
  • 36. each 함수 구현 function each(obj, fn, args) { if(obj.length == undefined) { for (var i in obj) { fn.apply(obj[i], args || [i, obj[i]]); } } else { for (var i = 0; i < obj.length; i++) { fn.apply(obj[i], args || [i, obj[i]]); } } return obj; } each([1, 2, 3], function (idx, num) { console.log(idx + " : " + num); });
  • 37. map 함수 구현 Array.prototype.map = function (callback) { var obj = this; var value, mapped_value; var A = new Array(obj.length); for (var i = 0; i < obj.length; i++) { value = obj[i]; mapped_value = callback.call(null, value); A[i] = mapped_value; } return A; }; var arr = [1, 2, 3]; var new_arr = arr.map(function (value) { return value * value; }); console.log(new_arr);
  • 38. reduce 함수 구현 Array.prototype.reduce = function (callback, memo) { var obj = this; var value, accumulated_value = 0; for (var i = 0; i < obj.length; i++) { value = obj[i]; accumulated_value = callback.call(null, accumulated_value, value); } return accumulated_value; }; var arr = [1, 2, 3]; var accumulated_val = arr.reduce(function (a, b) { return a + b; }) console.log(accumulated_val);
  • 39. 참고자료 - http://www.ecma-international.org/ecma-262/5.1/ - 자바스크립트 완벽 가이드 데이비드 플래너건 - 자바스크립트 핵심 가이드 더글라스 크락포드 - 인사이드 자바스크립트 송형주 고현준 - JavaScript Patterns 스토얀 스토파노프