0913 - 0919

0913

46일 차

1교시

Number.isNaN은 타입이 Number이고 값이 NaN인 경우에만 true를 반환한다.
반면 isNaN은 숫자 타입으로 암묵적 형번환을 한 뒤 비교한다.

화살표 함수는 무조건 익명 함수 표현식으로 써야 한다.

2교시

프로퍼티 축약표현
메서드 축약표현
-> 단어도 기억해둘 것

객체의 프로퍼티 값에 function 키워드로 들어가는 경우에는 메서드가 아니라 함수다.
함수라고 하는 것은 여러가지 용도가 있다. 일반적인 용도로 쓰는 것을 일반함수, 객체를 생성할 수 있는 능력을 가지고 있는 함수를 생성자 함수라고 한다.
객체.메서드명();는 메서드로서 호출했다고 한다.
일반적으로 메서드라고 함은 프로퍼티로 값이 함수가 온 것이다. 위에서 말한 메서드는 스펙 상의 메서드
메서드 축약 표현을 사용해서 표기하는 방법만 사용하도록 한다.

원시 타입은 기본 타입이라고 부르기도 한다. -> primitive
원시 타입은 변경 불가능한 값이다. -> immutable
객체는 변경 가능한 값이다. -> mutable

  • 단 선두 어드레스는 바뀌지 않는다.

객체도 원시값처럼 사용하려는 움직임이 보이고 있다.
두 객체가 값이 같은지 비교하는 함수 만들기 -> 숙제
isEqual, deepCopy

3교시

매개변수와 인수의 개수가 다를 때 어떻게 처리할 것인가?
-> Arguments 객체의 length를 확인한다.
단, 화살표 함수의 경우 arguments 객체를 갖지 않는다.
-> 이때는 매개변수를 ...args로 받아와야 한다. 이렇게 하면 인수들이 배열로 들어오게 된다.

자바스크립트에서 프로퍼티 키에 해당하는 값이 없으면 undefined가 나온다.

함수명(매개변수) 의 함수 호출 연산자의 경우 앞에 함수명과 같은 식별자가 있는지 찾는다.
또한 식별자가 함수인지까지 확인한다.

호이스팅은 선언문이 스코프의 상단에 끌어올려지는 것처럼 동작하는 특징이다. 그래서 함수 선언문은 런타임 이전에 함수 호이스팅이 발생해서 선언문 이전에 호출이 가능하다.

가장 좋은 방법은 arrow function -> 가독성
ajax 호출에서 객체를 바로 생성해서 보내는 이유
-> 변수에 담지 않고 한 번만 사용해서 다시 재사용하지 못하게 하기 위해서

4교시

중첩 함수
가독성과 재사용성 측면에서 함수를 외부 함수 내에 만든 것이다.

콜백 함수는 고차 함수를 호출할 때 인수로 사용되는 함수를 뜻한다.
콜백함수는 중첩함수와 연관이 있는데, 중첩함수는 고정적이므로 외부함수와 의존성이 높다. 반면 콜백함수는 외부에서 주입하는 것이므로 함수의 자유도가 높아진다.

항상 하는 일 + 계속 바뀌는 일
여기서 항상 하는 일은 고차함수의 기본 세팅으로 놔두고, 바뀌는 일을 콜백함수로 주입하여서 구현한다.

콜백함수는 대부분 고차함수가 호출한다. but 콜백함수를 고차함수가 호출하지 않는 경우가 있는데 그것이 바로 비동기이다.

predicate는 콜백 함수인대, true나 false를 반환하는 콜백함수이다.
자바스크립트는 싱글 스레드, 브라우저는 멀티 스레드이기 때문에 비동기 함수에서 기다렸다가 호출하는 일을 브라우저에게 위임한다.

0914

47일 차

2교시

다른 함수는 메인함수(진입점)이 존재하는 함수가 많다.
그러나 자바스크립트는 진입점이 존재하지 않는다.
자바스크립트 파일을 불러들이게 되면 로드하고 바로 실행한다.

모듈은 파일을 구분했을 때 파일들이 스코프를 갖는다. (간단하게 얘기한 것)
export와 import 키워드 두개를 통해서 다른 스코프에 있는 데이터를 가지고 올 수 있다.

