- Published on
자바스크립트 다시 공부하기
- Authors

- Name
- dexical30
2026.03.01.
자바스크립트의 객체구성
객체는 프로퍼티와 메서드로 구성된 집합체이다
- 프로퍼티: 객츼에 상태를 나타내는값
- 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작
리터럴(Literal) 이란
리터럴은 값을 직접 코드에 적는것을 의미합니다
10, "hello", { x, 1}, 그리고 function() {} 모두 리터럴이라 표현합니다.
객체 리터럴(Object Literal)에 의한 객체생성
객체 리터럴: 중괄호를 사용해서 객체를 직접 생성하는 문법
const user = {
name: "dexical",
age: 30,
isAdmin: false
};
- → 객체 리터럴 문법
- key: value 형태
- 실행 즉시 객체 생성
원시값(primitive value)
객체가 아닌 값이며, 변경 불가능(immutable)한 값
- string
- number
- bigint
- boolean
- undefined
- null
- symbol
문자열의 불변성
문자열은 0개이상의 문자로 이뤄진 집합을 말하며, 1개 문자는 2바이트의 메모리 공간을 가진다. 문자열은 원시값이기 때문에 불변한다
var str = "string"
str[0] = "a"
console.log(str) // string
symbol은 무엇인가요
고유하고 변경 불가능한 원시값(primitive) 타입
ES6(ES2015)에서 추가된 타입이고, 주로 객체의 고유한 프로퍼티 키를 만들기 위해 사용된다
const a = Symbol("id");
const b = Symbol("id");
console.log(a === b); // false
Symbol을 공유하고싶다면 symbol.for 로 전역 레지스트리(global registry)를 사용한다
const a = Symbol.for("id");
const b = Symbol.for("id");
console.log(a === b); // true
자바스크립트의 변수 재할당
var a = 10
var b = 10
위처럼 값은 primitive 값을 저장할때, 메모리에서는 a,b는 같은 메모리주소를 보도록 설계되어있다고 한다. ECMAScript 사양에 변수를 어떻게 관리할지 명확하게 정의되어있지 않기 떄문에 차이가 있을수있다.
ECMAScript
ECMAScript는 JavaScript의 공식 표준(사양, Specification)입니다.
자바스크립트 객체의 프로퍼티를 어떻게 접근하고 최적화했는지
히든 클래스(Hidden Class)는 V8 엔진이 객체의 프로퍼티 구조(키와 순서)를 내부적으로 저장해 두는 “설계도” 같은 개념입니다. 같은 구조로 생성된 객체들은 동일한 히든 클래스를 공유하며, 이를 통해 프로퍼티를 메모리 오프셋 기반으로 빠르게 접근할 수 있습니다. 하지만 프로퍼티 추가 순서가 달라지거나 delete로 구조가 변경되면 새로운 히든 클래스가 생성되어 최적화가 깨질 수 있습니다.
자바스크립트 객체를 수정할 수 있는 이유
객체는 생성과 관리에 많은 비용이 드는 복합 데이터 구조이다. 만약 객체를 변경할 때마다 원시값처럼 기존 객체를 복사하여 새로운 객체를 생성한다면, 불변성은 보장할 수 있지만 객체 크기가 클 경우 메모리 사용량이 크게 증가하고 성능 저하가 발생할 수 있다.
따라서 자바스크립트는 메모리를 효율적으로 사용하고 성능을 확보하기 위해 객체를 변경 가능한(mutable) 값으로 설계하였다. 이로 인해 변수는 객체 자체를 복사하는 것이 아니라, 객체를 가리키는 참조값을 저장하게 된다.
객체를 참조하는 변수를 다른 변수에 할당하면 같은 힙을 참조하게 된다.
함수 리터럴
함수 리터럴은 이름 없이(또는 필요하면 이름을 붙여) 코드 안에서 바로 정의하는 함수 표현식입니다.
ex) function() {}, () => {}
자바스크립트는 함수리터럴을 변수에 저장할수도, 다른함수에 전달도 가능합니다. 객체처럼 다룰수 있습니다.
자바스크립트의 함수는 일급객체
function foo() {}
console.log(typeof foo); // "function"
console.log(foo instanceof Object); // true
그렇기떄문에 property, method를 가질수 있습니다
“일급(First-class)”의 정확한 의미
어떤 값이 다른 값과 동등하게 취급될 수 있는가를 의미합니다. 즉, 특별 취급을 받지 않고 다른 값들처럼 자유롭게 사용할 수 있으면 그걸 일급(First-class) 이라고 합니다.
일급객체
일급객체는 일급이면서 객체의 특징을 가진것을 의미합니다 메서드와 프로퍼티가 있는것이 특징입니다.
ECMAScript에서 정의하는 Object
ECMAScript는 클래스 정의를 위한 문법을 포함하고 있지만, ECMAScript 객체는 C++, Smalltalk, Java와 같은 언어의 객체처럼 근본적으로 클래스 기반이 아니다.
대신 객체는 다양한 방법으로 생성될 수 있는데, 리터럴 표기법을 사용하거나 생성자를 통해 만들 수 있다. 생성자는 객체를 생성한 다음, 그 객체의 프로퍼티에 초기 값을 할당하여 객체의 전체 또는 일부를 초기화하는 코드를 실행하는 함수이다.
각 생성자는 "prototype"이라는 이름의 프로퍼티를 가지며, 이 프로퍼티는 프로토타입 기반 상속과 공유 프로퍼티를 구현하는 데 사용된다.
객체는 new 표현식을 사용하여 생성자를 통해 만들어진다. 예를 들어, new Date(2009, 11)은 새로운 Date 객체를 생성한다.
생성자를 new 없이 호출하면 그 결과는 생성자에 따라 달라진다. 예를 들어, Date()는 객체를 생성하는 대신 현재 날짜와 시간을 나타내는 문자열을 반환한다.
생성자에 의해 만들어진 모든 객체는 그 생성자의 "prototype" 프로퍼티 값을 가리키는 암묵적인 참조(이를 객체의 prototype이라 한다)를 가진다.
또한 그 prototype은 다시 자신의 prototype에 대한 암묵적인 참조를 가질 수 있고, 이러한 연결을 prototype chain(프로토타입 체인) 이라고 한다.
객체에서 어떤 프로퍼티를 참조할 때, 그 참조는 프로토타입 체인에서 해당 이름을 가진 프로퍼티를 처음으로 포함하는 객체의 프로퍼티를 가리킨다.
즉,
- 먼저 해당 객체 자체를 검사하고
- 그 객체에 해당 프로퍼티가 있으면 그것을 사용하며
- 없다면 그 객체의 prototype을 검사하고
- 이런 식으로 체인을 따라 계속 탐색한다.
클래스 기반 객체 지향 언어에서는 일반적으로 상태(state)는 인스턴스에 저장되고 메서드는 클래스에 저장되며 상속은 구조와 동작에 대해서만 이루어진다.
반면 ECMAScript에서는 상태와 메서드 모두 객체에 저장되며 구조, 동작, 상태 모두 상속된다.
비록 ECMAScript 객체가 본질적으로 클래스 기반은 아니지만, 생성자 함수, 프로토타입 객체, 메서드의 공통 패턴을 기반으로 클래스와 유사한 추상화를 정의하는 것이 종종 편리하다.
ECMAScript의 내장 객체들도 이러한 클래스 유사 패턴을 따른다.
ECMAScript 2015부터는 프로그래머가 이러한 클래스 유사 패턴에 맞는 객체를 더 간결하게 정의할 수 있도록 class 문법이 추가되었다.
함수 호이스팅
함수 선언문으로 정의한 함수는 런타임 이전에 함수객체가 먼저 생성이 된다 함수 표현식으로 정의한 함수는 런타임중에 생성이된다.
그래서 선언문으로 정의한 함수는 코드블럭상 위에서 호출해도 동작하고, 함수 표현식으로 정의한 함수를 호출하면 TypeError 가 발생한다.
함수 선언문이 코드의 선두로 끌어 올려진것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅이라고 한다.
함수를 호출하기전, 함수를 선언해야한다 라는 규칙을 무시하기 떄문에 함수를 정의할때는 함수표현식으로 선언하는것을 권장한다.
함수 생성자
todo..
고차함수 (high order function)
매개변수를 통해 함수의 외부에서 콜백함수를 전달받음 함수를 의미한다
// hof함수를 High Order Function 으로 부른다
cosnt hof = (callback: Function) => {
// ...
}
함수형 프로그래밍
순수함수와 보조함수의 조합을 통해 외부 상태를 변경하는 부수효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임이다
스코프
모든 식별자(변수이름, 함수이름, 클래스 이름 ..)는 자신이 선언된 위치에서 다른 코드가 식별자 자신을 참조할 수 있는 유효범위가 결정된다
자바스크립트 엔진은 스코프를 통해 어떤 변수를 참조할것인지를 결정한다
렉시컬스코프 lexical scope
정의가 평가되는 시점에 상위 스코프가 정적으로 결정되기 때문에 정적스코프라고 부른다. 함수를 어디서 정의했는지에 따라 상위스코프를 결정한다
2026.03.02.
내부 슬롯과 내부 메서드
ECMAScript에서 사용하는 의사 프로퍼티(pseudo property)와 의사 메서드(pseudo method)이다. ECMAScrpt사양에 등장하는 이중 대괄호 ([[]])로 감싼 이름들이 내부 슬롯과 내부 메서드이다
내부슬롯은 간접적으로 접근할수 없지만, [[Prototype]] 은 __proto__ 로 간접적으로 접근할수 있다.
프로퍼티 어트리뷰트
자바스크립트는 프로퍼티를 생성할때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 정의한다
const person = {
name: 'John',
}
console.log(Object.getOwnPropertyDescriptor(person,'name'));
// --- 결과: 프로퍼티 디스크립터 객체 ---
{
name: {
value: 'John',
writable: true,
enumerable: true,
configurable: true
}
}
데이터 프로퍼티와 접근자 프로퍼티
- 데이터 프로퍼티: 키와 값으로 이루어지는 일반적인 프로퍼티
- 접근자 프로퍼티: 자체적으로 값을 갖지않고 다른 데이터 프로퍼티의 값을 읽거나 호출되는 접근자 함수(accesor function)로 구성된 프로퍼티
데이터 프로퍼티
| 이름 | 설명 |
|---|---|
[[Value]] | 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는값 |
[[Writeable]] | 읽기/쓰지 전용 프로퍼티인지 알수있음 (true/false) |
[[Enumerable]] | 열거 기능 여부를 나타내며, 불리언값을 가짐. for in 이나 Object.keys 메서드 등으로 열거가능하다 |
[[Configurable]] | 프로퍼티 재정의 가능여부를 나타내며 불리언값을 찾는다. |
접근자 프로퍼티
| 이름 | 설명 |
|---|---|
[[Get]] | 접근자 프로퍼티를 통해 프로퍼티의 값을 읽을떄 호출하는 접근자 함수다. |
[[Set]] | 접근자 프로퍼티를 통해 값을 저장할때 호출하는 접근자 함수다. |
[[Enumerable]] | 열거 기능 여부를 나타내며, 불리언값을 가짐. for in 이나 Object.keys 메서드 등으로 열거가능하다 |
[[Configurable]] | 프로퍼티 재정의 가능여부를 나타내며 불리언값을 찾는다. |
접근자 프로퍼티를 이용해 저장하고싶을때는 setter와 getter를 정의한다
const person = {
name: 'John',
}
console.log(Object.getOwnPropertyDescriptors(person,'name'));
const person1 = {
name: 'John',
set name(value) {
this.name = value;
},
get name() {
return this.name;
}
}
console.log(Object.getOwnPropertyDescriptors(person1,'name'));
// --- 결과 ---
{
name: {
value: 'John',
writable: true,
enumerable: true,
configurable: true
}
}
{
name: {
get: [Function: get name],
set: [Function: set name],
enumerable: true,
configurable: true
}
}
프로토타입
어떤 객체의 상위 객체의 역할을 하는 객체이다 프로토타입은 하위 객체에게 자신의 프로퍼티와 메서드를 상속한다. 프로토타입 객체는 프로퍼티나 메서드를 상속받은 하위 객체는 자신의 프로퍼티 또는 메서드인것처럼 자유룝게 사용할수있다.
프로토타입 체인은 단방향 링크드리스트로 연결되어있는 상속구조를 말한다. 객체의 프로퍼티나 메서드에 접근하려고 할때 해당 객체에 접근하려는 프로퍼티 또는 메서드가 없다면 프로토타입 체인을 따라 프로토타입의 프로퍼티나 메서드를 차례대로 검색한다.
객체 변경을 방지하는방법
- 객체확장금지 Object.preventExtensions
- 객체 밀봉 Object.seal
- 객체 동결 Object.freeze
생성자 함수의 인스턴스 생성과정
new 키워드를 이용해 function 함수의 객체를 생성할수 있다
function Circle(radius) {
this.radius = 10
this.getDiameter = function() {
return this.radius * 2
}
}
const c = new Circle(5)
내부메서드 [[Call] 그리고 [[Construct]]
함수선언문과 함수 표현식으로 정의한 함수는 일반적인 함수로ㅎ서 호출할수 있는것은 물론 생성자로서도 호출할수있다. 함수는 객체이므로 일반객체와 동일하게 동작할수있다. 함수 객체는 일반 객체가 가지고있는 내부슬롯과 내부 메서드를 모두 가지고 있기 때문이다.
함수는 객체이지민 일반 객체와는 다르다. 일반객체는 호출할 수 없지만 함수는 호출할 수 있다.
함수로서 동작하기 위해 함수객체만을 위한 [[Environmnent]], [[FormalParameter]]등 의내부 슬롯을 가지고 있다
function foo () {}
foo() // [[Call]] 호출
new foo() // [[Constuctor]] 호출
내부메서드 Call을 갖는 함수객체는 Callable 이라한다 [[Constructor]] 여부에 따라 생성자 함수로서 호출할수 있는 함수, 혹은 호출할수 없는 Non-constructor 로 불린다.
ES6의 화살표함수가 [[Constructor]]가 없기 때문에 Callable만 가능하다
new.target
ES6에 생긴 문법으로 생성자 함수가 new 연산자없이 호출되었는지 확인할수있다 new 연산자로 호출한경우 new.target은 true, 안한경우 false로 구분할수있다 그래서 아래처럼 생성자패턴으로 실수하더라도 객체를 생성할수있다
function Circle(radius) {
if (!new.target) {
return new Circle(5)
}
}
const c = Circle(5) // new.target은 false이지만, callable하게 호출되고 new연산자로 객체를 반환하다
IE에서는 지원하지 않아서 this instanceof Circle 로도 체크할수있다
왜 직접 내부슬롯은 못보는걸까?
- 스펙 추상 개념이기 때문
- 엔진마다 구현이 다르기 때문
- 보안상 노출 위험
- GC 최적화 문제
2026.03.03.
함수와 일급객체
Todo