5. 일급객체 – First citizen
다음과 같은 조건을 만족할 때 일급
객체라고 말할 수 있다.
- 변수나 데이터 구조안에 담을 수
있다.
- 파라미터로 전달 할 수 있다.
- 반환값(return value)으로 사용할 수
있다.
1. 기본개념
var func = function () {};
return function(){};
func(function(){});
6. 함수 vs. 메서드
console.dir() 은 함수일까? 메서드일까?
vs.
1. 기본개념
function funcA() {
/* 코드 블록*/
}
var objA = {
funcA : function() {
/* 코드 블록 */
}
}
7. 함수 vs. 메서드
함수를 객체의 속성에 저장하는 경우
=> 메서드(method)
console.dir()의 dir역시
console 객체의 하나의 속성
1. 기본개념
9. 함수의 종류
FunctionDeclaration vs. FunctionExpression
* FunctionDeclaration은 Hoisting이 발생한다.
(단, 정식명칭은 아니다.)
1. 기본개념
Quiz.
funcA();
function funcA() {
console.log('funcA has called');
} // 호출됨
funcB();
var funcB = function() {
console.log('funcB has called');
}; // 에러
10. Quiz.
1. 기본개념
각각의 출력 결과는?
console.log(a);
function a() {};
var a = 1;
console.log(a);
console.log(a);
var a = 1;
function a() {};
console.log(a);
console.log(a);
var a = 1;
var a = function(){};
console.log(a);
11. 그 외의 함수들
즉시실행함수
1. 기본개념
중첩된 함수 혹은 내부함수
=> closure
(function(){
console.log("Right now!")
})();
function a() {
return function() {
}
}
12. 함수 전달인자 - arguments
=> 가변전달인자 varargs(variable length
arguments)
1. 기본개념
function maxNum(/* 어떤 값이 들어와도 상관 없음 */) {
var max = Number.NEGATIVE_INFINITY;
for(var idx in arguments) {
if(!isNaN(arguments[idx]) && arguments[idx]>max) {
max = Number(arguments[idx]);
}
}
return max;
}
maxNum(1, 21, 3, undefined, 5, 123, false, '1234', 'test');
13. Arguments 객체
- 함수 내부에 존재하는 객체
1. 기본개념
function dirArgu(/*파라미터 선언 없음*/) {
console.dir(arguments);
}
dirArgu(1);
dirArgu(1,2,3,4,5,6,7);
14. 1.기본개념부터 잡아보자
2.호출패턴에 따라 달라지는 this
3. 상속을 가능하게 해주는 Prototype
4. 다른 언어와 다른 유효범위 Scope
+@ 재귀함수를 구현하는 3가지 방법
15. 호출패턴과 this
1. 메서드 호출 패턴
- 호출하는 패턴에 따라 this라는 추가적인 매개변수를 다르게
초기화 한다.
2. 호출패턴에 따라 달라지는 this
var objA = {
sum : 0
, add : function(addVal) {
this.sum += addVal;
return this.sum;
}
}
objA.sum;
objA.add(2);
objA.add(3);
var directAddCall = objA.add;
directAddCall(2); this === objA
this === window
★ This -> 호출한 함수가
속한 오브젝트를 참조
16. 2. 함수 호출 – use strict
2. 호출패턴에 따라 달라지는 this
this === window
this === undefined
this === window
function funcA() {
console.dir(this);
};
console.dir(funcA());
function funcA() {
"use strict";
console.dir(this);
};
funcA();
window.funcA();
use strict : 따로 언급하지 않는 이상 window에 매핑되는 모호함을
허용하지 않음.
17. 3. 생성자에서 호출
2. 호출패턴에 따라 달라지는 this
this === FuncA
function FuncA() {};
var funcB = new FuncA();
FuncA.prototype.checkThis
= function(){
console.dir(this);
};
funcB.checkThis();
18. 4. call 과 apply
2. 호출패턴에 따라 달라지는 this
function A(a,b,c) {
console.log(this.x, this.y, a, b, c);
}
A();
A.call({x:1,y:2}, 3, 4, 5);
A.apply({x:1,y:2}, [6, 7, 8]);
명시적으로 this에
mapping시킬
프로퍼티들을 넘길 수 있다
19. +@ bind를 통한 this mapping
2. 호출패턴에 따라 달라지는 this
call, apply
-> 호출시점에 일시적인 매핑
bind
-> 영구적인 Binding
var newA = A.bind({x:3,y:4});
var newA2 = A.bind({x:3,y:4});
21. 함수의 프로토타입 상속
3. 상속을 가능하게 해주는 Prototype
=> __proto__ 는 생성자의 prototype을 바라보고 있다.
function FuncA() {}
var funcA1 = new FuncA();
console.dir(funcA1);
FuncA.prototype.addedMethod =
function(){ console.log("I'm added"); };
console.dir(funcA1);
22. 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. 변경이 발생했을 때
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에도 모두 적용
25. 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으로 참조하는지)를 확인할
수 있다.
26. 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가 참조되지 않을 수 있다.
27. 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 을 방지할 수 있다
28. Function의 용도가 2가지
: 실행을 위한 함수, 생성자 함수
혼란을 피하기 위해 생성자 함수는 대문자로
시작하도록 권고
크락포드옹님 주의사항
29. * prototype chaining 맛보기
3. 상속을 가능하게 해주는 Prototype
var a = {
func : function(){ console.log(this.val); }
};
var b = Object.create(a);
var c = Object.create(b);
var d = Object.create(c);
var e = Object.create(d);
b.val = 'b.val';
a.val = 'a.val';
e.func(); // b.val
e .__proto__ .__proto__ .__proto__ .__proto__ === a; // true
30. 1.기본개념부터 잡아보자
2.호출패턴에 따라 달라지는 this
3. 상속을 가능하게 해주는 Prototype
4. 다른 언어와 다른 유효범위 Scope
+@ 재귀함수를 구현하는 3가지 방법
31. Quiz.
a = ?
4. 다른 언어와 다른 유효범위 Scope
function aa() {
var a = 1;
function b() {
var a = 2;
c();
}
function c() {
console.log(a);
}
b();
}
aa();
32. Quiz. 항목별 유효범위
4. 다른 언어와 다른 유효범위 Scope
항목별 Scope는
어떻게 될까?
outer()
inner()
x, a, b, c
function outer() {
debugger;
inner();
var a = 1;
function inner() {
var x = 2;
}
var b = 2;
if(a==1) {
var c = 3;
}
console.log(c);
}
outer();
33. 항목별 유효범위
4. 다른 언어와 다른 유효범위 Scope
* JavaScript의 Scope는
블록단위가 아니라 함수 단위
function outer() {
debugger;
inner();
var a = 1;
function inner() {
var x = 2;
}
var b = 2;
if(a==1) {
var c = 3;
}
console.log(c);
}
outer();
!! If 블록을
넘어간다.
Scope 결정요소 :
어디에
선언되었느냐?
변수냐? 함수냐?
outer()
inner()
x a b c
34. 블록 vs. 함수 유효범위
C, Java 등의 언어의 유효범위 : { } (Block)
블록이 끝났다고(})
유효범위가 끝나지
않는다.
⇒ JavaScript의
유효범위 : 함수
4. 다른 언어와 다른 유효범위 Scope
if(window) {
var x =123;
}
console.log(x);
35. 1.기본개념부터 잡아보자
2.호출패턴에 따라 달라지는 this
3. 상속을 가능하게 해주는 Prototype
4. 다른 언어와 다른 유효범위 Scope
+@ 재귀함수를 구현하는 3가지 방법
36. Quiz.
+@ 재귀함수를 구현하는 3가지 방법
arguments?
callee?
괄호는 왜 2개?
function factorial() {
return function(x) {
if (x <= 1)
return 1;
else
return x * arguments.callee(x-1);
};
}
factorial()(5);
37. Quiz.
+@ 재귀함수를 구현하는 3가지 방법
function factorial() {
return function(x) {
if (x <= 1)
return 1;
else
return x * arguments.callee(x-1);
};
}
factorial()(5);
arguments? -> 함수가 실행될 때 생성되는 객체
callee? -> 자신을 호출한 객체
괄호는 왜 2개? -> 첫 번째 괄호는 실행 후에
function(x)를 리턴. 두 번째 괄호를 통해
function(x)를 실행.
38. 재귀 - Function Declaration
=> 어느 곳에서든지 이름으로 호출 가능
+@ 재귀함수를 구현하는 3가지 방법
function factorial(x) {
if (x <= 1) return 1;
else return x * factorial(x-1);
}
factorial(5);
39. 재귀 – 메서드(Function Expression)
=> 익명 함수에 이름을 주면 함수 내에서 사용할
수 있다.
+@ 재귀함수를 구현하는 3가지 방법
var factorial = function recurs(x) {
if (x <= 1) return 1;
else return x * recurs(x-1);
}
factorial(5);
40. 재귀 – arguments.callee (deprecated)
=> 함수가 호출되는 시점에 자신을 호출한
객체를 arguments.callee에 할당한다.
+@ 재귀함수를 구현하는 3가지 방법
var factorial = function(x) {
if (x <= 1) return 1;
else return x * arguments.callee(x-1);
}
factorial(5);