테스트와 코드를 분리해서 만들어야 한다. 왜냐하면 테스트를 배포해서는 안되기 때문이다.

jest에서 toBe는 ===, toEqual은 내용이 같아야 한다.

3교시

식별자는 유효한 범위가 있는데, 스코프라는 것이 사라지면 그 안에 있었던 식별자들도 같이 날라간다.
호이스팅이란 스코프의 최상단으로 끌어올려진 것처럼 보여지는 것

스코프라는 것은 개념이 아니라 자료구조가 있다고 생각하는 것이 쉽다.
-> 렉시컬 환경

모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다.

상속과 스코프는 유사한 개념. 둘 다 밑에서 위만 볼 수 있다.

var는 함수 레벨 스코프, let과 const는 블록 레벨 스코프

함수가 호출되면 객체가 하나 만들어진다.
함수안의 식별자들은 사실 실체안의 프로퍼티 키와 값으로 존재한다.

어떻게 런타임 이전에 변수를 선언할까?
AST를 만들어서 선언문만 쫙 뽑아낸다.
함수 또한 선언문을 호이스팅하기 때문에 선언한다. 함수 객체를 텍스트로 정의한다 (껍데기만).
함수는 호출이 발생하기 전까지는 함수 몸체 내용은 쳐다도 안본다.

식별자는 스코프 체인, 객체는 프로토타입 체인에 존재한다.
식별자를 찾는 행위, 프로토타입을 찾는 행위를 해당 존재하는 공간에서 찾는다.

하위 스코프에서 식별자 이름이 같은 것을 먼저 찾아서 상위 스코프에 같은 이름을 가진 식별자가 무시당하는 것을 가리워졌다, 쉐도잉 등의 단어로 표현한다.
그리고 이렇게 하위 스코프에서 식별자를 사용하기로 한 것을 식별자 결정이라고 한다.

전역 스코프는 스코프 체인의 종점

4교시

렉시컬 스코프 (정적 스코프)

상위 스코프를 어떻게 결정할 것인지의 메커니즘
변수의 스코프는 선언문의 위치에 따라 결정된다.
함수의 정의된 스코프가 상위 스코프이다.

반면 동적 스코프는 함수의 호출 위치가 상위 스코프를 결정한다.
대부분의 언어는 렉시컬 스코프이다.

함수 객체(함수)는 객체와 다른점이 하나인대, 호출이 가능하다는 것이다.
[[call]] 내부 슬롯을 가지고 있다.
내부 슬롯이란 자바스크립트 엔진이 보기위한 프로퍼티이다. 그래서 사용자는 접근할 수 없다.

함수 객체는 자신이 생성될 때 내부 슬롯 environment를 가진다. environment의 값이 상위 스코프에 대한 참조이다.
함수가 어디에 선언되는지에 상관없이 고정되는 이유.

모듈을 쓰는 환경에서는 전역변수를 선언할 수 없다.

책에 나와있는 모듈은 ESM이다.

0915

48일 차

1교시

버전 정보

1.7.3 버전 정보를 명시하는데, 맨 앞의 1 Major은 breaking change가 발생한것. 이전 버전과 다르게 동작할 수 있다.
두 번째 7 Minor는 기능 변경. 성능 변경이 발생한 것
마지막 3은 기타 버그 패치
-> 마음대로 버전업을 하면 안된다.

package.json

package.json에서 ^은 npm install을 다시 하더라도 메이저 버전은 바꿔주지 않겠다는 뜻
설치할 때도 의존성인지 개발 의존성인지 확인을 잘 하고 깔아야한다.

결국 package.json은 개발환경을 공유하기 위함

2교시

메서드를 어디에 집어넣을 것이냐? 빌트인 객체들은 어떻게 메서드를 구성했는가에서 힌트를 찾을 수 있을 것이다.

for…in문과 Object.keys()

객체 프로퍼티를 열거할 때에는 순서가 무의미하다.
in 연산자는 객체의 프로퍼티를 확인하기 위해 사용을 하는대, 상속받아서 사용할 수 있는 프로퍼티까지 다 열거한다.
Object.keys()는 상속받은 프로퍼티는 제외하고 열거한다.
for… in 문에서는 const 키워드를 사용해서 변수를 선언하는대, 그 이유는 for…in 문에서는 재할당을 하지 않고 돌 때마다 새로 선언하기 때문이다.

