39
스스스스 스스스 CH.04. 스스스스 , 스스스 스스스스스

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

Embed Size (px)

Citation preview

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

스파르탄 스터디CH.04. 객체지향 , 함수형 프로그래밍

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

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 === ?

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

this === func=> 인스턴스를 바라본다

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

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.

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

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 메서드는 Per-son 에 추가 되었을까 ? 아니면 me 에만 추가 되었을까 ?

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

중복되는 영역을 메모리에 올려놓고 사용-> 메모리 낭비

var personA = new Person("personA");var personB = new Person("personB");var personC = new Person("personC");

불필요한 중복

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

personA.getName = function () { return 'Hello, ' + this.name;}

console.log(personA.getName());console.log(personB.getName());console.log(personC.getName());

변경이 발생했을 때

Hello, personApersonBpersonC

변경된 사항이 적용되지 않는다 .

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

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 마다 개별적으로 가져야 할 프로퍼티

공통으로 가져야 할 프로퍼티

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

Prototype 을 사용하지 않은 경우

Prototype 참조

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

변경이 발생했을 때Person.prototype.getName = function () { return 'Hello, ' + this.name;}

console.log(personA.getName());console.log(personB.getName());console.log(personC.getName());

Hello, personAHello, personBHello, personC

Prototype 을 참조하고 있는 다른 모든 Instance 에도 모두 적용

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

Prototype 의 몇 가지 속성

name : name / hasOwnProperty : truename : getName / hasOwnProperty : falsename : setName / hasOwnProperty : false

for (var obj in personA) { console.log('name : ', obj, ' / hasOwnProperty : ' + personA.ha-sOwnProperty(obj));}

- 마치 자신의 속성처럼 열거할 수 있다 .(for in 사용 )- hasOwnProperty() 메서드를 사용해 소유여부를 확인할 수 있다 .

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

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 가 참조되지 않을 수 있다 .

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

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 을 방지할 수 있다

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

Function 의 용도가 2 가지실행 , 생성자혼란을 피하기 위해 생성자 함수는 대문자로 시작하도록 권고

크락포드옹님 주의사항

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

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 기반의 생성자처럼 생성하는 시점에 초깃값을 주고 싶다면 ?

상속을 구현

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

// 초깃값을 넣고 싶은 경우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());

- 초깃값을 주고 싶은 경우

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

재정의 , 기능확장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 메서드를 사용

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

슈퍼 클래스와 서브 클래스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 : 4console.log(rect.area()); // 넓이 : 4

// rect 객체는 세 개 클래스의 인스턴스가 된다 .console.log(rect instanceof PositionedRectangle && rect instanceof Rectangle && rect instanceof Object); // true

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

클래스 방식의 상속패턴 완성 // 라이브러리로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);

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

생성자 체이닝

function PositionedRectangle(x, y, w, h) { this.superclass(w, h); this.x = x; this.y = y;}

// 상위 클래스 생성자에 대한 참조를 저장한다 .PositionedRectangle.prototype.superclass = Rectangle;

처음의 예제처럼 call 이나 apply 를 사용하지 않아도 된다 .

생성자 함수에서 상위 클래스의 생성자 함수를 명시적으로 호출할때 아래와 같은 방법도 가능

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

재정의 된 메서드 호출하기서브 클래스에서 재정의하는 메서드는 종종 기존 메서드에 있던 기능을 완전히 교체하기보다 확장시킨다 .

// 메서드 재정의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());

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

재정의 된 메서드 호출하기서브 클래스에서 재정의하는 메서드는 종종 기존 메서드에 있던 기능을 완전히 교체하기보다 확장시킨다 .

// 메서드 재정의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());

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

Functional Programming

함수의 조합으로 작업을 수행한다 .

작업에 필요한 데이터와 상태는 변하지 않는다 .오로지 함수만 변한다 .

명령형 프로그래밍 (Imperative Programming)<-> 함수형 프로그래밍 (Functional Programming)

명령을 순서대로 기술하는 것은 겉모양이 함수여도 Procedure 에 가깝다 .

함수형 프로그래밍의 함수는 독립적으로 작동하는 순수함수 (Pure function)

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

명령형 프로그래밍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));

유사한 로직이지만 매번 새로 구현해야 한다 .

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

함수형 프로그래밍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));

추상화 , 모듈화를 통한 재사용이 가능하다 .

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

핵심요소함수 = 일급객체Þ 값으로 사용 가능하고 전달할 수 있다 . 클로저=> 함수의 실행이 끝난 후에도 존재하고 , 모듈화를 가능하게 해준다 .

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

함수 실행 소요시간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++) { }});

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

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));

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

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));

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

피보나치 수열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));

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

피보나치 수열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));

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

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));

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

Bind - 새로운 함수 정의 var print_all = function (arg) { for (var i in this) { console.log(i + " : " + this[i]); } for (var j in arguments) { console.log(j + " : " + argu-ments[j]); }}

var myobj = {name: "zzoon"};

var myfunc = print_all.bind(myobj);myfunc();

var myfunc1 = print_all.bind(myobj, 'yb', 'others');myfunc1('insidejs');

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

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');

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

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);});

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

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);

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

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);

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

참고자료- http://www.ecma-international.org/ecma-262/5.1/

- 자바스크립트 완벽 가이드 데이비드 플래너건- 자바스크립트 핵심 가이드 더글라스 크락포드- 인사이드 자바스크립트 송형주 고현준- JavaScript Patterns 스토얀 스토파노프