객체

2023. 10. 23. 20:21JS

2번째 보는 건데(딴 강의 본 것 하면 4번째)도 불구하고 this 부분은 못 알아 먹겠다. + 게터 셋터도 마찬가지 

일단은 진도 빼면서 전체적인 틀을 세우고 차근차근 구멍난 부분 메꿔가는 식으로 가야지 

 

PART 9 객체 더 보기

213. 객체란 무엇인가?

사실상 JavaScript의 객체는 데이터 구조입니다

-값 쌍인 프로퍼티와 메서드로 이루어져 있죠

메서드 역시 결국에는 키-값 쌍이지만

값은 함수로 객체에 연결되어 있습니다

따라서 프로퍼티는 객체의 변수이고

메서드는 객체의 함수라고 할 수 있습니다

따라서 데이터를 저장하기 위해서는 프로퍼티를 사용하고 해당 데이터는

동일한 객체와 연결되어 있으며

이 객체에 적합한 작업이 이루어지게 됩니다

 

JavaScript에서는 항상 기억해야 할 두 가지 유형의

값이 존재합니다 하나는 원시 값이고

다른 하나는 참조 값이죠 참조 값이 바로 객체이며

오직 객체만이 참조 값이라고 할 수 있습니다

 

객체는 중괄호를 이용해서 사용자가 직접 생성하는데

이를 객체 생성을 위한 객체 리터럴 표기법이라고 합니다

 

즉 객체 리터럴(Literal)을 사용해서

객체를 생성하는 거죠 그리고 여기에

배열도 포함됩니다 배열 또한 length 프로퍼티를

자동으로 조절할 수 있는 특수한 객체였죠

이 특수성은 for of 반복문을 사용할 수 있다는 점에 있는데

이 기능은 다른 객체가 아닌 이와 같은 이터러블에서만 사용할 수 있다고 했습니다

배열 또한 특별한 유형이긴 하지만 역시나 결국 객체에 속합니다

DOM 노드, DOM에서 선택하는 모든 사항 또한 객체에 속하죠

이 외에도 많습니다

 

 

214. 객체 & 원시 값

객체는 참조 값이라는 점은 이미 배우셨습니다.

 

아직 명확하지 않을 수도 있지만, 객체가 원시 값으로 구성된다는 점을 이해하는 것이 중요합니다.

 

다음은 예시입니다.

 

const complexPerson = {

name: 'Max',

hobbies: ['Sports', 'Cooking'],

address: {

street: 'Some Street 5',

stateId: 5,

country: 'Germany',

phone: {

number: 12 345 678 9,

isMobile: true

}

},

};

complexPerson 에 여러 개의 중첩된 참조 값(중첩된 배열과 객체)이 있긴 하지만 이 객체를 파헤쳐보면 결국 원시 값이 됩니다.

 

name은 문자열('Max')을 저장하고 있습니다 => 원시 값

 

hobbies 는 문자열로 된('Sports', 'Cooking') (즉 참조 값) 배열을 저장하고 있습니다 => 원시 값

 

address 'Some Street 5' 와 같은 원시 값과 중첩된 객체(phone)를 포함하게 되지만 phone을 더 자세히 살펴보면 숫자와 불리언만 있습니다 => 원시 값

 

따라서 원시 값은 데이터를 저장하는 핵심 구성 요소이고 객체(와 배열)는 해당 데이터를 구성하고 작업하는 데에 유용합니다.

 

215. 객체 복습

 

person 객체를 하나 생성해 봅니다

중괄호를 사용할 텐데 이 방법을 객체 리터럴(Literal) 표기법이라고 합니다

그리고 키-값 쌍이 필요하겠죠

여기에는 키-값 쌍인 프로퍼티가 들어가는데

프로퍼티에는 정적 값이나 함수가 아닌 값이 저장됩니다

특정 키에 함수를 값으로 저장하게 되면 이를 메서드라고 부르죠

프로퍼티든 메서드든 임의로 선택한

이름에 대해 생성되는데 여기서는 name을 입력하고

: 표시 다음에 값을 넣어 줄 겁니다 중요한 점은

constlet 없이 키로 사용하고자 하는 이름 뒤에

: 표시를 입력하고 값을 넣어 주는데 여기서는 Max를 값으로 해 보겠습니다

age라는 값에는 30을 저장하고

hobbies에는 배열을 값으로 저장해 볼 수도 있겠죠

배열 또한 객체이니

객체에도 객체를 저장할 수 있다는 점을 확인해 볼 수도 있습니다

 

 

216. 프로퍼티 추가, 수정 & 삭제

 

객체에 대해 정의되지 않은 프로퍼티에 액세스를 시도하면

오류 메시지가 뜨는 대신 undefined라는 표시가 나옵니다

person.isAdmin = true ;

이전에 정의한 적이 없더라도 지금 true라고 지정한 뒤

console.log로 전체 person을 로그해 보면

isAdmin도 해당 객체의 일부로 표시될 겁니다

새로 고침하고 펼쳐 보면 isAdmin이 추가되었다고 나옵니다

이렇게 프로퍼티를 즉시 추가하는 것도 아주 쉽습니다

점 표기법을 사용해서 값을 할당하기만 하면 끝이죠

 

이미 속해 있는 프로퍼티에 대해서도 지금처럼 age31

