[모던 자바스크립트] 객체의 모든 것

재오·2023년 7월 13일
1

JavaScript

목록 보기
35/48
post-thumbnail

객체 리터럴

원시 값은 변경 불가능한 값이지만 객체는 변경이 가능한 값이다. 함수도 프로퍼티의 값으로 사용할 수 있는데 일반 함수와 구분하기 위해서 이를 메서드라 부른다.

키 값으로 식별자 네이밍 규칙을 따르지 않는 프로퍼티 키는 모두 따옴표를 생략해서는 안된다. 여기서 식별자 네이밍 규칙은 카멜케이스, 파스칼케이스 등을 의미한다.
네이밍 규칙을 따르는 프로퍼티 키라면 대괄호 표기법이나 마침표 표기법을 이용하여 프로퍼티에 접근이 가능하다. 대괄호 표기법을 사용하는 경우 대괄호 프로퍼티 접근 연산자 내부에 지정하는 프로퍼티 키는 반드시 따옴표로 감싼 문자열이어야 한다.

ES6에서 추가된 객체 리터럴의 확장 기능

프로퍼티 축약 표현

let x = 1, y = 2;

const obj = { x, y };
console.log(obj); // {x: 1, Y: 2}

계산된 프로퍼티 이름

const prefix = 'prop';
let i =0;

const obj = {
  [`${prop}-${++i}`]: i,
  [`${prop}-${++i}`]: i,
  [`${prop}-${++i}`]: i,
};

console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3}

단 프로퍼티 키로 사용할 표현식을 대괄호로 묶어야 한다.

메서드 축약 표현

const obj = {
  name: 'Lee',
  sayHi(){ // sayHi: function() {}
    console.log('Hi: ' + this.name);
  }
};

원시 값과 객체의 비교

값에 의한 전달참조에 의한 전달이 존재한다. 값에 의한 전달은 보통 원시 값을 갖는 변수를 할당하는데 이는 복사를 하더라도 값이 같은 것이지 다른 메모리 공간에 저장된 별개의 값이라는 점을 명심해야 한다.

얕은복사와 깊은복사
객체를 프로퍼티 값으로 갖는 객체의 경우 얕은 복사는 한단계까지만 복사하는 것을 말하고 깊은 복사는 객체에 중첩되어 있는 객체까지 모두 복사하는 것을 의미한다.

참조에 의한 전달은 원본 person의 위치와 이 복사본인 copy에 저장된 메모리 위치는 다르다. 하지만 이 둘은 동일한 참조 값을 갖는다. 다시말해 원본과 사본 모두 동일한 객체를 가리킨다. 이것은 두 개의 식별자가 하나의 객체를 공유하기 때문에 객체 값을 변경하거나 수정하면 서로 영향을 받는다.

생성자 함수에 의한 객체 생성

생성자 함수란 new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수를 말한다. 여기서 인스턴스는 생성자 함수에 의해 생성된 객체를 의미한다.

객체 리터럴에 의한 객체 생성 방식의 문제점
객체 리터럴에 의한 객체 생성 방식은 직관적이고 간편하나, 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 매번 같은 프로퍼티를 기술해야 하기 때문에 비효율적이다.

생성자 함수의 인스턴스 생성 과정
우선 암묵적으로 빈 객체가 생성된다. 이 빈 객체가 바로 생성자 함수가 생성한 인스턴스다. 그리고 이 인스턴스는 this에 바인딩 된다. 생성자 함수 내부의 this가 생성자 함수가 생성할 인스턴스를 가리키는 이유가 바로 이것이다. 그리고 이 this에 바인딩되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고 생성자 함수가 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다. 만약 this가 아닌 다른 객체를 명시적으로 반환하면 this가 반환되지 못하고 return문제 명시한 객체가 반환된다. 원시 값을 반환하면 원시 값 반환은 무시되고 암묵적으로 this가 반환된다.

내부 메서드 [[Call]]과 [[Construct]]
함수가 일반 함수로서 호출되면 함수 객체의 내부 메서드 [[Call]]이 호출되고 new 연산자와 함께 생성자 함수로서 호출되면 내부 메서드 [[Construct]]가 호출된다. 일반 함수(함수 선언문, 함수 표현식)로 정의된 함수만이 constructor이고 화살표 함수로 호출하면 non-constructor이다. 즉 new 연산자와 함께 호출하는 함수는 constructor여야만 한다.

