Functions
함수 선언과 호이스팅
console.log(`🔥 ${factorial(10)}`);
-
function factorial(x) {
if (x <= 1) return 1;
return x * factorial(x - 1);
}
- 즉 어디에서 선언하든 상관없이 호이스팅이 가능
- 하지만 전통적인 방식으로 함수를 만들어줘야 가능하다.
함수 변수 선언 - 호이스팅 불가능
const square = function (x) {
return x * x;
};
- 다음과 같은 방식으로 변수에 함수를 선언하면 호이스팅이 불가능하다.
화살표 함수, 함수의 변형
functon square(x){
return x * x ;
};
const square = function (x) {
return x * x;
};
const square = (x) => {
return x * x;
}
const square = (x) => x * x;
- 이는 다 똑같은 함수 선언 방식이다. 다만 이처럼 화살표를 사용해서 식을 만들 수도 있다. 이는 Array에서 배웠던 Map이나 filter에도 축약해서 사용한다.
Nested Funtions(중첩 함수)
function hypotenuse(a, b) {
function square(x) {
return x * x + a * b;
}
return square;
}
let s1 = hypotenuse(10, 20);
let s2 = hypotenuse(5, 5);
console.log(s1(10));
console.log(s2(2));
- 함수들은 함수 안에서 정의될 수 있다.
- inner function은 콘솔에서 검색할 수 없다. private한 것.
따라서 outer funtion에서만 접근할 수 있다.
- 그리고 s1과 s2는 각각의 a,b를 가지는 독립적인 공간이다.
Invoking Funtions
let calculator = {
operand1: 1,
operand2: 1,
add() {
this.result = this.operand1 + this.operand2;
},
};
calculator.add();
calculator.result;
- 객체 안에서 add : function()을 add()로 생략할 수 있다.
- this.result의 경우 원래 존재하지 않았던 프로퍼티므로 새로 생성이 된다.
this 사용법 = 그냥 함수
let o = {
m: function () {
let self = this;
function f() {
this === o;
self === o;
}
},
};
- 중첩된 함수 안에서는 외부함수의 this를 사용할 수 없다.
- 따라서 변수에 this를 할당하고 사용한다.
- 참고로 이렇게 선언하면 함수 내 호이스팅이 가능하다.
this 사용법 = 화살표 함수
let o = {
m: function () {
const f = () => {
this === o;
};
},
};
- 화살표 함수의 경우 this를 사용할 수 있다.
- 마찬가지로 내부함수의 호이스팅이 불가능하다.
bind()
let o = {
m: function () {
const f = function () {
console.log(`👏 ${this === o}`);
}.bind(this);
f();
},
};
-
let k = function (a) {
return this.x + a;
};
let k_bind = k.bind({ x: 10, y: 20 });
console.log(`👏`, k_bind(5));
- bind() 메소드를 사용하면 this로 미리 묶어서 지정해주는 것이다.
- this를 굳이 따로 사용하지 않고 객체에 지정해놓는 것.
함수 인자에 spread operater 사용하기
max(1, 10, 100, 2, 3, 1000, 4, 5, 6);
-
function max(first = -Infinity, ...rest) {
let maxValue = first;
for (let n of rest) {
if (n > maxValue) {
maxValue = n;
}
}
return maxValue;
}
- ...rest를 사용하면 변수를 여러개 받겠다는 뜻이다.
- 배열인 max를 넣어주면 첫번째 값인 1이 first에 들어가고,
나머지는 rest에 들어가게 된다.
Array.sort()
let a = [33, 4, 1111, 222];
a.sort();
-
a.sort(function (a, b) {
return a - b;
});
-
- return값이 음수면 a가 앞에, 0이면 위치 유지,양수면 b가 앞에로 정렬한다.
- 기본적으로 오름차순으로 정리가 된다.
함수도 프로퍼티를 가질 수 있다.
uniqueInteger.counter = 0;
function uniqueInteger() {
return uniqueInteger.counter++;
}
/
uniqueInteger();
uniqueInteger();
uniqueInteger();
uniqueInteger();
- 함수도 일급객체이기 때문에 프로퍼티를 가질 수 있다.
함수 내에서 선언된 변수가 겹칠때 + 익명함수
let global = "hi";
function chunkNamespace() {
let global = "hello";
function aaa() {
console.log("🌟", global);
}
aaa();
}
chunkNamespace()
(function () {
let global = "Dweb";
function dweb() {
console.log("🌟", global);
}
dweb();
})();
- 함수 밖에서 선언된 변수와 함수 내부에서 선언된 변수명이 겹칠 수 있다.
- 이 경우에는 함수 내부에 있는 변수를 사용한다. 내변수 ㅎㅎ
Closures1
let scope = "global scope";
function checkscope() {
let scope = "local scope";
function f() {
return scope;
}
return f();
}
let v = checkscope();
- lexical scoping.
- 오직 전해진 매개변수 안에서만 정의되는 함수. 함수 밖에서 변수가 어떻게 정의되든 상관없이 아주 안정적인 함수라고 할 수 있다.
Closures2
let uniqueInteger2 = (function () {
let counter = 0;
return function () {
return counter++;
};
})();
uniqueInteger2.counter = 100;
uniqueInteger2();
uniqueInteger2();
- 이렇게 내부에서 변수를 선언해놓으면 외부에서 절대 접근할 수 없기 때문에 안정적이다.
Closures3
function counter() {
let n = 0;
return {
count: function () {
return n++;
},
reset: function () {
n = 0;
},
};
}
/
let c = counter(),
d = counter();
console.log(c.count(<));
console.log(d.count());
c.reset();
console.log(c.count());
console.log(d.count());
- c와 d는 완전히 다른 독립적인 공간이다.
- 따라서 메소드들도 독립적으로 작용한다.
get(), set()
function counter(n) {
return {
get count() {
return n++;
},
set count(m) {
if (m > n) n = m;
else throw Error("count can only be set to a larger value");
},
};
}
- get과 set이 문법적으로 정의 내려져있다.
loop를 통해 클로저 생성
function constfunc(v) {
return () => v;
}
let funcs1 = [];
for (var i = 0; i < 10; i++) funcs1[i] = constfunc(i);
funcs1[5]();
funcs1[6]();
- 루프를 통해서 리턴값으로 함수를 집어넣을 수 있다.
그리고 그 함수의 리턴은 i가 될 것.
함수 프로퍼티
function func1() {}
-
function func2(a, b) {}
-
console.log(func1.length, func1.name);
-
console.log(func2.length, func2.name);
-
- 함수도 프로퍼티를 가질 수 있다. 아규먼트의 갯수와 이름을 반환해준다.
call() 메소드
let obj = { class: "dweb", prof: "giseok" };
let fullname = function (name) {
this.class = "incheon" + this.class;
this.prof = this.prof + name;
console.log(name);
};
fullname.call(obj, "park");
- call 메소드를 쓰면 fullname의 첫번째 프로퍼티에는 obj가 들어간다. 즉 객체를 전달.
- 그리도 두번째 name에는 "park"이 들어가게 된다.
Constructor
const f = new Function("x", "y", "return x*y;");
- 컨스트럭터를 사용해서 함수를 생성하면 런타임에 함수가 생성된다. 즉 그래서 LEXICAL SCOPING을 사용하지 않음.