람다 함수
일반함수 기본형 (함수명 포함)
function 함수명(){
함수 로직
}
function honey(){
console.log("hi");
}
TypeScript
복사
익명함수 기본형 (일회용, 함수명 미포함)
익명함수는 메모리를 차지하지 않아 일회용으로 많이 사용된다. ⇒ 불필요한 메모리를 줄일 수 있다.
변수에 주로 담겨서 많이 사용된다. (리터럴 방식)
function() {
함수 로직
}
const honey = function (){
console.log("hi");
}
TypeScript
복사
•
익명함수는 호이스팅 시 위로 올라가지 않고 익명 함수를 저장한 변수만 올라가게 된다.
•
일반 함수일 땐 정상적으로 호이스팅되어 에러 발생X
호이스팅 : 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 이동시키는 과정
// const honey; = 호이스팅 시
honey() // error
// 익명함수
const honey = function (){
console.log("hi");
}
honey()
JavaScript
복사
화살표 함수 == 익명함수
// 화살표함수
const honey = () => {
함수 로직
}
const honey = () => 한줄일 경우의 함수 로직;
TypeScript
복사
일반 함수에서의 this
일반 함수의 경우 this가 object를 가리킴
target = 'global honey'; //전역 변수
function test(){ // 3
console.log(this.target); // local honey
}
const object = { // 1
target: 'local honey', // 4
action: test // 2
}
object.action();
JavaScript
복사
화살표 함수에서의 this
화살표 함수의 경우는 내부의 this는 선언한 시점에서 호출
target = 'global honey';
const test = () => {
console.log(this.target); // global honey
}
const object = {
target: 'local honey', //
action: test
}
object.action(); // 1
JavaScript
복사
라고 적혀있었지만 이는 틀렸다
undefined 로 뜨는 모습
왜 그럴까?
함수 setTimeout에 메서드를 전달할 때처럼, 객체 메서드를 콜백으로 전달할 때 ’this 정보가 사라지는’ 문제가 생긴다.
객체 메서드가 객체 내부가 아닌 다른 곳에 전달되어 호출되면 this가 사라지는데
let user = {
firstName: "Honey",
sayHi() {
console.log(`Hello, ${this.firstName}!`);
}
};
setTimeout(user.sayHi, 1000); // Hello, undefined!
JavaScript
복사
this.firstName이 "John"이 되어야 하는데, 콘솔엔 undefined가 출력된다.
이는 setTimeout에 객체에서 분리된 함수인 user.sayHi가 전달되기 때문이다.
위 예시의 마지막 줄의 확대 버전은
let f = user.sayHi;
setTimeout(f, 1000); // user 컨텍스트를 잃어버림
JavaScript
복사
따라서 위 예시는 this가 아닌 window가 되고 window객체엔 firstName이 없으므로 undefined가 출력
해결책
1.
래퍼 함수 이용하기
외부 렉시컬 환경에서 user를 받아서 보통 때처럼 메서드를 호출해서 해결한다.
렉시컬 환경 : 함수 본인 내부의 식별자 그리고 식별자에 바인딩된 값 등을 기록하고 있는 하나의 자료구조
let user = {
firstName: "Honey",
sayHi() {
console.log(`Hello, ${this.firstName}!`);
}
};
setTimeout(function() {
user.sayHi(); // Hello, Honey!
}, 1000);
// == setTimeout(() => user.sayHi(), 1000); // Hello, Honey!
JavaScript
복사
위 처럼 코드를 작성할 경우 간결하지만 다음과 같은 약간의 취약성이 발생한다.
let user = {
firstName: "Honey",
sayHi() {
console.log(`Hello, ${this.firstName}!`);
}
};
setTimeout(() => user.sayHi(), 1000);
// 1초가 지나기 전에 user의 값이 바뀜
user = { sayHi() { console.log("또 다른 사용자!"); } }; // 다른 사용자!
JavaScript
복사
2.
bind 사용하기
bind는 보통 객체 메서드의 this를 고정해 어딘가에 넘기고자 할 때 사용한다.
•
•
func.bind(context)는 함수처럼 호출 가능한 '특수 객체(exotic object)'를 반환한다. 이 객체를 호출하면 this가 context로 고정된 함수 func가 반환된다.
•
boundFunc를 호출하면 this가 고정된 func를 호출하는 것과 동일한 효과를 본다.
bind 기본 문법
let boundFunc = func.bind(context);
JavaScript
복사
수정된 코드
let user = {
firstName: "Honey",
sayHi() {
console.log(`Hello, ${this.firstName}!`);
}
};
let funcUser = user.sayHi.bind(user);
funcUser(); // Hello, Honey!
// 1초 이내에 user 값이 변화해도
// sayHi는 기존 값을 사용한다.
user = {
sayHi() { console.log("또 다른 사용자!"); }
};
JavaScript
복사
그렇다면 다시 그 문제로 돌아가서 해결방법은 무엇일까?
해당 this는 상위 영역의 data를 찾기에 {}가 들어가게 된다.
1.
그냥 전역변수를 가져오거나
target = 'global honey';
const test = () => {
console.log(target); // global honey
}
const object = {
target: 'local honey',
action: test
}
object.action();
JavaScript
복사
2.
함수 내부에서 this.target을 지정해준다.
target = 'global honey';
const test = () => {
this.target = target;
console.log(this.target); // global honey
}
const object = {
target: 'local honey',
action: test
}
object.action();
JavaScript
복사
3.
혹은 this.target을 밖에서 지정해주거나
this.target = 'global honey';
const test = () => {
console.log(this.target); // global honey
}
const object = {
target: 'local honey',
action: test
}
object.action();
JavaScript
복사
의 또 반전은 해당 환경을 Node에서 진행했기 때문..
노드는 js랑 다르게 global 객체를 가르키기 때문에 하나의 함수로 동작하므로 지역객체가 된다.
그래서 nodejs에서는 this가 module.export를 가리키고 해당 객체가 target이란 멤버를 가지고 있지 않아서 undefined이 뜬것 이였다..
-해피엔딩-