function Circle(radius){
  // 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
  console.log(this); // Circle {}
  
  // this에 바인딩되어 있는 인스턴스를 초기화한다.
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
  
  // 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}

함수와 일급 객체

arguments 프로퍼티
arguments 프로퍼티는 유사배열 객체이며, 함수 내부에서 전역변수처럼 사용된다. arguments 객체의 length 프로퍼티는 인자의 개수를 가리킨다.

function sum(){
  let res = 0;
  
  for(let i=0; i<arguments.length; i++){
    res += arguments[i];
  }
  
  return res;
}

length 프로퍼티
선언한 매개변수의 개수를 가리킨다.

function bar(x, y){
  return x * y;
}

console.log(bar.length); // 2

name 프로퍼티
함수의 이름을 나타내는데 익명함수 같은 경우에는 함수 객체를 가리키는 식별자를 값으로 갖는다.

let namedFunc = function foo() {};
console.log(namedFunc.name); // foo

let anonymousFunc = function() {};
console.log(anonymous.name); // anonymous

prototype 프로퍼티
prototype 프로퍼티는 생성자 함수로 호출할 수 있는 함수 객체만이 소유하는 프로퍼티이다.

(function () {}).hasOwnProperty('prototype'); // true

빌트인 객체

표준 빌트인 객체

자바스크립트는 Object, String, Number, Boolean, Symbol, Date, Math, RegExp, Array, Map/Set 등의 표준 빌트인 객체를 제공한다. 생성자 함수 객체인 표준 빌트인 객체는 프로토타입 메서드정적 메서드를 제공하고 생성자 함수 객체가 아닌 표준 빌트인 객체는 정적 메서드만 제공한다.

const numObj = new Number(1.5); // Number 생성자 함수에 의한 Number 객체 생성

// toFixed는 Number.prototype의 프로토타입 메서드이다.
console.log(numObj.toFixed()); // 2

// isInteger는 Number의 정적 메서드다.
console.log(Number.isInteger(0.5)); // false

원시값과 래퍼 객체

원시값은 객체가 아니므로 프로퍼티나 메서드를 가질 수 없다. 하지만 원시값이 마치 객체처럼 동작한다.

const str = "hello";

console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO

이는 원시값에 대해 마치 객체처럼 마침표 표기법으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해주기 때문이다. 즉 자바스크립트 엔진은 암묵적으로 연관된 객체를 생성하여 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 다시 원시값으로 돌린다.

이처럼 문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를 래퍼 객체라고 한다.

// 식별자 str은 문자열을 값으로 가지고 있다.
const str = "hello";

// 식별자 str은 암묵적으로 생성된 래퍼 객체를 가리킨다.
// 래퍼 객체에 name 프로퍼티가 동적 추가된다.
str.name = "LEE";

// 식별자 str은 다시 원시값을 가진다.

// 식별자 str은 새롭게 암묵적으로 생성된 다른 래퍼 객체를 가리킨다.
// 새롭게 생성된 래퍼 객체에는 name 프로퍼티가 존재하지 않는다.
console.log(str.name); // undefined

전역 객체

전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다 먼저 생성되는 특수한 객체이며, 어떤 객체에도 속하지 않는 최상위 객체이다. 브라우저 환경에서는 window, Node.js 환경에서는 global이 전역 객체를 가리킨다.

// var 키워드로 선언한 전역 변수
var foo = 1;
console.log(window.foo); // 1

전역 객체의 프로퍼티를 참조할 때 window나 global을 생략할 수 있다. 하지만 let, const는 전역 객체 프로퍼티가 아니기 때문에 window.foo와 같이 접근할 수 없다.

parseFloat

  • 문자열을 적어도 숫자로 반환되어 계산된다.
  • 공백으로 구분된 문자열은 첫번째 문자열만 숫자로 변환되어 반환된다.
  • 첫번째 문자열이 숫자로 변환될 수 없다면 NaN을 반환한다.
  • 앞뒤 공백은 무시된다.

parseInt
parseFloat과 같은 특성을 가지나 두개의 인수를 갖는다. 두번째 인수는 첫번째 인수를 두번째 인수의 진법으로 판단하여 10진수 정수로 반환하는 역할을 한다.

profile
블로그 이전했습니다

0개의 댓글