지정하여 이전에 정해져 있던 값을 덮어쓸 수도 있습니다

값을 덮어쓰거나 추가하는 기능 모두 지원됩니다

많은 유연성이 제공된다고 할 수 있겠죠

 

특정 프로퍼티를 삭제하고자 하는 경우가 생길 수도 있습니다

age라는 프로퍼티를 지우려고 한다고 해 보죠

재할당하는 대신 프로퍼티 자체를

삭제하는 경우입니다 이럴 때는 JavaScript

특별한 키워드인 delete를 사용하면 됩니다

delete 다음에 공백을 입력해서

독립 실행형(standalone) 키워드라는 점을 확인하고

person. 뒤에 삭제하고자 하는 age 프로퍼티를 입력합니다

이렇게 하면 person이라는 객체에서 age 프로퍼티를 삭제하게 됩니다

 

person.age = null

null로 설정했을 경우에는

지금 당장은 없지만 나중에 age에 또 다른 값을 설정한다는 의미가 되고

person.age = delete

delete를 사용할 때는 age라는 프로퍼티 자체가 불필요하다는 뜻이 됩니다

 

217. 특수 키 이름 & 대괄호 프로퍼티 액세스

 

지금까지는 키 이름을 정할 때

변수의 이름을 정할 때와 마찬가지의 방식을 따랐습니다

변수의 이름으로 지정할 수 있는 단어라면

키 이름으로 사용할 수 있었죠 키는 변수보다 유연한 특성을 갖습니다

즉 변수에 사용할 수 있는 모든 이름을 키에

사용할 수 있으나, 키의 이름을 모두 변수에 사용할 수 있는 건 아닙니다

 

그렇다면 JavaScript에 이 값이 키 이름이며

문자열에 불과하다는 사실을 어떻게 알려 줄 수 있을까요?

‘first-name’ : ‘Max’

따옴표로 묶어 주기만 하면 됩니다 큰따옴표든 작은따옴표는 상관없습니다

그 뒤에는 모든 문자열을 키 이름으로 사용할 수 있죠

 

그렇다면 first name이라는 키에

아무 오류 없이 표현법 그대로

액세스하는 방법은 무엇일까요? 표현식 그대로 액세스할 수는 없습니다

하지만 JavaScript 객체에 액세스할 수 있는

다른 방법이 있죠 바로 대괄호 표기법을 이용하는 겁니다

person[]

이 표기법을 배열에서 봤는데 배열에서는

특정 인덱스의 요소에 액세스할 때 이 표기법을 사용했었습니다

배열 또한 객체에 속하기 때문에 이 방법을 사용해서

액세스하는 것도 일반적인 객체 표기법에 들어간다고 할 수 있죠

배열 객체에 대해서는 빌트인 특수 동작이 있어서

배열에 요소를 추가할 수 있는 메서드로

인덱스가 자동으로 할당되는 등의 작업을 수행할 수 있습니다

그 외의 다른 객체에 대해서는 이 대괄호 표기법을 사용할 수 있죠

단 대괄호 안에 입력하는 내용은 이제 인덱스 번호가 아닙니다

person 객체는 배열이 아니기 때문에 인덱스가 없죠

따라서 그 대신 이 괄호 안에는

키 이름을 입력해 줄 텐데 여기서 중요하게 짚을 점은

이렇게 age를 입력했을 때 객체 외부에 있는 변숫값을

읽어 들이고 해당 키 이름을 갖는 변수를 찾도록 만드는 것이 아니라

문자열을 입력해 줘야 합니다

perosn [‘first name’]

'first name'이라고 입력해 주면

대괄호 표기법을 이용하여 personfirst name에 액세스가 가능합니다

movieList.style[backgroundColor] = 'red';

이렇게 대괄호 표기법을 사용하면

배경색에 액세스할 수 있는데

앞서 말한 대로 따옴표를 사용했을 때도

따옴표를 사용하지 않았을 때도

JavaScriptbackgroundColor라는

변수를 코드에서 찾아내 해당 변수 안에 있는 값을 용하며 style 객체의 변숫값에 대한 키를 찾습니다

 

 

218. 프로퍼티 유형 & 프로퍼티 순서

 

문자열 프로퍼티 이름 외에도

프로퍼티 이름으로 사용할 수 있는 두 가지 다른 값이 있습니다

바로 숫자와 심볼형이죠

 

프로퍼티를 추가한 순서대로 프로퍼티가 표시됩니다

한 가지 중요하게 짚을 예외를 보여 드리고 넘어가겠습니다

숫자키로만 구성된 numbers라는 객체가 있다고 해 봅시다

숫자가 자동으로 정렬되어 표시된다는 점을 중요하게 기억하시기 바랍니다

 

 

219. 프로퍼티 유형 & 프로퍼티 순서

 

const keyName = ‘first name’;

console.log(person[keyName])

 

first name을 상수에 저장한다면 어떨까요

대괄호 표기법을 사용하면 키 이름에 액세스할 수 있는데

이렇게 하면 따옴표가 필요치 않습니다

keyName의 프로퍼티의 이름을 찾는 것이 아니라

keyName에 속해 있는 프로퍼티의 값을 찾고 있기 때문입니다

person에서 'first name'을 불러오기만 하면 되는 겁니다

person.keyName

점 표기법으로는 불러올 수 없죠

점 표기법을 사용하면 JavaScriptperson