__proto__는 왜 함수가 아니라 접근자 프로퍼티로 만들었을까?

Object.freeze는 쓰일일이 있는데, 객체를 상수처럼 사용하고 싶을 때 쓰인다.

react에서는 불변 객체인 것 처럼 객체를 사용하라고 하는데, 이 말은 원시값처럼 사용하라는 것이다. 복사해서 값을 바꿔치기

4교시

클래스의 문제점

프론트엔드 개발자는 이벤트 처리를 해야 한다.
클래스를 사용하면 네임스페이스처럼 사용할 수 있다는 문제점이 있다.
클래스는 일반 객체를 만들기에는 좋지만, 내부에 많은 이벤트 로직을 포함하고 있으면 this가 꼬여서 문제가 발생할 수 있다. 함수로 객체를 만들기 위해서는 클로저를 알아야 한다.

메서드 공유

프로퍼티는 생성자 함수가 생성한 객체마다 똑같을 수도 있지만 다르게 유지해야 한다. 하지만 메서드는 굳이 똑같이 동작하는데 다르게 생성할 필요가 없다. 그래서 프로토타입으로 공유하는 메서드를 올려서 상속받아 쓰면 이 문제를 해결할 수 있다.

5교시

함수가 일급 객체라는 뜻은 JS는 함수형 프로그래밍이다 라는 뜻

화살표함수는 내부에 arguments를 가지고 있지 않다.
…으로 인수를 받아서 해결하면 된다.

arguments는 유사배열인데, 배열이 가지고 있는 유용한 메서드들을 사용할 수 없다.

모든 객체는 프로토타입 객체를 갖는다. 프로토타입 객체가 없으면 상속을 못받는다.

0916

49일 차

19장 프로토타입

원시 타입의 값을 제외한 나머지 값들, 자바스크립트를 이루고 있는 거의 모든 것이 객체다.

객체지향 프로그래밍

독립적 단위인 객체를 집합으로 프로그램을 표현하려는 프로그래밍 패러다임
다양한 속성 중에 필요한 속성만 간추려 내어 표현하는 것을 추상화라고 한다.
객체는 상태 데이터와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조
이때 객체의 상태 데이터를 프로퍼티, 동작을 메서드라 부른다.

상속과 프로토타입

상속은 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.
-> JS는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.

function Circle(radius) {
  this.radius = radius;
  this.getArea = function () {
    return Math.PI * this.radius ** 2;
  };
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); // false
  • radius 프로퍼티 값은 일반적으로 인스턴스마다 다르다.
  • 하지만 getArea 메서드는 모든 인스턴스가 동일한 내용의 메서드를 사용하므로 단 하나만 생성하여 모든 인스턴스가 공유해서 사용하는 것이 바람직하다.
  • 위와 같이 코드를 작성하면 새로운 인스턴스를 생성할 때마다 getArea 메서드를 중복 생성하고 모든 인스턴스가 중복 소유한다.
    -> 메모리 낭비, 성능 저하
function Circle(radius) {
  this.radius = radius;
}

Circle.prototype.getArea = function () {
  return Math.PI * this.radius ** 2;
};

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); // true
  • 자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
  • Circle 생성자 함수가 생성한 모든 인스턴스는 자신의 프로토타입, 즉 상위 객체 역할을 하는 Circle.prototype의 모든 프로퍼티와 메서드를 상속받늗나.
  • 생성자 함수가 생성할 모든 인스턴스가 공통적으로 사용할 프로퍼티나 메서드를 프로토타입에 미리 구현해 두면 인스턴스는 별도의 구현 없이 상위 객체인 프로토타입의 자산을 공유하여 사용할 수 있다.

프로토타입 객체

프로토타입 객체란 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용한다.

  • 프로토타입을 상속받은 하위 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 자유롭게 사용할 수 있다.
  • 모든 객체는 [[prototype]]이라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다.
  • [[prototype]]에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다.
    • 즉, 객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[prototype]]에 저장된다.
  • 모든 객체는 하나의 프로토타입을 갖고, 모든 프로토타입은 생성자 함수와 연결되어 있다.
    • [[prototype]] 내부 슬롯의 값이 null인 객체는 프로토타입이 없다.
  • [[prototype]] 내부 슬롯에 직접 접근할 수는 없지만, __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다.
  • 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고, 생성자 함수는 자신의 prototype 프로퍼티를 통해 프로토타입에 접근할 수 있다.

