사전 문제 1
function Dog(name, age) {
this.name = name;
this.age = age;
}
const dog = Dog('happy', 3);
console.log(dog.name);
위 코드는 오류가 발생하는데, 그이유는
Dog 함수는 반환 값이 없기에 dog엔 undefiend 값이 들어가게 되고, undefined.name을 찾을 수 없기에 오류가 발생한다.
또한 추가로 함수안에 있는 this는 window를 가르키기에 window.name을 찍으면 happy 가 나온다
✅ 왜 this가 window를 가르킬까 ?
- 그 이유는 함수를 new를 통해 생성하지 않았기 때문이다.
- new를 사용하지 않고 함수를 선언할 시 함수 내부의 this는 window를 가르킨다.
- new를 사용하여 dog 을 생성하면 this는 Dog함수를 가르키게 된다.
사전 문제 2
(function(name){
console.log(`Hello, ${name}`)
})('beni');
위 코드는 Hello, beni 가 출력된다.
ㅅ위 처럼 작성하는 함수 방식을 IIFE(즉시실행함수)라고 하는데, 사용하는 이유는 크게 두가지가 있다.
◼ 전역(window)에 필요없는 변수 생성을 막을 수 있다.
- 즉시실행함수 내부에 변수를 선언할 시, 내부 변수는 전역 변수가 아닌 지역변수로 남는다.
따라서 전역스코프가 오염되는 것을 줄일 수 있다.
◼ privte 변수를 생성할 수 있다.
const person = (function(){
let age = 24;
function getAge(){
return age;
}
return { getAge : getAge }
})();
위 코드에서 age는 직접적인 변경이 불가능하며, 접근자함수(getAge)로만 age를 확인할 수있다.
사전문제 3
- this의 범위에 대한 문제
var obj = {
name : "beni",
obj2 : {
obj3 : {
name : "euna",
newName : function(){ console.log(`${this.name}`)}
}
}
}
newName() 함수는 euna를 출력한다.
newName() 함수내 this는 obj3를 가르키기에 beni가 아닌 euna를 가르킨다.
사전문제 4
function school(students){
this.students = students;
this.play = function () {
setTimeout(function(){
this.students.forEach(function(student){
student.play();
})
}, 1000)
}
}
var catholic = new school([
{
student: 'beni',
play: function() {}
}
});
catholic.perform();
위 문제도 this의 범위에 대한 문제인데, setTimeout() 함수 내 this는 setTimeout() 내 function 을 가르킨다
따라서 this안에 students가 없기때문에 에러가 발생한다.
위 문제를 해결할 수 있는 방법은 크게 3가지가 있다.
◼ Arrow Function 이용하기
setTimeout(() => {
this.students.forEach(function(student){
student.play();
})
}, 1000)
- Arrow Function은 자기 자신의 함수 스코프를 만들지 않고 해당 Arrow Function 상위의 Scope를 가진다.
따라서 this는 school 객체를 가르키게 된다.
◼ bind() 이용하기
setTimeout(function(){
this.students.forEach(function(student){
student.play();
})
}.bind(this), 1000)
- bind() 메서드를 이용하면 this를 지정해 줄수 있다.
bind는 새로운 함수를 생성하는 메서드로 위 코드에서의 bind안 this는 school을 가르키기에
내부 함수에서 this가 school을 가르키게 된다.
◼ 클로저 이용하기
function school(students){
var that = this;
this.students = students;
this.play = function () {
setTimeout(function(){
that.students.forEach(function(student){
student.play();
})
}, 1000)
}
}
- school을 가르키는 속성을 선언해주고 내부에서 사용해주는 방식이다.
사전문제 5
function counting() {
let i = 0;
for(i=0; i<5; i++){
setTimeout(function (){
console.log(i);
}, i*100);
}
};
counting();
- 위 코드를 출력하면 5만 5번 출력한다.
- 그 이유는 setTimeout()에 인자로 넘긴 익명함수는 0.1초후에 호출되는데,
이미 0.1초 동안 반복문은 모두 순회하여 i 가 5가 되버렸기에 이미 5가된 i를 출력하게 되는 것이다.
👉 해결방법 1 IIFE(즉시 실행 함수 표현)
function counting() {
let i = 0;
for(i=0; i<5; i++){
(function (number) {
setTimeout(function (){
console.log(i);
}, i*100);
})(i);
}
};
counting();
👉 해결방법 2 : 매 루프마다 클로저 생성하게 하기
function counting() {
for(let i=0; i<5; i++){ // var 쓰면 안된다(호이스팅되기때문)
setTimeout(function (){
console.log(i);
}, i*100);
}
};
counting();
👉 해결방법 3 : forEach 메서드 사용하기
사전문제 6
var | 함수 레벨 스코프 변수 재할당 가능 호이스팅 O |
let | 블록 레벨 스코프 변수 재할당 가능 |
const | 블록 레벨 스코프 변수 재할당 불가능 |
* 호이스팅 : function scope상 맨 위로 var 선언이 끌어올라지는 현상
* let과 const가 hosting이 일어나지 않는 것은 아니다. 스코프에 변수가 만들어지고 TDZ(Temporal Dead Zone)이
생성되지만, 코드 실행 변수 실제 위치에 도달할 때까지 액세스 할 수 없는 것 (할당되기전에 호출 시 에러남)
사전문제 7
💡 클로저란 ?
함수가 선언된 환경의 스코프를 기억하여 함수가 스코프 밖에서 실행될때에도 기억한 스코프에 접근할 수 있게 함
- 은닉화 : 클로저를 이용하여 내부 변수와 함수를 숨길 수 있음
'Frontend > 프로그래머스 FE 데브코스' 카테고리의 다른 글
[DAY 11] VanillaJS를 통한 자바스크립트 기본 역량 강화 I (3) (0) | 2022.10.31 |
---|---|
[DAY 10] VanillaJS를 통한 자바스크립트 기본 역량 강화Ⅰ(2) (0) | 2022.10.28 |
[Day 8] JavaScript 주요 문법 (8) (0) | 2022.10.26 |
[Day 6] JavaScript 주요 문법 (6) (0) | 2022.10.25 |
[Day 5] JavaScript 주요 문법 (5) (0) | 2022.10.21 |