프로퍼티 이름, keyName이라는 프로퍼티를 찾기 때문이죠

keyName의 값이 아니라 person에서 keyName이라는

프로퍼티를 찾는데 없으니

undefined가 될 겁니다 이때 대괄호를 사용하면

동적으로 해당 값을 찾습니다 그리고 keyName

저장되어 있는 상수나 기타 표현식의

결과를 찾아내어 출력해 주죠

 

 

 

 

 

const userChossenKeyName = ‘level’;

 

let persone = {

‘first name’ = ‘max’;

age : 30

hobbies : [‘Sports’, ‘Cooking’]

userChosenKeyName : ‘ ... ’

}

사용자의 입력값이 있다고 해 보죠 userChosenKeyName으로

'level'로 지정한 상수입니다 사용자 임의의 입력값으로

프로그래머인 우리는 코드를 작성할 때 이에 대해 미리 알지 못했습니다

여기서는 예시로 보여 드릴 더미로 하드코딩했다는 점 유념하시기 바랍니다

이렇게 사용자에 의한 동적 입력값이 있고

사전에 알지는 못했으나 이 이름으로 객체에 프로퍼티를 추가하려 합니다

이 위치든 어디든 간에

userChosenKeyName에 값을 추가해 보겠습니다

이 경우 동일한 이름의 변수에 저장된 값이 아닌

userChosenKeyName에 다른 값을 저장한다는 점이

문제가 되는데, 이 경우에는

대괄호를 사용해 볼 텐데 이 위치에 사용하는 건 처음이실 겁니다

[useChoosenKeyName] : ,

좌측 : 앞에 대괄호를 입력하는데

그 괄호 앞에 키 이름을 입력해서 해당 변수를 참조합니다

이제 JavaScriptuserChosenKeyName

키 이름으로 인식해 객체에 추가하지 않고

해당 이름의 변수를 찾아서

해당 변수 또는 상수에 저장된 값을 가지고 옵니다

따라서 이 경우에는 'level'이라는 문자열이 키 이름이 되고

person 객체에 추가되는 거죠 그 뒤에는

원하는 값을 마음껏 할당할 수 있습니다 따라서 이렇게 대괄호를 사용하여

동적으로 프로퍼티에 액세스할 수 있을 뿐만 아니라

동적으로 설정할 수도 있는 겁니다 이 또한 아주 유용한 기능이죠

 

220. 데모 앱 & 축약어 프로퍼티 구문

const moive = {

title : title -> title로 표시 할 수 있음

};

유용한 축약 표기법을 사용해 볼 수 있는데

값의 이름과 동일한 프로퍼티의 이름

즉 변수의 이름이 키에 저장해서

도출하려는 값의 이름과 동일한 경우에는

값의 이름과 ; 표시를 생략할 수 있습니다

설정은 JavaScript가 알아서 수행하게 됩니다

따라서 키 이름과 값 이름이 동일한 경우에 이 방법을 쓸 수 있는데

물론 'title'과 같이

값이 하드코딩된 문자열인 경우에는 생략이 불가능합니다

값이 동적으로 변수에서 도출될 때

해당 변수의 이름이 키 이름과 동일한 경우에만

이 표기법을 사용할 수 있죠

 

[extraName] = extraName;

대괄호를 사용해서 동적 프로퍼티 이름을 할당할 수 있습니다

그 값도 동적이겠지만

이전에 했던 것처럼 : 표시 우측에

본 프로퍼티 값을 저장할 변수를 입력해 주기만 하면 됩니다

 

221. 객체에 기반해 요소 렌더링하기

다중 프로퍼티 요청을 체인이라고 부르죠

 

222. For-in 반복문 & 동적 프로퍼티 출력하기

동적 값에 액세스하는 방법에 대해서는 익히 배웠습니다

대괄호 표기법을 사용하면 되죠

이 구문을 활용해서 동적으로 저장까지는 했습니다만, 어떻게 출력할까요?

 

객체의 모든 키-값 쌍을 살펴볼 수 있는 방법은 무엇일까요?

제어 구조 모듈에서 배웠다시피

for-in이라는 특별한 반복문을 사용하면 됩니다

for in <- 객체 순환 for of <- 배열 순환

 

for (const key in movie.info){

if ( key !== 'title')

}

이 반복문을 통해서 해당 객체에 있는 모든 프로퍼티를 살펴볼 텐데

여기에는 다시 추가할 필요가 없는 title 프로퍼티도 포함됩니다

따라서 if 검사를 추가하여 keytitle과 같지 않을 경우를

나타내는 문자열을 추가합니다

문자열로 입력하지 않으면

JavaScripttitle이라는 이름의 변수를 찾게 되는데 해당 변수를 본 함수 내에서는

찾을 수 없으므로 이 비교문에서는 해당 변수에 저장된 값을 사용합니다

따라서 여기 나와 있는 key가 문자열이므로 문자열과 비교해 줘야겠죠

 

 

${movie.info[key]}

movie.info는 객체로

key 상수에 포함된 키의 값에

액세스하려면 대괄호를 사용해야 합니다

이렇게 사용자가 설정한 프로퍼티 이름에 대한 값에

동적으로 액세스할 수 있습니다

 

223. 필터 기능 추가하기

224. “체이닝(Chaining)” 이해하기 (프로퍼티 & 메서드 체이닝)