__proto__ 접근자 프로퍼티

모든 객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.

  1. __proto__는 접근자 프로퍼티다. 내부 슬롯에는 직접 접근할 수 없기에 간접적으로 접근해야 한다. Object.prototype의 접근자 프로퍼티인 __proto__는 접근자 함수를 통해 __proto__ 내부 슬롯의 값, 즉 프로토타입을 취득하거나 할당한다.

  2. __proto__ 접근자 프로퍼티는 상속을 통해 사용된다. __proto__ 접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아니라 Object.prototype의 프로퍼티다. 모든 객체는 상속을 통해 __proto__ 접근자 프로퍼티를 사용할 수 있다.

  3. __proto__ 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다.

  4. __proto__ 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.

  • 직접 상속을 통해 Object.prototype을 상속받지 않는 객체를 생성할 수도 있기 때문에 __proto__ 접근자 프로퍼티를 사용할 수 없는 경우가 있다.
  • 따라서 프로토타입의 참조를 취득하고 싶은 경우에는 Object.getPrototypeOf 메서드를 사용하고, 프로토타입을 교체하고 싶은 경우에는 Object.setPrototypeOf 메서드를 사용한다.
  • 두 메서드는 __proto__의 처리내용과 정확히 일치한다.
const parent = {};
const child = {};
// child의 프로토타입을 parent로 설정
child.__proto__ = parent;
// parent의 프로토타입을 child로 설정
parent.__proto__ = child; // TypeError: Cyclic __proto__ value
  • 위와 같은 코드가 에러 없이 정상적으로 처리되면 서로가 자신의 프로토타입이 되는 비정상적인 프로토타입 체인이 만들어지기 때문에 __proto__ 접근자 프로퍼티는 에러를 발생시킨다.
  • 프로토타입 체인은 단방향 링크드 리스트로 구현되어야 한다.
  • 아무런 체크 없이 무조건적으로 프로토타입을 교체할 수 없도록 __proto__를 통해 프로토타입에 접근하고 교체하도록 구현되어 있다.

함수 객체의 prototype 프로퍼티

  • 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
  • 따라서 생성자 함수로서 호출할 수 없는 non-constructor는 prototype 프로퍼티를 소유하지 않고 프로토타입도 생성하지 않는다.
  • 모든 객체가 가지고 있는 __proto__ 접근자 프로퍼티와 함수 객체만이 가지고 있는 prototype 프로퍼티는 동일한 프로토타입을 가리킨다.

프로토타입의 constructor 프로퍼티와 생성자 함수

  • 모든 프로토타입은 constructor 프로퍼티를 갖는데, 이 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다.
  • 이 연결은 생성자 함수 객체가 생성될 때 이뤄진다.
  • me 객체는 프로토타입의 constructor 프로퍼티를 상속받아 사용할 수 있기에 이를 통해 생성자 함수와 연결된다.

리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입

  • 리터럴 표기법에 의해 생성된 객체도 물론 프로토타입이 존재한다.
  • 하지만 프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수 없다.
const obj = {};

console.log(obj.constructor); // [Function: Object]
  • obj 객체는 Object 생성자 함수로 생성한 객체가 아니라 객체 리터럴에 의해 생성된 객체이다.
  • 하지만 obj 객체는 Object 생성자 함수와 constructor 프로퍼티로 연결되어 있다.
  • Object 생성자 함수 호출과 객체 리터럴의 평가는 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성하는 점에서 동일하나 세부 내용은 다르다.
  • 따라서 객체 리터럴에 의해 생성된 객체는 Object 생성자 함수가 생성한 객체가 아니다.
  • 함수 역시 함구 객체를 생성한 것은 Function 생성자가 아니지만 constructor 프로퍼티를 통해 확인해보면 생성자 함수는 Function 함수다.
  • 리터럴 표기법에 의해 생성된 객체도 상속을 위해 프로토타입이 필요하다. 따라서 가상적인 생성자 함수를 갖는다.
  • 프로토타입은 생성자 함수와 더불어 생성되며 prototype, constructor 프로퍼티에 의해 연결되어 있기 때문이다.
  • 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재한다.
  • 리터럴 표기법에 의해 생성된 객체는 생성자 함수에 의해 생성된 객체는 아니지만, constructor 프로퍼티를 통해 연결되어 있는 생성자 함수를 리터럴 표기법으로 생성한 객체를 생성한 생성자 함수로 생각해도 크게 무리는 없다.

