4주차(월) - 프리 온보딩 코스 프론트엔드 - Core JavaScript 2

minbr0ther·2022년 2월 23일
0

pre-onboarding-fe

목록 보기
15/15
post-thumbnail

🏅 Execution Context

실행 컨텍스트

JavaScript 코드가 실행되고 있는 컨텍스트(환경)를 제공하는 객체

  • 실행컨텍스트는 실행할 코드에 제공할 환경 정보들을(변수 정보들) 모아놓는다.
  • 함수를 실행할 때마다, 그 함수에 대한 새로운 실행 컨텍스트를 생성하여 자신만의 고유한 컨텐스트에서 실행된다.

“실행할 코드”와 콜스택 (=실행스택 =Execution Stack)

  • 함수 각각마다 실행 컨텍스트가 생성됨

  • 전역코드, 함수 코드

  • 전역 컨텍스트는 브라우저를 종료하기 전까지 생성되어 있다.


컨텍스트에 담기는 정보

  1. VariableEnvironment : 변수 객체 정보

  2. LexicalEnvironment : 변수와 함수 선언 저장, 코드가 실행되기 전에 정보를 모두 수집


🏅 Hoisting

함수 선언문과 함수 표현식

함수 선언문(function declaration)

function a() {
	// 로직
}
  • function 정의만 존재하고 별도의 할당 명령이 없다.

함수 표현식(function expression)

자바스크립트 인터프리터가 계산하여 값을 구할 수 있는 자바스크립트 구절을 말한다. 이러한 값을 표현하는 것을 ‘리터럴’이라고 한다.

var a = function() {
	// 로직
}
  • 함수를 정의하고 변수에다가 저장
  • function 키워드로 정의한 함수를 변수에 할당하는 것을 말한다.

Hoisting

  • 호이스팅은 변수의 선언을 끌어올리는 것을 말한다.

  • 선언부는 끌어올리고, 할당은 코드가 실행되는 시점에 진행된다.


함수의 Hoisting

  • 함수 선언식 ⇒ 다른 프로그래밍 언어는 불가능
    catName("Chloe");
    
    function catName(name) {
      console.log("My cat's name is " + name);
    }
    /*
    위 코드의 결과는: "My cat's name is Chloe"
    */
  • 함수 표현식 ⇒ 선언하고 사용안하면 undefined
    console.log(notHoisted) // undefined
    notHoisted(); // TypeError: notHoisted is not a function
    
    var notHoisted = function() {
       console.log('bar');
    };

let, const의 Hoisting

  • let, const는 hoisting이 되지 않는다?
    console.log(x); // Uncaught ReferenceError: x is not defined
    let x = 1;
  • 면접 때 let const 질문하면 hoisting 얘기하는게 좋음 (+ TDZ)
    • 사실은 호이스팅 안되는 것이 아니라 정의가 안 된 것이다(not defined)

Temporal Dead Zone(TDZ)

  • var는 TDZ 가 없다

  • let, const 역시 마찬가지로 LexicalEnvironment에 변수 정보를 미리 수집한다(hoisting의 개념으로 알고 있는 동작)

  • let, const는 실행되기 전까지 액세스 할 수 없고, 이 단계(공간)를 TDZ라고 함

    // Temporal Dead Zone(TDZ)를 확인하는 예제
    
    // x가 있는 것을 알고 있다
    x = 3; // Uncaught ReferenceError: Cannot access 'x' before initialization
    let x = 1;

Quiz

출처 : https://ui.toast.com/weekly-pick/ko_20191014

new Car('red'); //  ReferenceError 

class Car {
  constructor(color) {
    this.color = color;
  }
}
greet('World'); // Hello, World

function greet(who) {
  return `Hello, ${who}!`;
}

🏅 Scope

Scope

변수가 유효한(살아있는) 범위

  • 스코프가 없었다면, 코드 전체에 절대 충돌하지 않는 변수(식별자)명을 딱 하나만 써야 한다. 모든 프로그래밍 언어에 적용되는 개념

Scope 종류

Global Scope

  • 코드 어디에서든지 참조 가능

  • var로 선언한 변수는 전역 객체에 속하게 된다.(프로퍼티가 된다)

  • 만약에 순수 js 라이브러리를 만들게 되면 전역 객체를 써야 할경우가 있다.


Local Scope

  • 자바스크립트의 특이한 성질중 하나

  • JavaScipt는 다른 언어와 달리 scope의 범위가 함수 블록 내이다. ({} 블록과 상관이 없다)

  • ⚠️JavaScipt에서 let, const로 변수를 선언할 때의 scope은 블록({}) 단위이다.

    { 
    	let x = 1; 
    }
    
    console.log(x); //Uncaught ReferenceError: x is not defined

Scope Chain

  • 변수가 해당 scope에서 유효하지 않을 때, 안에서부터 바깥으로 차례로 검색해 나가는 것

  • inner, outer, global scope 순으로 탐색


🏅 Closure

  1. 일급 객체 함수의 개념을 이용하여 스코프에 묶인 변수를 바인딩 하기 위한 일종의 기술
  2. 함수를 일급 객체로 취급하는 여러 함수형 프로그래밍 언어에서 사용되는 보편적인 특성

