자바스크립트 심화 (1)

김주언·2022년 5월 23일

자바스크립트

목록 보기
4/8

4. 프로토타입과 스코프

  • 자바스크립트 객체의 프로퍼티나 메소드에 접근하는 원리
  • 스코프 - 규칙, 모듈, 클로저, 호이스팅

4.1 프로토타입

자바스크립트는 프로토타입 기반으로 객체 지향의 상속 개념 구현한다.
모든 객체는 자신의 부모 역할을 하는 프로토타입 객체 (이하 프로토타입)의 참조 링크를 가지며, 이 링크를 통해 프로토타입으로부터 프로퍼티나 메서드를 상속받는다. 프로토타입 또한 또 다른 상위 프로토타입으로부터 상속받기 가능하다.

4.1.1 프로토타입

객체의 프로토타입은 참조링크 형태로 [[Prototype]] 내부 프로퍼티에 저장된다. 참조링크 형태로 저장 = 동일 프로토타입 상속 시 모두 같은 프로퍼티와 메서드 공유

[[Prototype]]은 자바스크립트 엔진 내부에서만 사용하는 숨겨진 프로퍼티이지만, 브라우저에서 __proto__ 프로퍼티로 접근 가능

하지만 __proto__는 공식적인 접근 방식 아니니까 웬만하면 쓰지 마로라
[[Prototype]] 접근하려면 Object.getPrototypeOf() 하도록..

4.1.2 프로토타입 체인

const obj = {
  name: 'obj1'
}
console.log(obj.toString()); // [Object object]

obj 객체에 메서드가 없는데 호출 가능한 이유?

  • 프로토타입 체인, 즉 상위 프로토타입과 연결된 구조로 인해서 프로퍼티나 메서드에 접근하기 위해 차례대로 검색하는 행위 (프로토타입 체이닝)을 수행하였기 때문에.

최상위 프로토타입은 Object.prototype이다.

4.1.3 프로토타입과 생성자 함수

모든 함수는 prototype 이라는 특별한 프로퍼티가 존재한다. 이 프로퍼티는 참조링크 [[Prototype]] 과 다르다!! 함수의 prototype 프로퍼티는 특수 역할을 수행하기는 하지만, 일반적인 객체의 프로퍼티이며, 프로토타입을 가리키는 참조링크가 아니다.

생성자 함수에서 prototype 프로퍼티의 역할

생성자 함수로 생성된 객체는 생성자함수의 prototype프로퍼티가 프로토타입( [[Prototype]] )으로 설정된다.

function Vehicle(type) {
  this.type = type;
}

const vehicle = new Vehicle('Car');

console.log(Vehicle.prototype === vehicle.__proto__); //true!

4.1.4 함수의 prototype 프로퍼티와 프로토타입의 관계

함수의 prototype 프로퍼티는 constructor 프로퍼티 하나만 가진 객체.
constructor 프로퍼티는 자신과 연결된 생성자 함수를 가리키며, 이를 통해 객체가 어떤 생성자함수를 통해 생성되었는지 알 수 있다. 즉, 상호 참조 관계


4.2 스코프

스코프는 변수나 매개변수가 접근할 수 있는 범위를 결정한다. 자바 스크립트의 스코프는 아래와 같다

  • 함수 스코프 var
  • 블록 스코프 let, const
  • 렉시컬 스코프

4.2.1 렉시컬 스코프

프로그래밍 언어의 스코프는 대부분 동적 스코프와 렉시컬 스코프 두 가지 방식으로 동작한다. 동적 스코프는 런타임 중 함수의 호출에 의해 결정되고, 렉시컬 스코프는 변수나 함수를 어디에 작성하였는지를 기초하여 결정된다. 자바스크립트는 렉시컬 스코프 기반 언어이다.

❓ 자바스크립트는 렉시컬 스코프를 따르고, this 바인딩만 함수 호출방법에 따라 동적으로 변하는 것
function foo(){
  var a = 1;
  function bar(b) {
    console.log(a,b)
  }
  bar(2);
}
foo();

위 코드의 진행 순서는 아래와 같다.

  1. console.log()에서 참조된 변수 a를 찾기 위해 bar()의 스코프 검색
  2. bar()에서 찾기 실패 -> foo()로 이동
  3. foo()에서 변수 a 찾기 성공, 검색 중단

이러한 스코프들의 연결관계를 스코프 체인이라고 하고, 스코프체인을 따라 검색하는 과정을 스코프 체이닝이라고 한다.


4.3 호이스팅

선언문이 스코프 내의 가장 최상단으로 끌어올려지는 것
호이스팅은 스코프별로 동작한다.


4.4 클로저

: 함수의 렉시컬 스코프를 기억하여 함수가 렉시컬 스코프를 벗어날 외부 스코프에서 실행될 때에도 자신의 렉시컬 스코프에 접근할 수 있게 해주는 것
함수를 사용하는 곳이면 어디든지 적용 가능하다. 클로저를 활용하면 특정 상태를 기억하여 캡슐화하거나 하나의 모듈을 정의하는 패턴으로 확장 가능하다.

function foo(){
  var a = 1;
  function bar() {
    console.log(a)	// 1
  }
  bar();
}
foo();

bar()와 같은 내부 함수가 자신을 감싼 외부 함수를 벗어나 완전히 독립적인 스코프에서 실행되는 경우를 클로저라고 한다.
위 코드를 클로저를 이용한 코드로 변경하면 아래와 같은 코드가 된다.

function foo(){
  var a = 1;
  function bar() {
    console.log(a)	// 1
  }
  return bar();
}
const baz = foo()
baz() // 1

위 코드의 진행 순서

  1. bar() 는 렉시컬 스코프체인으로 foo() 함수의 스코프를 기억
  2. 전역변수 baz 사용하여 bar()호출
  3. bar()는 자신의 스코프에서 변수 a를 찾는다
  4. a 찾기 실패 -> 스코프체인을 통헤 foo()의 스코프에서 a 찾기
  5. foo()의 스코프에서 a 찾아서 1 출력

클로저를 사용하여 외부에서도 원래의 렉시컬 스코프에 접근가능하다

profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글