movie.info.title

여기서 한 작업이 바로 체이닝(Chaining)이라는 작업이죠

한 줄에도 이렇게 여러 점을 볼 수 있는데

좀 더 정확히 말하면 한 표현식 안에도 여러 점이 들어간 겁니다

이전 연산에서 반환된 객체나 값에 여러 연산을 실행하기 위함이죠

가령 movie.info는 객체를 반환하므로 .title로 해당 객체에

액세스할 수 있습니다

체이닝의 개념은 프로퍼티뿐만 아니라 메서드에서도 활용 가능합니다

id: Math.random().toString()

Math에 대해 random 메서드를 호출하고 그 난수에 toString으로

숫자를 호출하는 거죠 이렇게 체이닝은 아주 특수한

용어이자 개념이며 대부분의 프로그래밍 언어에서

자주 볼 수 있으며 특히 JavaScript에서는

흔히 하는 작업으로 기억해 두셔야 합니다

 

225. 객체 분산 연산자 ()

const person = { name ; ‘Max’, hobbies : [‘Sports’, ‘cooking’]};

 

person.age = 30;

 

const person2 = { ...person};

 

person.age = 31;

 

person2 = name ; ‘Max’, hobbies : Array(2), age: 30};

 

person.hobbies.push(‘coding’);

...라는 전개 연산자 후에

입력된 객체의 모든 키-값 쌍을

해당 키-값 쌍을 본 객체에 병합합니다

이렇게 하면 새로운 객체가 생성되는데

이때 이전 객체의 모든 키값이 복사되는 겁니다

값뿐만 아니라 키 이름도 같이 오죠

이렇게 설정하고 person.age31로 정하면 person2

age는 여전히 30으로 나옵니다 복사본이 만들어졌으니 새 값을

가지고 오지 않는 거죠, 본 코스의 앞에서 살펴본 배열에서처럼

객체 안에 다른 참조 값이 있는 경우

hobbies 배열 등이 있는 경우 배열 또한 객체이며 참조 값이므로

복사 대상이 되지 않습니다

새 객체로 복사된다고 할 수는 있지만

완벽히 복제되는 건 아니죠

메모리에 있는 동일한 배열 객체일 뿐입니다
person.hobbies에 대해 push로 새 취미인

'Coding'을 넣으면 person2에도

hobbiesCoding이 포함된 것을 알 수 있습니다

 

전개 연산자가 객체나 배열에 있는

모든 중첩 참조 값의 수준에 대해

처음부터 복사를 깊게 수행하지 않는다는 점을

알 수 있었습니다 대신 이 연산자는

최상위 수준의 키-값 쌍을 새로운 객체로 복사하죠

모든 중첩 참조 값과 주소를 그대로 유지하나

따로 hobbies가 생성되지는 않습니다

배열에 있는 값 또한 복사하려면

수기로 새 hobbies 배열을

이전 배열에 복사해 줘야 합니다

이것도 주목할 만한 작업이니 제가 한번 보여 드리도록 하죠

 

const person3 = { ,,,person, age: 29, hobbies: [ ...person.hobbies]}

person3라는 상수를 생성해서 person을 그대로 복사한다고

해 봅시다, 원래 있던 hobbies라는 배열을

새로운 배열로 덮어쓰려고 합니다 앞서 사용했던 작업을

그대로 따라서 또 다른 중첩 참조 값으로 덮어쓰는 것이 아니라

언제든 그 값을 덮어쓰고 싶을 때 덮어쓸 수 있도록 설정하고자 합니다

age도 덮어쓰려 한다고 해 보죠

age를 추가하고 30이나 29로 한번 설정해 봅니다

지금 이 작업으로 person에 대한 모든 키-값 쌍을 불러옵니다

age도 포함해서 말이죠 대신 person에서 끌어온

age를 여기서 설정한 값으로 덮어쓰게 되며

hobbies도 이와 같은 과정을 거쳐 덮어쓰게 됩니다

hobbies로 새로운 배열을 설정했는데

여기서 이전에 배웠던 것과 같이

또다시 전개 연산자를 사용해 보겠습니다

person.hobbies에 있는 모든 배열 요소를 새로운 배열로

바꿔 줄 텐데 이를 위해 이전 배열의 복제본을 생성하는 겁니다

대신에 이전 배열 주소를 그대로 복사하지 않고

새로운 객체에 대해

새로운 배열을 생성해 주는 겁니다

 

226. Object.assign() 이해하기

const person = { name : ‘max’};

 

const person2 = object.assign({}, person);

 

person 2

{name : “max”}

Object.assign을 사용하는 방법인데

JavaScript에서 Object는 전역에서 사용 가능한 객체로

assign 메서드를 사용할 수 있는데 여기에 대상을 입력합니다

대상은 생성한 새로운 객체가 될 수 있겠죠

그리고 복사하고자 하는 값을 입력합니다 여기서는 person을 넣어 보죠

-값 쌍에 대해 복사할 여러 소스를 추가할 수 있습니다

이렇게 하면 Object.assign

새로운 객체를 출력하고 다른 인자의

모든 키-값 쌍을 새로운 객체에 병합합니다

이때 반드시 새로운 객체를 생성할 필요 없이

이미 따로 프로퍼티를 갖는 객체를 입력해도 됩니다