프로토타입의 생성 시점

프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다
-> 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문이다.

사용자 정의 생성자 함수와 프로토타입 생성 시점

  • constructor는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다.
  • 생성자 함수로서 호출할 수 없는 함수, non-constructor는 프로토타입이 생성되지 않는다.
  • 생성된 프로토타입은 오직 constructor 프로퍼티만을 갖는 객체다.
  • 사용자 정의 생성자 함수는 자신이 평가되어 함수 객체로 생성되는 시점에 프로토타입도 더불어 생성되며, 생성된 프로토타입의 프로토타입은 Object.prototype이다.

빌트인 생성자 함수와 프로토타입 생성 시점

  • Object, String, Number, Function, Array, RegExp, Date, Promise 등과 같은 빌트인 생성자 함수도 일반 함수와 마찬가지로 빌트인 생성자 함수가 생성되는 시점에 프로토타입이 생성된다.
  • 모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성된다.
  • 생성된 프로토타입은 빌트인 생성자 함수의 prototype 프로퍼티에 바인딩된다.
  • 전역 객체는 코드가 실행되기 이전 단계에 JS 엔진에 의해 생성되는 특수한 객체다.
  • 표준 빌트인 객체인 Object도 전역 객체의 프로퍼티이며, 전역 객체가 생성되는 시점에 생성된다.
  • 이후 생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성된 객체의 [[Prototype]] 내부 슬롯에 할당된다.
    • 이로써 생성된 객체는 프로토타입을 상속받는다.

객체 생성 방식과 프로토타입의 결정

객체는 다양한 생성 방식이 있다. 다양한 방식으로 생성된 객체는 세부적인 차이는 있지만 추상 연산 OrdinaryObjectCreate에 의해 생성된다는 공통점이 있다.

  • 추상 연산 OrdinaryObjectCreate는 필수적으로 자신이 생성할 객체의 프로토타입을 인수로 전달받는다.
  • 빈 객체를 생성한 후, 객체에 추가할 프로퍼티 목록이 인수로 전달된 경우 프로퍼티를 객체에 추가한다.
  • 그리고 인수로 전달받은 프로토타입을 자신이 생성한 객체의 [[prototype]] 내부 슬롯에 할당한 다음, 생성한 객체를 반환한다.
  • 즉, 프로토타입은 추상 연산에 전달되는 인수에 의해 결정되는데, 이 인수는 객체가 생성되는 시점에 객체 생성 방식에 의해 결정된다.

객체 리터럴에 의해 생성된 객체의 프로토타입

  • 객체 리터럴에 의해 생성된 객체의 프로토타입은 Object.prototype이다.
  • 생성된 객체는 Object.prototype의 프로퍼티와 메서드를 자신의 자산인 것처럼 자유롭게 사용할 수 있다.

Object 생성자 함수에 의해 생성된 객체의 프로토타입

  • 객체 리터럴에 의해 생성된 객체와 마찬가지로 Object.prototype을 프로토타입으로 갖게 된다.
  • 객체 리터럴과 Object 생성자 함수에 의한 객체 생성 방식의 차이는 프로퍼티 추가 방식에 있다.
  • 객체 리터럴 방식은 객체 리터럴 내부에 프로퍼티를 추가하지만 Object 생성자 함수 방식은 일단 빈 객체를 생성한 이후 프로퍼티를 추가해야 한다.

생성자 함수에 의해 생성된 객체의 프로토타입

  • 추상 연산에 의해 생성자 함수와 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체와 생성된 객체 사이에 연결이 만들어진다.
  • 일반 객체와 같이 프로토타입에도 프로퍼티를 추가/삭제할 수 있다.
  • 이렇게 추가/삭제된 프로퍼티는 프로토타입 체인에 즉각 반영된다.

