All Articles

[20190703 TIL] Javascipt 프로토타입


오늘의 TIL


delete 연산자

delete 연산자는 객체 프로퍼티만 삭제 가능하고, 객체 자체는 삭제하지 못합니다.

아래의 예제를 통해 보면, foo 객체 자체를 삭제하는 구문이 에러 없이 실행은 되지만, 삭제되지 않고 foo 객체의 프로퍼티가 출력되는 것을 볼 수 있습니다.

var foo = {
  name : 'foo',
  age : 30
};

console.log(foo.name);  // foo

// foo의 name 프로퍼티 삭제
delete foo.name;
console.log(foo.name);  // undefined

// foo 객체 삭제
delete foo;
console.log(foo.age);  // 30

프로토타입

[ 객체 리터럴 방식과 생성자 함수를 통한 객체 생성 방식의 차이 ]

객체 리터럴 방식

  • 같은 형태의 객체를 재생성할 수 없음

  • 객체의 __proto__ 프로퍼티의 값이 Object 이다.

생성자 함수를 통한 객체 생성 방식

  • new 객체 생성으로 다른 인자를 넘김으로써 같은 형태의 서로 다른 객체 생성 가능

  • 객체의 __proto__ 프로퍼티의 값이 ‘생성자 함수’ 이다.

예제를 보면,

// 객체 리터럴 방식
var foo = {
  name : 'foo',
  age : 35,
  gender : 'man'
};

//생성자 함수를 통한 객체 생성 방식
function Person(name, age, gender) {
  this.name = name;
  this.age = age;
  this.gender = gender;
}

var bar = new Person('bar', 33, 'woman');
var baz = new Person('baz', 25, 'woman');

자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정합니다.

객체 리터럴 방식에서는 객체 생성자 함수가 Object() 이고,

생성자 함수 방식의 경우는 ‘생성자 함수 자체’로 예제에서는 Person() 이므로 다른 프로토타입 객체를 가집니다.

[*참고 - __proto__ 프로퍼티는 크롬환경인 경우 나타납니다. __proto__ 프로퍼티는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체인 부모 객체를 숨겨진 링크로 연결한다고 생각하면 됩니다.]

위의 설명을 아래의 그림으로도 표현해보았습니다.

먼저 객체 리터럴 방식으로 생성된 foo 객체를 그림으로 나타내면 아래와 같습니다.


object.jpg


다음으로 Person 생성자 함수를 통해 만들어진 bar 객체, baz 객체를 그림으로 나타내면 아래와 같습니다.


person.jpg



실행 컨텍스트

실행 가능한 코드를 형상화하여 구분하는 추상적인 개념.

즉, 실행 가능한 자바스크립트 코드 블록이 실행되는 환경입니다.

실행 컨텍스트에서 중요하게 알아야 되는 스코프 체인 이 있습니다.

스코프 체인

C 언어 같은 경우에는 { } 묶여 있는 범위 안에서 선언된 변수는 블록이 끝나는 순간 사라지므로, 밖에서는 접근할 수 없습니다. 특히 함수의 { } 뿐만 아니라 if, for 문의 { }로 한 불록으로 묶여, 그 안에서 선언된 변수가 밖에서는 접근이 불가능합니다.

하지만 자바스크립트에서는 함수 내의 { } 블록은 이를테면 for() {}, if {} 와 같은 구문은 유효 범위가 없습니다. 오직 함수만의 유효범위의 한 단위가 됩니다. 이 유효 범위를 나타내는 스코프가 [[scope]] 프로퍼티로 각 함수 객체 내에서 연결 리스트 형식으로 관리되는데, 이를 스코프 체인이라고 합니다.

각각의 함수는 [[scope]] 프로퍼티로 자신이 생성된 실행 컨텍스트의 스코프 체인을 참조합니다. 함수가 실행되는 순간 실행 컨텍스트가 만들어지고, 이 실행 컨텍스트는 실행된 함수의 [[scope]] 프로퍼티를 기반으로 새로운 스코프 체인을 만듭니다.

예제를 통해 정리해봅시다.

var value = "value1";

function printFunc() {
  var value = "value2";

  function printValue(){
    return value;
  }
  console.log(printValue());
}

printFunc();

execution_context.jpg


printValue 함수에서 사용하는 value 변수는, printValue 실행 컨텍스트의 변수 객체가 가지는 [[scope]] 프로퍼티 내에 있는 printFunc 변수 객체에서 찾아, 결과값은 “value2”가 됩니다.


위의 예제처럼 자신의 함수 내에 없는 변수여도, 자신의 실행 컨텍스트 내에 [[scope]] 프로퍼티가 가지고 있는 변수 객체들의 리스트에 있는 변수는 사용 가능합니다.