그 경우에는 해당 프로퍼티 또한 다른 객체에 병합되겠죠

하지만 지금 보이는 이 사례처럼 Object.assign으로

기존 객체의 프로퍼티를 새로운 객체에 할당하는 것이 일반적입니다

 

227. 객체 구조 분해

객체 구조 분해를 사용하여

-값 쌍을 빼내서 새로운 변수에 저장할 수 있습니다

상수를 하나 넣어 보죠

배열 구조 분해와 같은 개념인데 구문을 본 적은 없으실 겁니다

이번에는 = 표시 좌측에 중괄호를 입력합니다

그리고 우측에는 객체를 지정해 주는데

빼낼 항목이 있는 객체를 입력해 주는 겁니다

const { info}=movie;

객체에서 프로퍼티를 빼낼 때는

순서는 전혀 상관없고 키만이 중요합니다

따라서 지금처럼 info를 사용하려면

movie 안에 info라는 키 즉 프로퍼티 이름이 있어야 합니다

이렇게 지정하면

info 안에 있는 모든 프로퍼티를 빼낼 수 있는데

이 경우에는 또 다른 객체가 됩니다 하지만 문자열이나

다른 항목이라도 상관없이 작업이 수행됩니다

이제 info라는 상수를 사용할 수 있게 되었으니

아래에도 movie.info가 있던 위치에 그 대신에

info를 사용할 수 있게 되었습니다

배열 구조 분해와 마찬가지로

const { info, ...othersProps}=movie;

...로 이루어진 rest 매개변수를 사용할 수도 있습니다

othersProps로 한번 이름을 붙여 보죠

이렇게 하면 info로 빼내지 못한

모든 프로퍼티를 수거하고 수거된 모든 프로퍼티를

포함하고 있는 새로운 객체를 얻을 수 있습니다

otherPropsconsole.log에 입력해 보면

해당 객체에 id만이 포함된 것을 알 수 있습니다

info로 포함되지 않은

유일한 프로퍼티이기 때문이죠

 

const {title: movieTitle } = info;

객체에서 프로퍼티를 빼낼 때는 이름을 사용해야 합니다

순서를 사용해서 빼낼 수는 없죠 단 다른 이름을

사용하고자 하는 경우가 생깁니다 다른 변수와

충돌이 생기거나 변수 이름을 달리 지정하려면

빼낼 값 뒤에 : 표시를 추가해서

새로운 이름을 할당할 수 있죠

= 표시 우측에 있는 중괄호

즉 구조 분해 구문 내에 :을 추가하면

키 이름과 값이 있는

새로운 객체를 생성하는 대신

추출한 프로퍼티에 새로운 이름을 할당할 수 있습니다

 

228. 프로퍼티 존재 확인하기

코드를 작성하다 보면 객체에 어떤 프로퍼티가 있는지 환히 꿰게 됩니다

지금처럼 직접 코드를 작성했기 때문에

모든 movie 객체에 info 프로퍼티가 있음을 알 수 있죠

강사님 제 머릿속에는 없는데 어떻게 하죠?ㅋㅋㅋㅋ

프로그램의 동적인 정도에 따라

 

그리고 코드를 작성할 때는 알 수 없는

객체에 저장될 최종 사용자 입력 데이터의 양에 따라

표시되는 정보가 여전히 존재하는지에 대한 검증이 필요하다고 생각할 겁니다

혹은 코드의 어느 부분에서 info 프로퍼티를

삭제했었는데 여전히 실행되고 있는 건 아닌지 그 여부를 알고 싶어질 수도 있죠

혹은 프로퍼티가 객체에 속해 있는지를 확인해 보고자 할 수도 있겠죠

이 작업도 JavaScript에서 해 볼 수 있습니다

가령 여기 나와 있는 if 문에서 객체에 특정 항목이 포함되었는지를

확인할 때에 특수한 키워드인 in 키워드를 사용해서 볼 수 있습니다

if ( !(‘info’ in movie)){

}

if 뒤에 확인하고자 하는 프로퍼티 이름을 문자열로 입력합니다

'info'와 같이 말이죠, 그 뒤에 in을 넣고 객체를 추가해 줍니다]

infomovie에 포함되는지 확인하는 거죠

결과가 true로 나오면 movieinfo 프로퍼티가

있다는 뜻이 됩니다

info 프로퍼티가 있을 때만 실행되도록 하는 코드를

작성할 수도 있겠죠 이 반대의 경우를 보려면

괄호로 묶고 ! 연산자를 추가해 줍니다

false라는 값이 반환되는지를 확인하는 작업인 거죠

if (info)

}

물론 if 뒤에 (info)를 입력해서 Truthy 값을

반환하는지 볼 수도 있겠죠 undefined

info 키가 없는지 확인하는 방식으로 말입니다

단 객체 구조 분해를 사용할 계획이 없고

여전히 프로퍼티가 코드의 일환인지 확인하는 것이 중요하다면

in 연산자를 사용하면 됩니다

 

if(movie.info === undefined) {

}

또 달리 확인하는 방법으로는

movie.infoundefined와 같은지를 비교해 보는 겁니다

프로퍼티가 undefined라는 값을 반환할 때는

해당 프로퍼티가 존재하지 않거나 삭제되었거나 수기로

undefined라고 설정되었거나 정의된 적이 없는 경우입니다

