10~12장을 읽으며 얻은 인사이트를 추가로 공부하면서 정리해 보자.
- 10장: 객체 리터럴
- 11장: 원시값과 객체의 비교
- 12장: 함수
1. 메서드
프로퍼티 값이 함수일 경우 일반 함수와 구분하기 위해 메서드라 부른다.
즉, 메서드는 객체에 묶여있는 함수를 의미한다.
var circle = {
radius : 5, // 프로퍼티
getDiameter : function () { // 메서드
return 2 * this.radius;
}
}
2. 원시 타입과 객체 타입의 차이
2-1. 원시 값은 변경 불가능한 값이지만, 객체(참조) 타입의 값은 객체는 변경가능한 값이다.
원시값은 변경 불가능한 값, 즉 읽기 전용값이다.
let foo = 12
foo = 14
console.log(foo) // 14
변수는 언제든지 재할당을 통해 변수값을 교체할 수 있다.
원시값이 변경 불가능 하다는 말은 원시값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것이 아니다.
원시값을 할당한 변수에 새로운 원시 값을 재할당하게 된다면?
메모리 공간에 저장되어 있는 원시값(12)을 변경하는 것이 아니라
새로운 메모리 공간을 확보하고 재할당한 원시값(14)을 저장한 후, 변수는 새롭게 재할당한 원시값을 가리킨다.
따라서, 변수가 달라진 이유는 원시값이 바뀐 것이 아닌 새로운 원시값이 생성된 후, 생성된 원시값을 가리키는 주소가 업데이트되기 때문이라고 볼 수 있다.
원시값은 변경 불가능한 값이기 때문에 값을 직접 변경할 수 없는 불변성을 가지고 있는데, 이러한 특성으로 데이터의 신뢰성을 보장할 수 있다.
2-2. 원시값을 변수에 할당하면 변수에는 실제 값이 저장되지만, 객체를 변수에 할당하면 변수에는 참조 값이 저장된다.
객체는 프로퍼티의 개수가 정해져 있지 않고, 동적으로 추가되고 삭제할 수 있으며, 프로퍼티의 값에 제약도 없다.
따라서 객체는 원시값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해둘 수 없다.
이런 복합적인 자료구조를 가지고 있어, 객체를 관리하는 방식은 원시값과 비교해 복잡하고 구현방식도 브라우저마다 다를 수 있다.
(크롬 V8 자바스크립트 엔진에는 프로퍼티에 접근하기 위해 동적 탐색 대신 히든 클래스라는 방식을 사용해 C++객체의 프로퍼티의 접근하는 정도의 성능을 보장해 준다)
https://engineering.linecorp.com/ko/blog/v8-hidden-class
[V8의 히든 클래스 이야기
자바스크립트가 되어 그 기분을 헤아릴 수 있다면 안녕하세요? LINE Fukuoka의 프론트엔드 엔지니어 Yonehara입니다. 저는 프론트엔드 개발자로서 아직 웹 브라우저나 자바스크립트의 기분을 헤아려
engineering.linecorp.com](https://engineering.linecorp.com/ko/blog/v8-hidden-class)
위와 같은 이유(객체를 생성하고 관리하는 데는 매우 복잡하고 비용이 많이 듦)로 따라서 객체는 원시값과는 다른 방식으로 동작하도록 설계되었다.
객체를 변경할 때마다 원시값처럼 이전 값을 복사해서 새롭게 업데이트 부분만 교체해 준다면 명확하고 신뢰성이 확보되겠지만, 객체는 원시값처럼 크기가 일정하지도 않고 복사 생성에 비용이 많이 들어 메모리의 효율적 소비가 어렵고 성능이 나빠진다.
따라서 메모리를 효율성과 성능을 위해 객체는 변경 가능한 값으로 설계되어 있다. 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다.
let person = {
name : 'lee'
}
person.name = 'kim'
console.log(person) // {name : 'kim'}
2-3. 값에 의한 전달과 참조에 의한 전달
원시값을 갖는 변수를 다른 변수에 할당하면 원본의 원시값이 복사되어 전달되고, 이를 값에 의한 전달이라고 부른다.
반면, 객체를 가리키는 변수를 다른 변수에 할당하면, 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달이라고 부른다.
(1) 값에 의한 전달
먼저, 값에 의한 전달에 대해 좀 더 살펴보자.
let score = 50
let copy = score
console.log(score) // 50
console.log(copy) // 50
score = 100
console.log(score) // 100
console.log(copy) // 50
console.log(score === copy) // false
변수 copy에는 score의 원시값이 복사되어 전달된다.
하지면 score변수와 copy변수는 다른 메모리 공간에 주소 된 별개의 값이다.
따라서 처음 score 값을 복사한 이후, score는 copy에게 어떠한 영향력을 주지 않는다.
정확하게 말하자면, 서로 다른 메모리 공간에 저장된 별개의 값이 되어버려, 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다.
(2) 참조에 의한 전달
const person = {
neme : 'Lee'
}
// 참조 값을 복사(얕은 복사)
const copy = person;
객체를 가리키는 변수에 다른 변수를 할당하면 원본의 참조값이 복사되어 전달되는데, 이를 참조에 의한 전달이라 한다.
원본의 person과 사본 copy는 저장된 메모리 주소는 다르지만 동일한 참조값을 바라본다.
즉, 두 개의 식별자가 하나의 객체를 공유한다고 할 수 있다.
따라서, 원본 또는 사본 중 어느 한쪽에서 객체를 변경하면 서로 영향을 받을 수 있게 된다.
3. 함수는 정의 (변수는 선언)
정의란, 변수에 값을 할당하여 변수의 실체를 명확히 하는 것을 의미한다.
단순히 컴파일러에게 식별자의 존재만 알리는 것은 선언,
실제로 컴파일러가 변수를 생성해서 식별자와 메모리 주소가 연결되면 정의라고 구분 짓는다.
3. 이상적인 매개변수의 개수
이상적인 매개변수의 개수는 0이나, 최대 3개를 넘지 않을 것을 권장한다.
매개변수의 개수가 많다는 것은 함수가 여러 가지 일을 한다는 증거이므로 바람직하지 않다.
이상적인 함수는 한 가지 일만 해야 하며 가급적 작게 만들어야 한다.
3개 이상이 필요한 경우, 객체 전달이 유리할 수 있다.
객체를 인수로 사용하는 경우, 프로퍼티키만 명확히 지정하면 매개변수의 순서를 상관 쓰지 않아도 되며, 명시적으로 인수의 의미를 설명하는 프로퍼티 키를 사용하게 되어 코드의 가독성도 좋아지고 실수도 줄어드는 효과가 있다.
하지만 함수 외부에서 내부로 전달한 객체를 함수 내부에서 변경할 경우 외부 객체가 변경되는 side effect가 일어날 수 있으므로 주의하자.
'Read > Morden Javascript Deep Dive' 카테고리의 다른 글
[Modern Javascript Deep Dive] 16~18장 인사이트 정리 (0) | 2024.01.16 |
---|---|
[Modern Javascript Deep Dive] 13~15장 인사이트 정리 (0) | 2024.01.11 |
[Modern Javascript Deep Dive] 8~9장 인사이트 정리 (1) | 2023.11.11 |
[Modern Javascript Deep Dive] 8장 제어문 (0) | 2023.02.09 |
[Modern Javascript Deep Dive] 7장 연산자 (0) | 2023.02.08 |