Front-End 면접 질문 대비 Part1 (hoisting, closure, this)

holim0·2021년 1월 1일
23

직무 면접 대비

목록 보기
1/4

이번에 면접 대비를 위해 프론트 엔드 분야에서 알아야 될 내용들을 정리하고자 합니다.


Hoisting

➡️ 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것. 끌어올린다고 생각하면 됩니다.

여기서 유효 범위는 함수 블록 {} 안을 뜻합니다.

호이스팅의 대상

var 변수 선언과 **함수 선언문(Function Declaration)**에서만 호이스팅이 일어납니다.

=> 여기서 var 변수의 할당은 호이스팅이 이뤄지지 않습니다. (런타임 과정에서 이루어지기 때문)

=> let/const 변수 선언함수 표현식에서는 호이스팅이 이뤄지지 않습니다.

Example)

calculateAge(1999);   // 함수 선언 전에 함수를 호출 -> hoisting 이 되어 잘 작동한다. 

function calculateAge(year){  // 함수 선언. 
    console.log(2020 - year);
}

//retirement(1990);   // 작동하지 않는다

var retirement = function(year) {     // 함수의 선언 방식이 아니기 떄문에 hoisting 되지 않는다. (only work on function declaration)
    console.log(65- (2020- year));
}

//variables (변수)

console.log(age); // 작동은 되지만 undefined로 뜬다. (hoisting) -> js 가 변수가 선언되었는지는 알고 있는 것이다. 

// 변수의 선언만 호이스팅.

var age = 50;  //global 

console.log(age);

function foo(){
    var age = 65; //local
    console.log(age);   //local print
}

foo();  
console.log(age);  // global print

호이스팅 우선순위

➡️ 변수 선언이 함수 선언보다 높은 우선순위를 가집니다.

var myName = "hi";

  function myName() {
      console.log("yuddomack");
  }
  function yourName() {
      console.log("everyone");
  }

  var yourName = "bye";

  console.log(typeof myName);  // string
  console.log(typeof yourName); // string


Closure (클로져) ✨

✅ 두 개의 함수로 만들어진 환경으로 특별한 객체의 한 종류

-> 외부 함수 호출이 종료되더라도 외부 함수의 지역 변수 및 변수 스코프 객체의 체인 관계를 유지할 수 있는 구조를 클로저라고 합니다.

++ 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수

var color = 'red';
function foo() {
    var color = 'blue'; // 2
    function bar() {
        console.log(color); // 1
    }
    return bar;
}
var baz = foo(); // 3
baz(); // 4

-> 여기서 baz가 클로져입니다.

  • outer 함수의 context에 속해있는 변수를 참조합니다.

  • outer 함수의 지역변수로 존재하는 color를 자유변수라고 합니다.


클로져의 활용

  1. 상태 유지

  2. 전역 변수의 사용 억제 => 자신이 생성되었을 때의 lexical 환경을 기억하기 때문이다.

  3. 정보의 은닉

참고 : https://poiemaweb.com/js-closure



this

✅ 자바스크립트에서 모든 함수는 실행될 때마다 함수 내부에 this라는 객체가 추가됩니다.

✅ this는 함수가 호출되는 상황에 따라서 달라집니다.

1. 객체의 메서드를 호출할 때

객체의 프로퍼티가 함수일 경우에는 메서드라고 합니다.

var myObject = {
  name: "foo",
  sayName: function() {
    console.log(this);  // 여기서 this는 myObject를 참조 
  }
};
myObject.sayName();
// console> Object {name: "foo", sayName: sayName()}

➡️ 메서드에서 this 는 메서드를 포함하고 있는 객체를 참조합니다. (해당 메서드를 호출한 객체가 바인딩 되는 것)

2. 함수를 호출할 때

✅ 객체의 메서드가 아니라 함수를 호출하면 this 는 전역 객체에 바인딩됩니다.

var value = 100;
var myObj = {
  value: 1,
  func1: function() {
    console.log(`func1's this.value: ${this.value}`);

    var func2 = function() {
      console.log(`func2's this.value ${this.value}`);
    };
    func2();
  }
};

myObj.func1();
// console> func1's this.value: 1
// console> func2's this.value: 100
  • func 은 myObj 객체의 메서드이기 때문에 this에는 myObj가 바인딩 된다.

  • func2는 메서드가 아닌 함수이기 때문에 this에는 전역 객체가 바인딩된다.


3. 생성자 함수를 통해 객체를 생성할 때

✅ new 키워드를 통해서 생성자 함수를 호출할 때는 this는 객체 자신이 됩니다.

✅ new를 사용하면 빈 객체가 생성되는 것입니다.

let Person = function (name, year, job) {
    this.name = name;
    this.year = year;
    this.job = job;
    console.log(this);
};

var john = new Person("hi", 1996, "hoho"); // new 를 통해서 새로운 빈 object 가 생성된 것이다. 그리고john 에 할당해주는 것이다. 

var Person = function(name) {
  console.log(this);
  this.name = name;
};

var foo = new Person("foo"); // Person
console.log(foo.name); // foo

4. apply, call, bind를 통한 호출

➡️ bind 는 함수가 가리키는 this 만 바꾸고 호출하지 않음. (this 를 고정시킨다)

➡️ call 은 this를 바인딩하고 함수를 호출하고 실행시킨다. (this 를 설정해줄 수 있다)

➡️ apply 는 call과 거의 똑같지만 인자 전달을 배열로 해준다.

var john = {
    name: "heeje",
    age: 25,
    job: "student",
    presentation: function (style, day) {
        if (style === "formal") {
            console.log(
                "good moring" + day + "i'm " + this.name + this.job + this.age
            );
        } else if (style === "friendly") {
            console.log("hey what's up?" + this.name + this.job + this.age);
        }
    },
};

john.presentation("formal", "morning");

var jane = {
    name: "jane",
    age: 25,
    job: "pro",
};

john.presentation.call(jane, "friendly", "afternoon"); //  call method (jane 을 전달. this를 바인딩 )

// => john.presentation.apply(jane, ["friendly", "afternoon"]);

let johnFriendy = john.presentation.bind(jane); //bind method -> this를 jane 으로 변경 -> 함수를 실행하지 않는다.
johnFriendy("friendly", "moring");

마무리

앞으로의 면접 준비를 위해서 글을 정리해보았습니다.

profile
매일 조금씩 성장하고 있는 개발자입니다.

0개의 댓글