따라서 undefined와 같은 경우에는 프로퍼티가 존재하지 않으며

이 경우 info 프로퍼티가 없다는 결론을 내릴 수 있습니다

 

229. “this” 소개

JavaScript에는 객체의 일부인

함수 내부뿐만 아니라 코드의 모든 곳에서

사용할 수 있는 특정 키워드가 있습니다

객체의 일부인 함수 내에서

사용할 수 있다는 점이 가장 중요한데 이것이 바로 this 키워드입니다

함수 내에서, 즉 해당 함수가 객체의 일부인지와 상관없이

this 키워드는 해당 함수를 호출한 모든 항목을 참조합니다

해당 함수를 실행시켰던 모든 항목을 말이죠

 

예시를 하나 살펴보죠 return 뒤에

this.info.title.toUpperCase를 입력해 봅니다

이 변환 논리가 객체 안에 포함되도록 말이죠

프로그래밍 시 자주 하게 되는 작업일 겁니다

객체에 논리를 넣어 두는 일 말이죠

본 코스에서는 데이터를 저장하는 데에만 객체를 활용했었습니다

잘못된 것은 아니지만 객체에 논리를

집어넣을 수 있다면 활용도가 훨씬 올라가죠

그렇게 하면 공유 가능한 데이터 컨테이너를 갖게 되어

작업할 수 있는 데이터를 생성할 뿐만 아니라

객체로부터 데이터를 추출해 냈을 때에

변환하는 작업 또한 수행할 수 있기 때문입니다

여기에 특정 논리를 일종의 박스에 포함시킴으로써

원하는 작업을 하도록 실행할 수 있습니다

이때 this 키워드가 중요한 역할을 합니다

this 키워드가 없다면 객체 내에서 info 프로퍼티를 찾지 않을 것이며

다른 곳에서 info 변수를 찾기 위해 헤맬 텐데

따라서 이상한 동작을 수행하게 되고 이 경우에는

info 변수가 없기 때문에 실패한 동작이 될 겁니다

 

230. 메서드 축악어 구문

getFormattedTitle: function() {

return this.info.title.toUppercase();

}

메서드를 정의하는 방법 중 좀 더 짧은 방법으로

함수 키워드를 삭제하는 방법이 있습니다 : 표시를 지우고

프로퍼티 이름 바로 뒤에 괄호를 추가하는 거죠

:과 함께 표시되는 일반적인 키-값 쌍이 아닌

getFormattedTitle() {

return this.info.title.toUppercase();

}

이와 같은 구문을 갖게 됩니다

참고로 화살표 함수를 사용했다면

해당 화살표 또한 삭제해야 합니다

이 또한 객체에 메서드를 추가할 수 있는 또 다른 축약어입니다

 

231. “This” 키워드와 이상한 작동 방식 <이건 다시 봐야겠네, bind 보고 다시 .


232. call()apply()

getFormattedTitle = getFormattedTitle.bind(this);

bind는 나중에 실행할 함수를 미리 구성하는 데에는 유용하지만

여기서는 함수를 바로 실행할 거기 때문에

bind 대신에 함수에서 호출할 수 있는

다른 메서드를 사용할 수도 있는데요

let text = getFormattedTitle.call(movie);

바로 call이 있죠 call 또한 여러 인자를 받는데요

첫 번째 인자는 bind와 마찬가지로 this입니다

this 키워드는 곧 실행될 함수의 내부에서 참조가 되어야 하죠

두 번째, 그리고 그 이상의 인자는 원하는 대로

추가하시면 되고 필요한 경우 인자는 함수 내로 전달됩니다

여기서는 인자를 전달할 필요가 없으니

call 내로 전달할 첫 번째 매개변수에만

신경 쓰도록 하겠습니다 이번에도 바로 movie입니다

그러면 callbind의 차이는 무엇일까요?

bind는 나중에 실행할 함수를 준비하고

마지막에는 새로운 함수 객체를 반환해서

getFormattedTitle에 저장하는 데 반해

call은 그렇지 않고 함수를 바로 실행합니다

즉 여기에 괄호를 추가했지만

함수 내부의 this가 참조하는 내용을 덮어쓰기 할

추가적인 방법이 있어서

this가 가리키는 내용을 변경할 때 함수를 실행해 주는 거죠

이런 작업에 call의 역할이 중요한 겁니다

let text = getFormattedTitle.apply(movie ,[]);

apply가 있는데요, applycall

아주 유사하게 함수를 바로 실행해 줍니다

다만 첫 번째 인자는 여전히 this가 나타내는 내용이지만

다음 인자를 무한하게 추가할 수는 없습니다

추가할 수 있는 인자는 하나 뿐이며

이 인자는 배열이어야 하죠

그리고 그 배열이 이 함수가 가지게 될 다양한 인자에 대한

값이 될 수 있습니다 그러므로 결국 차이점은

call을 사용하면 쉼표로 구분된 목록으로

추가 인자를 전달할 수 있고

apply를 사용하면 배열로서 추가 인자를 전달합니다

함수 내부의 this는 항상 해당 함수를 호출한 것

 

정확히 말하자면 함수 실행 앞에 있는 내용을

참조하게 된다는 점을

기억해 두시면 됩니다

 

233. 브라우저가 (가끔씩) “this”에 하는 작업 <이건 2번째 보는데도 모르겠네

다시 말씀 드리지만 this는 앞에 있는 부분은