프로토타입 체인

  • JS는 객체의 프로퍼티에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다.
  • 이를 프로토타입 체인이라 한다. 프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 메커니즘이다.
  • me.hasOwnProperty('name')과 같이 메서드를 호출하면 다음과 같은 과정을 거친다.
    1. 먼저 me 객체에서 hasOwnProperty 메서드를 검색한다. 없으므로 프로토타입 체인을 따라 내부 슬롯에 바인딩되어 있는 프로토타입으로 이동하여 다시 메서드를 검색한다.
    2. Person.prototype에도 메서드가 없으므로 Object.prototype으로 이동하여 메서드를 검색한다.
    3. Object.prototype에는 메서드가 존재하므로 JS 엔진이 Object.prototype.hasOwnProperty 메서드를 호출한다. 이때 메서드의 this에는 me 객체가 바인딩된다.
  • 프로토타입 체인 최상위에 위치하는 객체는 언제나 Object.prototype이다. 모든 객체는 Object.prototype을 상속받는다.
  • Object.prototype을 프로토타입 체인의 종점이라 한다. Object.prototype의 [[prototype]] 내부 슬롯의 값은 null이다.
  • Object.prototype에서도 프로퍼티를 검색할 수 없는 경우 에러가 아닌 undefined를 반환한다.

  • 프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘이라고 할 수 있다.
  • 스코프 체인은 식별자 검색을 위한 메커니즘이라고 할 수 있다.

me.hasOwnProperty('name')

  1. 먼저 스코프 체인에서 me 식별자를 검색한다. me 식별자는 전역에서 선언되었으므로 전역 스코프에서 검색된다.
  2. me 객체의 프로토타입 체인에서 hasOwnProperty 메서드를 검색한다.
    -> 스코프 체인과 프로토타입 체인은 서로 연관없이 별도로 동작하는 것이 아니라 서로 협력하여 식별자와 프로퍼티를 검색하는 데 사용된다.

출처

모던 자바스크립트 Deep Dive

0917

50일 차

2교시

프로토타입을 한마디로 이야기하자면 자바스크립트가 상속을 구현하는 매커니즘

function Person(name) {
  this.name = name;
  this.sayHi = function () {};
}
  • 과연 반드시 생성자 함수 안에 메서드를 작성해야 하는가?
  • sayHi 메서드를 밖으로 빼서 함수로 작성해도 된다.
  • 이것을 결정하는 것이 실력
  • 되든 안되든 좋든 안좋든 자기 철학이 들어있어야 한다.

상속의 단점

부모의 프로퍼티를 사용하는 경우, 프로퍼티가 제대로 있다는 전제하에 인스터스의 코드가 동작한다. 즉, 부모와 강하게 연결되어 있다. Tight Coupling
또한 사용하려면 인스턴스가 있어야 한다는 전제가 존재한다.
그리고 메서드가 어떤 객체에 속한 메서드인지 알 수 없다.

3교시

Object.hasOwn()

  • 흩어져 있으면 사용하기가 힘들다. 네임스페이스의 개념으로 정적 메서드들을 모아둬서 사용 가능
  • 모듈에 함수를 작성하고 객체로 export하면 네임스페이스처럼 사용이 가능하다.

함수 객체는 프로토타입이라는 프로퍼티를 갖는다. 모든 객체는 [[prototype]] 내부 슬롯을 갖는다. 객체를 생성할 때 인스턴스의 [[prototype]] 값에 자신을 new한 생성자.prototype 값을 할당해준다.

4교시

__proto__처럼 사용하는 것은 쓰지말라는 컨벤션. get 함수를 만든다면 set 함수도 만들어야 하는 것이 아닌가 고민해봐야 한다.

정적 메서드로도 해결이 가능하고 프로토타입 메서드로도 해결이 가능하다면 정적 메서드로 작성하는 것이 좋다.

5교시

for …in문보다는 Object.keys()나 Object.entries()를 쓰는게 좋다.
-> 상속을 고려하지 않아도 되기 때문에

인스턴스에서 Object 프로토타입 메서드를 사용하려는 경우, 혹시라도 인스턴스의 프로토타입이 null 일수도 있기 때문에 call 함수를 활용해서 호출하여 해결할 수 있다.
새로 나오는 메서드는 정적 메서드로 만들려고 하는 경향이 있다.

배열을 얼마만큼 잘 순회하는가? -> 매우 중요한 코딩 스킬

태그:

카테고리:

업데이트: