[JS CS] 객체

작성:    

업데이트:

카테고리:

태그: , ,

객체

객체란?

  • 속성(property)의 집합
  • python의 dictionary


key-value 정의

  • key는 문자열 타입만 가능
  • key 이름에 띄어쓰기 같은 구분자가 있으면 따옴표로 묶어서 정의
  • value는 모든 타입(함수포함) 가능


접근

  • 객체 요소 접근은 점 또는 대괄호로 가능
  • key 이름에 띄어쓰기 같은 구분자가 있으면 대괄호 접근만 가능


객체와 메서드

  • 메서드는 어떤 객체의 속성이 참조하는 함수
  • 객체.메서드명() 으로 호출
  • 메서드 내부에서는 this 키워드가 객체를 의미
const me = {
  firstName: 'John',
  lastName: 'Doe',

  fullName: this.firstName + this.lastName, // NaN 반환

  getFullName: function () {
    return this.firstName + this.lastName // 정상적으로 firstName+lastName 반환
  }
}
  • fullName 속성은 메서드가 아닌데 this를 사용 → 정상출력 되지 않음(NaN)
  • getFullName 메서드는 메서드이므로 this 사용 가능 → 정상적으로 반환


객체 ES6 문법 1 : 속성명 축약(shorthand)

  • 객체를 정의할 때 key와 할당하는 변수의 이름이 같으면 축약 가능
var books = ['Learning JS', 'Learning Python']
var magazines = ['Vogue', 'Science']

// ES5
var bookShop = {
  books: books,
  magazines: magazines,
}

// ES6
const bookShop = {
  books,
  magazines,
}

console.log(bookShop)


객체 ES6 문법 2 : 메서드명 축약(shorthand)

  • 메서드 선언 시 function 키워드 생략 가능
// ES5
var obj = {
  greeting: function () {
    console.log('Hi!')
  }
}

// ES6
const obj = {
  greeting() {
    console.log('Hi!')
  }
}

obj.greeting()  // Hi!


객체 ES6 문법 3 : 계산된 속성(computed property name)

  • 객체를 정의할 때 key의 이름을 표현식을 이용하여 동적으로 생성 가능
const key = 'fruits'
const value = ['바나나', '사과', '파인애플', '참외']

const food = {
  [key]: value,
}

console.log(food)         // {fruits: Array(4)}
console.log(food.fruits)  // ["바나나", "사과", "파인애플", "참외"]


객체 ES6 문법 4 : 구조 분해 할당(destructing assignment)

  • 배열 또는 객체를 분해하여 속성을 변수에 쉽게 할당할 수 있는 문법
const userInformation = {
  name: '홍길동',
  userId: 'gildong1234',
  phoneNumber: '010-1234-1234',
  email: 'gildong@gmail.com',
}

const name = userInformation.name
const userId = userInformation.userId
const phoneNumber = userInformation.phoneNumber
const email = userInformation.email


const userInformation = {
  name: '홍길동',
  userId: 'gildong1234',
  phoneNumber: '010-1234-1234',
  email: 'gildong@gmail.com',
}

const { name } = userInformation
const { userId } = userInformation
const { phoneNumber } = userInformation
const { email } = userInformation

// 여러 개도 가능
const {name, userId} = userInformation


객체 ES6 문법 5 : Spread operator

  • spread operator(…)를 사용하면 객체 내부에서 객체 전개 가능
  • ES5까지는 Object.assign() 메서드 사용
  • 얕은 복사에 활용 가능
const obj = {b: 2, c: 3, d: 4}
const newObj = {a: 1, ...obj, e: 5}

console.log(newObj) // {a: 1, b: 2, c: 3, d: 4, e: 5}


JSON

  • JavaScript Object Notation
  • key-value 쌍의 형태로 데이터를 표기하는 언어 독립적 표준 포맷
  • 자바스크립트의 객체와 유사하게 생겼으나 실제로는 문자열 타입
  • JS의 객체로써 조작하기 위해서는 구문 분석(parsing)이 필수

  • 자바스크립트에서는 JSON을 조작하기 위한 두 가지 내장 메서드 제공
  • JSON.parse() : JSON → JS 객체
  • JSON.stringify() : JS 객체 → JSON


예시

// object → JSON