함수를 직접 실행할 경우에만 의미가 있습니다

즉 괄호를 추가하거나 apply 혹은 call을 사용할 경우죠,

 

const searchMovieHandler = () => {

console.log(this);

const filterTerm = document.getElementById('filter-tilte').value;

renderMovies(filterTerm);

};

 

addMovieBtn.addEventListener('click', addMovieHandler);

searchBtn.addEventListener('click', searchMovieHandler);

 

함수 내부의 this는 사실 객체를 나타냅니다, 즉 함수를 발생시키는 이벤트를 (정리: 브라우저는 이벤트 리스너에서 이벤트를 트리거 하는 DOM 요소에 this를 바인딩 합니다)

그러나 사실은 이것도 화살표 함수인

() =>를 사용하지 않을 때만 해당되는 내용

 

234. “This”와 화살표 함수

const searchMovieHandler = () => {

console.log(this);

const filterTerm = document.getElementById('filter-tilte').value;

renderMovies(filterTerm);

};

 

addMovieBtn.addEventListener('click', addMovieHandler);

searchBtn.addEventListener('click', searchMovieHandler);

이 함수에는 this가 없습니다

모든 함수는 고유의 this가 있죠 function 키워드 또는

메서드 단축키로 생성된 함수는 고유의 this 바인딩을 가집니다

결국 함수 내부의 this가 무엇인가에 바인딩 되는데

함수를 실행하는 주체에 바인딩이 되죠

그런데 화살표 함수에는 this가 어느 것에도 바인딩되지 않아서

여기에 this 키워드를 사용하면 오류가 발생하지 않습니다

하지만 this는 단순히 함수로 덮어쓰여지는 게 아니라

함수 외부를 참조하게 됩니다

 

화살표 함수는 this를 모릅니다

화살표 함수 내부의 this는 화살표 함수 외부의 this(전역 스크립트에서의 this 전역윈도우를 가리킴)와 역할이 같기 때문입니다

 

const members = {teamName : ‘Blue Rockets’,

People: [‘Max’, ‘Mannuel’], getTeamMembers(p => {

console.log(p + ‘ - ’ + this.teamname);

){

this.people.forEach

}};

members.getTeamMembers();

객체는 teamName이고 Blue Rockets가 이름입니다

이름은 임의대로 고르시면 됩니다 키는 people이며

MaxManuel이라는 배열을 포함하고 있죠

여기에 메서드도 넣겠습니다

getTeamMembers 그리고 이 작업의 목표는 팀 이름과

사람 이름을 결합하는 겁니다

members.getTeamMembers() 함수를 호출하면, 뭐가 나타날까요

여기서 thisgetTeamMembers 내부의

members 객체를 나타냅니다 왜냐하면 .을 이용해 members에서

getTeamMembers를 호출하고 있기 때문이죠

Enter 키를 누르면 Max - Blue Rockets

Manuel - Blue Rockets가 나오네요 이 값을 얻게 된 이유는

forEach 내에 화살표 함수를 사용했기 때문입니다

이제 화살표 함수가 없으면 어떻게 나올지를 보여 드릴게요

여기를 복사하고 페이지를 새로 고침한 뒤 members 객체를 재생성합니다

이번에는 function 키워드로 함수를 사용해 보겠습니다

괄호 내에는 사람을 뜻하는 p를 넣고, 나머지는 동일합니다

논리는 그대로이고 forEach에서 함수를 정의하는 방식만 변경한 거죠

Enter 키로 members 객체를 생성하고, getTeamMembers

호출하면, MaxManuelundefined 상태입니다

앞서는 작동을 했는데 왜 지금은 안 되는 걸까요?

forEach에 전달하는 함수의 생성 방법이 다르기 때문입니다

이렇게 function 키워드로 함수를 생성하면

this가 바인딩됩니다, function 키워드로 생성된 함수는

this를 함수 내부에 바인딩하는 거죠

<-번역이 이상하게 되어 있는건지 내용 이해가 안되는데

 

 

235. “This” - 요약

this 키워드는 JavaScript에서 골칫거리가 될 수 있습니다. 이 요약이 해결책이 되기를 바랍니다.

 

this는 사용 위치와 (함수에서 사용되는 경우) 함수 호출 방법에 따라 다른 것을 참조합니다.

 

보통 this(함수 내부에서 사용되는 경우) 함수를 호출한 '무언가'를 나타냅니다. 이는 전역 컨텍스트, 객체 또는 바인딩된 데이터/객체일 수도 있습니다(: 브라우저가 클릭 이벤트를 트리거한 버튼과 this를 바인드할 때).

 

1) 전역 컨텍스트(즉 함수 외부)에서의 this

 

function something() { ... }

 

console.log(this); // 전역 객체(브라우저의 창)를 기록합니다 - 항상(엄격 모드에서도)!

2) (화살표 함수가 아닌)함수에서의 this - 전역 컨텍스트에서 호출됐을 때

 

function something() {

console.log(this);

}

 

something(); // 엄격 모드가 아닐 땐 전역 객체(브라우저의 창)를 기록하고 엄격

3) 화살표 함수에서의 this - 전역 컨텍스트에서 호출됐을 때

 

const something = () => {

console.log(this);

}

 

something(); // 전역 객체(브라우저의 창)를 기록합니다 - 항상(엄격 모드에서도)!