변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있다. 상태 변경이나 가변(mutable) 데이터를 피하고 불변성(Immutability)을 지향하는 함수형 프로그래밍에서 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이기 위해 클로저는 적극적으로 사용된다. 🔗

  • 함수를 선언할 때 만들어진 scope가 사라진 후에도 호출할 수 있는 함수

  • 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우,
    A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상

  • 의도치 않게 클로저를 사용할 수 있는데 그때 이슈를 해결하기 위해 쓰일 듯 👀

var A = function() {
	var a = 1;

	var B = function() {
		return ++a;
	};

	**return B;**
};

var outer = A();
console.log(outer());  // 2
console.log(outer());  // 3

메모리 관리 (closure’s keyword)

  • JavaScript는 원래 메모리 관리에 신경쓰지 않아도 된다.

    • 사용하지 않는 변수는 알아서 Garbage Collector에 수집 (실행컨텍스트를 참고 하겠죠)
  • 그런데 closure에서는 의도적으로 변수를 사용하므로 ‘메모리가 계속 소모됨’

    • 만약 GC에 수집되게 하려면 null이나 undefined를 할당하면 됨

🏅 This

일반적으로 this는 클래스(class)에서만 사용하며, class로 생성한 인스턴스 객체를 의미하나, JavaScript에서는 그렇지 않고 this가 가르키는 대상이 항상 달라집니다.


함수와 메서드

  • 함수와 메서드는 모두 function 키워드로 함수를 정의한 것을 의미합니다.

  • 그 중에서도 ‘메서드’는 객체의 프로퍼티로 함수가 정의되어야 한다.

let user = {
  name: 'kim',
  underTwenty: function(age) {
    return age < 20;
  }
}

user.underTwenty(30); // 메서드

const under20 = user.underTwenty; // 새롭게 변수에 할당해서 호출?
under20(15); // 객체 안에 정의된 함수라도, 이것은 메서드가 아닌 함수

this

  • this는 실행컨텍스트가 생성될 때 결정된다.

    • 실행컨텍스트는 함수를 호출할 때 생성되므로, this는 함수를 호출할 때 결정된다 👀
  • this가 무엇이냐고 한다면

    • this가 바라보고 있는 객체인데, 상황에 따라 대상이 달라진다.
    • 어떤 객체와 바인드 되어 있는가?

this의 동작 방식

전역 공간에서 this가 바라보는 대상

var a = 1;
console.log(a);
console.log(window.a);
console.log(this.a);

메서드로 호출될 때 this가 바라보는 대상 (암시적 binding)

  • 객체의 프로퍼티에 할당된 함수를 호출하면, this는 해당 객체를 바라본다

    • 물론 객체가 메서드로 호출해야 함
var name = 'lee';

var user = {
	name: 'kim',
	getName: function() {
		console.log(this.name);
	},
	age: 50,
	child: {
		age: 15,
		underTwenty: function() {
			console.log(this.age);
			return this.age < 20
		}
	}
}

user.getName();  // kim | getName 메서드는 user 객체를 바라봄
user.child.underTwenty();  // 15 | underTwenty 메서드는 child 객체를 바라봄

user.parentUnderTwenty = user.child.underTwenty;
user.parentUnderTwenty(); // 50 👀 | parentUnderTwenty 메서드는 user 객체를 바라봄
  • 호출 하는 것의 직전을 본다 ✨

    • child.underTwenty ⇒ child가 this

    • user.underTwenty ⇒ user가 this


Quiz

var name = 'lee';

var user = {
	name: 'kim',
	getName: function() {
		console.log(this.name); //kim
	
		var inner = function() {
			console.log(this.name); //undefined ❌
	    // 정답은 lee, this가 window를 가르킴
		}

		inner(); //window.inner라고 생각해야함 👀
	}
}

user.getName();

call

  • 함수를 호출할 때, 원하는 대상의 객체를 인자로 넘겨준다.
var user = {
  name: 'kim',
  getName: function() {
    console.log(this.name);
  },
  age: 50,
  child: {
    age: 15,
    underTwenty: function() {
      console.log(this.age);
      return this.age < 20
    }
  }
}
// child.underTwentys는 15이다
user.child.underTwenty.call(user); // 50

apply

const nums = [1,2,3,4];

//this가 필요 없는 함수는 Null처리 해줘도 된다
const minNum = Math.min.apply(null, nums); 
const maxNum = Math.max.apply(null, nums);

// call은 매개변수를 하나씩 넣어줘야 한다
const minNumCall = Math.min.call(null, ...nums);
  • call 메서드와 완전히 같은 기능이나, 호출할 함수에 인자를 배열로 넘긴다

bind

  • call과 비슷하지만, 바로 호출하는 것이 아니라 대상을 묶어놓기(binding)만 하는 것

  • 함수의 this 값을 영구히 바꿀 수 있다

const mike = {
  name: "Mike",
};

function update(birthYear, occupation) {
  this.birthYear = birthYear;
  this.occupation = occupation;
}

const updateMike = update.bind(mike);

updateMike(1988, 'police');
console.log(mike);
profile
느리지만 꾸준하게 💪🏻

0개의 댓글