const jsonData = JSON.stringify({
  coffee: 'Americano',
  iceCream: 'Cookie and cream',
})

console.log(jsonData)          // "{"coffee":"Americano",...}
console.log(typeof jsonData)   // string
// JSON → object

const jsonData = JSON.stringify({
  coffee: 'Americano',
  iceCream: 'Cookie and cream',
})

const parsedAta = JSON.parse(jsonData)

console.log(parsedData)          // "{"coffee":"Americano",...}
console.log(typeof parsedData)   // object


this

  • JS의 this는 실행 문맥(execution context)에 따라 다른 대상을 가리킨다.
  • class 내부의 생성자(constructor) 함수에서는 생성되는 객체를 가리킴(python의 self)
  • 메서드에서는 해당 메서드가 소속된 객체를 가리킴
  • 위의 두 경우를 제외하면 모두 최상위 객체(window)를 가리킴


function getFullName () {
  return this.firstName + this.lastName
}

const me = {
  firstName: 'John',
  lastName: 'Doe',
  getFullName: getFullName,
}

const you = {
  firstName: 'Jack',
  lastName: 'Lee',
  getFullName: getFullName,
}

me.getFullName()    // JohnDoe (this === me)
you.getFullName()   // JackLee (this === you)
getFullName()       // NaN     (this === window)


function 키워드와 화살표 함수 ⭐

  • this.radiuses는 메서드 소속이므로 정상적으로 접근 가능
  • forEach의 콜백함수의 경우 메서드가 아님
  • 때문에 콜백함수 내부의 this는 window가 되어 this.PI는 정상적으로 접근 불가능

  • 이 콜백함수 내부에서 this.PI에 접근하기 위해서 함수객체.bind(this) 메서드 사용
  • “너가 말하는 this가 obj 객체지? 내가 고정해줄게” 라는 기능
  • 이 번거로운 bind 과정을 없앤 것이 화살표 함수
const obj = {
  PI: 3.14,
  radiuses: [1, 2, 3, 4, 5],
  printArea: function () {
    this.radiuses.forEach(function (r) {
      console.log(this.PI * r * r)
    }).bind(this)
  },
}
const obj = {
  PI: 3.14,
  radiuses: [1, 2, 3, 4, 5],
  printArea: function () {
    this.radiuses.forEach((r) => {
      console.log(this.PI * r * r)
    })
  },
}

Summary

  • 함수 내부에 this 키워드가 존재할 경우
  • 화살표 함수와 function 키워드로 선언한 함수가 다르게 동작

  • 함수 내부에 this 키워드가 존재하지 않을 경우
  • 완전히 동일하게 동작


lodash

A modern JavaScript utility library

  • 모듈성, 성능 및 추가 기능을 제공하는 JavaScript 유틸리티 라이브러리
  • array, object 등 자료구조를 다룰 때 사용하는 유용하고 간편한 유틸리티 함수들 제공
  • reverse, sortBy, range, random, cloneDeep


사용 예시

<body>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
  <script>
    // 위의 CDN import를 통해 _(underscore) 식별자 사용 가능

    _.sample([1, 2, 3, 4]) // 3 (random 1 element)
    _.sampleSize([1, 2, 3, 4], 2) // [2, 3] (random 2 element)

    _.reverse([1, 2, 3, 4]) // [4, 3, 2, 1]

    _.range(5) // [0, 1, 2, 3, 4]
    _.range(1, 5) // [1, 2, 3, 4]
    _.range(1, 5, 2) // [1, 3]

  </script>
</body>


얕은 복사와 깊은 복사

<body>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
  <script>
    // 위의 CDN import를 통해 _(underscore) 식별자 사용 가능

    const original = {a: {b: 1}}
    const ref = original
    const copy = _.copyDeep(original)

    console.log(original.a.b, ref.a.b, copy.a.b) // 1, 1, 1
    ref.a.b = 10
    console.log(original.a.b, ref.a.b, copy.a.b) // 10, 10, 1
    copy.a.b = 100
    console.log(original.a.b, ref.a.b, copy.a.b) // 10, 10, 100
  </script>
</body>

lodash를 사용하지 않을 경우, 깊은 복사는 직접 함수를 만들어서 구현해야 함

댓글남기기