4) (화살표가 아닌) 메서드에서의 this - 객체에서 호출됐을 때

 

const person = {

name: 'Max',

greet: function() { // or use method shorthand: greet() { ... }

console.log(this.name);

}

};

 

person.greet(); // 'Max'를 기록하고, "this"person 객체를 참조함

5) (화살표 함수) 메서드에서의 this - 객체에서 호출됐을 때

 

const person = {

name: 'Max',

greet: () => {

console.log(this.name);

}

};

 

person.greet(); // 아무것도 기록하지 않음(아니면 창 객체의 일부 전역 이름을 기록), "this"는 엄격 모드에서도 전역() 객체를 나타냅니다.

this는 다른 객체에서 호출하는 경우 예상치 못한 것을 나타낼 수도 있습니다. 예시:

 

const person = {

name: 'Max',

greet() {

console.log(this.name);

}

};

 

const anotherPerson = { name: 'Manuel' }; // 내장된 greet 메서드가 없습니다!

 

anotherPerson.sayHi = person.greet; // greet은 여기서 호출되는 것이 아니라 "anotherPerson" 객체의 새로운 프로퍼티/메서드에 할당됩니다.

 

anotherPerson.sayHi(); // "anotherPerson" 객체에서 호출되었기 때문에 ‘Manuel’을 기록합니다 => "this"는 호출한 "무언가"를 나타냅니다

헷갈리는 경우에는 console.log(this);가 항상 this가 현재 무엇을 의미하는지 알아내는 데에 도움을 줄 수 있습니다!

 

236. 획득자(Getters) & 설정자(Setters) <2회차 뭔말인지 못 알아 먹겠는데 ?

if 문 내의 title 확인을 제거하고 아래의 info에서도 제거합니다

그 대신, info에 특별한 키워드를 추가하겠습니다

get, 그리고 프로퍼티 이름으로 선택했던

title을 적고 메서드처럼 괄호를 사용한 뒤

메서드 본문처럼 중괄호를 넣습니다 get title()

이렇게 하면 getter를 생성할 수 있게 됩니다

JavaScript가 특수 get 키워드를 감지하고 메서드와 결합해서

프로퍼티와 같이 액세스를 할 수 있게 되죠

괄호는 더 추가하지 않고 따옴표로 호출하지만

값을 회수하기 위해 논리를 실행하는 겁니다

set에서도 똑같이 할 수 있습니다

set 키워드, 프로퍼티 이름, 그리고 괄호 및 중괄호입니다 set title()

이때 매개변수도 수락해야 하는데 value 매개변수라고 하겠습니다

원하는 이름으로 만드세요 여러분이 set하려는

값을 가진 매개변수가 되죠 그리고 setter 내부에는

newMovie를 참조하는 this로 프로퍼티를 타겟팅할 수 있는데요

newMovie.title을 나중에 호출할 경우죠

만약 다른 프로퍼티를 set 한다면

title이 아니라 _title을 사용해서 내부 값을 표시하고

외부의 값에 대해서는 getsettitle

사용할 수 있습니다 그럼 this._title = val;로 지정해 봅시다

그런데 여기에 추가적인 if 확인을 할 수 있는데요

val.trim이 빈 문자열인지를 확인하고 val.trim() === ' '

그런 경우에는 this._title = 'DEFAULT'로 설정하겠습니다

그리고 return을 사용해 줄이 계속되지 않도록 해줍시다

그러면 결과는 이전과 달라지겠죠

아까는 잘못된 입력 때문에 전체 함수를 중지했지만

이제는 계속하면서 기본 값을 set 하게 되는 겁니다

이런 시나리오가 있을 때 setter를 사용하면 (코드 실행 중지/try-catch 원할 경우 오류를 발생시켜도 됩니다)

값이 title 프로퍼티에 할당되고 수락되거나 (코드 실행 중지/try-catch 원할 경우 오류를 발생시켜도 됩니다)

다른 값으로 set될 때 유효성 검사를 할 수 있습니다

getter의 경우 사람들이 title에 액세스할 때

무엇을 할지 정의할 수 있죠 get 부분을 생략하실 수도 있는데

그런 경우 읽을 수 없는 프로퍼티가 생기고

setter를 생략하면 읽기 전용 속성이 생깁니다만, 저는 둘 다 추가할게요

그리고 return this._title로 반환을 하겠습니다

이렇게 즉석에서 생성하는 내부 프로퍼티를 참조하는 거죠

그럼 이 부분을 어떻게 사용하면 될까요?

 

 

gettersetter

추가적인 유효성 검사를 할 경우에 유용하고

폴백이나 또는 값을 얻을 때의 추가 변환에 유용하게 사용됩니다

그리고 앞서 말씀 드렸던 것 처럼

읽기 전용 값과도 작업할 수 있어서 유용합니다

setter 없이 getter만 추가할 때에는 절대 사용하지 않습니다

둘 다 추가하거나 둘 다 사용하지 않는 거죠

 

237. 마무리

'JS' 카테고리의 다른 글

deep js - 2일차  (0) 2024.05.18
deep js - 1일차  (0) 2024.05.17
HTTP 요청으로 작업하기  (0) 2023.10.20
비동기 프로미스 & 콜백  (1) 2023.10.19
JS 오늘 공부한 내용  (0) 2023.10.16