자바스크립트는 프로포타입 기반 객체지향 언어이다.
(클래스 기반 객체지향 언어가 아님)
js 객체 생성 방법
- 객체 리터럴
- Object 생성자 함수
- 생성자 함수
- Object.create 메서드
- 클래스(ES6)
객체 리터럴
- 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용하여 값을 생성하는 표기법을 말한다.
- 객체 리터럴은 객체를 생성하기 위한 표기법이다.
- 객체 리터럴은 값으로 평가되는 표현식이다.
- 자바스크립트의 유연함과 강력함을 대표한다.
- 객체 리터럴에 프로퍼티를 포함시켜 객체를 생성함과 동시에 프로퍼티를 만들 수 있고, 객체를 생성한 이후에 프로퍼티를 동적으로 추가할 수 있다.
var person = {
name: 'Lee',
sayHello: function() {
console.log(`Hello! My name is ${this.name}.`);
}
};
console.log(typeof person); //object
프로퍼티
- 객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다.
- 프로퍼티 키: 식별자 네이밍 규칙을 따르지 않는 이름에는 반드시 따옴표를 사용해야 한다. (빈 문자열도 프로퍼티 키로 사용할 수 있음)
- 프로퍼티 값: 자바스크립트에서 사용할 수 있는 모든 값
- 함수 가능
- 접근시 마침표 표기법, 대괄호 표기법이 있다.
참고) 브라우저 환경에서 name이라는 전역변수가 존재한다. (전역 객체 window의 프로퍼티)
- 프로퍼티 삭제 : delete person.age
- 프로퍼티 확장 기능 : 축약표현
원시 값과 객체의 비교
<사실 다른 객체 지향 언어에서 알던 사실 ... 다시 한번 짚고 넘어간다는 느낌으로~ >
자바스크립트에서는 7가지 데이터 타입을 제공한다.
- 숫자, 문자열, 불리언, null, undefined, 심벌, 객체 타입
- 원시 타입과 객체 타입으로 구분할 수 있음
- 원시 값은 변경 불가능한 값, 객체는 변경 가능한 값이다.
- 원시 값을 변수에 할당하면 변수는 실제 값이 저장되지만, 객체는 변수를 할당하면 참조 값이 저장된다.
- 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달한다. (값에 의한 전달)
- 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달된다. (참조에 의한 전달)
- 변경 불가능하다는 것은 변수가 아니라 값에 대한 진술이다.
- 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것은 아니다.
- 변수는 언제든지 재할당을 통해 변수를 변경(교체)할 수 있다.
- 상수와 변경 불가능한 값을 동일시하면 안된다. 상수는 재할당이 금지된 변수일 뿐이다.
const obj = {};
o.a = 1; //const키워드로 선언한 변수에 할당한 객체는 변경할 수 있다. (변수는 안 됨.)
console.log(obj); // {a:1}
문자열과 불변성
- ECMAScript 사양에서 문자열 타입(2바이트)와 숫자 타입(8바이트) 이외의 원시 타입은 크기를 명확하게 규정하고 있지 않음.
- C는 하나의 문자를 위한 char 타입이 있을 뿐 문자열 타입은 존재하지 않음.
- JS는 개발자의 편의를 위해 원시 타입인 문자열 타입을 제공함. (자바스크립트의 장점 중 하나)
- JS의 문자열은 원시 타입이며, 변경 불가능하다.
- 문자열은 유사 배열 객체이다. (배열과 유사하게 각 문자에 접근할 수 있어서)
var str = 'string';
console.log(str.length);
str[0] = 'S';
console.log(str); // string
//문자열은 원시 값이므로 변경할 수 없다. (에러는 발생하지 않는다.)
- 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있다.
- 변수에 원시 값을 갖는 변수를 할당하면 변수 할당 시점이든, 두 변수 중 어느 하나의 변수에 값을 재할당하는 시점이든 결국은
두 변수의 원시 값은 서로 다른 메모리 공간에 저장되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다는 것임.
객체
- 객체는 원시 값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해둘 수 없다.
- 메모리를 효율적으로 사용하기 위해, 객체를 복사해 생성하는 비용을 절약하여 성능을 향상시키기 위해 객체는 변경가능한 값으로 설계됨
- JS 객체는 프로퍼티 키를 인덱스로 사용하는 해시 테이블이라고 생각할 수 있다.
- 클래스 기반 객체지향 언어는 사전에 정의된 클래스를 기반으로 객체(인스턴스)를 생성한다. 객체를 생성하기 이전에 이미 프로퍼티와 메서드가 정해져있다.
- 하지만 자바스크립트는 객체가 생성된 이후더라도 동적으로 프로퍼티와 메서드를 추가할 수 있다.
- 사용하기 편리하지만 비용이 더 많이 드는 비효율적인 방법이다. (V8 js 엔진에서 성능을 보장하는 방법이 있음)
- 객체는 변경 가능한 값이므로 메모리에 저장된 객체를 직접 수정할 수 있는데, 객체를 할당한 변수에 재할당하지 않았기 때문에 객체를 할당한 변수의 참조 값은 변경되지 않는다.
- 원시 값과 다르게 여러 개의 식별자가 하나의 객체를 공유할 수 있다.
얕은 복사와 깊은 복사
- 얕은 복사, 깊은 복사로 생성된 객체는 원본과는 다른 객체다.
- 하지만,
- 얕은 복사는 객체에 중첩되어 있는 객체의 경우 참조 값을 복사하고,
- 깊은 복사는 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전한 복사본을 만든다는 차이가 있다.
//얕은 복사 예시 const o = { x: { y:1} }; const c1 = { ... o} console.log(c1 === o); //false console.log(c1.x === o.x); //true
- 값에 의한 전달, 참조에 의한 전달 모두 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다.
- 식별자가 기억하는 메모리 공간, 즉 변수에 저장되어 있는 값이 원시 값이냐 참조 값이냐의 차이가 있을 뿐.
- JS에서 참조에 의한 전달은 존재하지 않고,, 값에 의한 전달만 존재한다고 말할 수도 있음.
- 공유에 의한 전달이라고 표현하기도 함. (공식적인 용어x)
- C언어의 '참조에 의한 전달'과 의미가 명확히 일치하지 않는다는 점 알고가기..
함수
- 함수가 객체라는 사실은 다른 프로그래밍 언어와 구별되는 자바스크립트의 중요한 특징이다.
- 정의 방식 4가지 : 함수 선언문, 함수 표현식, function 생성자 함수, 화살표함수(ES6)
참조에 의한 전달과 외부 상태의 변경 :
객체가 변경할 수 있는 값이며, 참조에 의한 방식으로 동작하면서 발생하는 부작용이 있는데,
이러한 문제의 해결 방법 중 하나는 객체를 불변 객체로 만들어 사용하는 것이다. (함수형 프로그래밍 방식)
객체의 복사본을 새롭게 생성하는 비용은 들지만, 객체를 마치 원시 값처럼 변경 불가능한 값으로 동작하게 만드는 것이다.
* 함수형 프로그래밍 : 외부 상태를 변경하지 않고 외부 상태에 의존하지도 않는 함수를 순수 함수라고 하는데,
순수 함수를 통해 부수 효과를 최대한 억제하여 오류를 피하고 프로그래밍의 안정성을 높이려는 프로그래밍 패러다임
- 다양한 함수의 형태: 즉시실행함수, 재귀함수, 중첩함수, 콜백함수, 순수함수와비순수함수
- 중첩함수(내부함수)
- 중첩함수는 외부 함수 내부에서만 호출할 수 있다.
- 자신을 포함하는 외부 함수를 돕는 헬퍼 함수의 역할을 함.
- 스코프와 클로저에 깊은 관련이 있음.
- 콜백함수
- 자바스크립트의 함수는 일급 객체이므로 함수의 매개변수를 통해 함수를 전달할 수 있다.
- 콜백함수: 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
- 고차함수: 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수
- 함수형 패러다임 뿐만 아니라 비동기 처리(이벤트 처리, Ajax 통신, 타이머 함수 등)에 활용되는 중요한 패턴
//콜백 함수를 사용한 이벤트 처리
document.getElementById('myButton').addEventListener('click', function() {
console.log('button clicked!');
});
//콜백 함수를 통한 비동기 처리
setTimeout(function() {console.log('1초 경과');}, 1000);
//콜백 함수를 사용하는 고차 함수 map
var res = [1, 2, 3].map(function(item) {
return item * 2;
});
console.log(res); // [2, 4, 6]
//콜백 함수를 사용하는 고차 함수 filter
res = [1, 2, 3].filter(function(item) { return item % 2; });
//콜백 함수를 사용하는 고차 함수 reduce
res = [1, 2, 3].reduce(function(acc, cur) { return acc + cur; }, 0);
console.log(res); //6
'Javascript' 카테고리의 다른 글
| [js] 함수와 일급 객체 (2) | 2025.01.21 |
|---|---|
| [js] 생성자 함수에 의한 객체 생성 (5) | 2025.01.21 |
| [js] Property Attribute (4) | 2025.01.20 |
| [js] var, let, const (4) | 2025.01.16 |
| [js] 스코프 (3) | 2025.01.14 |