항해99 WIL

항해 99 3주차 WIL

코치원 2022. 10. 2. 03:46

🔐 자바스크립트에서 유사배열과 배열의 차이는 무엇일까요?

유사배열의 각 요소를 수정하고 싶다면 어떤 과정을 거쳐야 할까요?

 

자바스크립에서 유사배열과 배열의 차이는 무엇일까요?

 

유사배열(Array-Like Object)이란

 

배열처럼 보이지만 인덱스로 프로퍼티 값에 접근할 수 있고, length 프로퍼티를 갖는 객체를 뜻한다. 함수에서 처리 결과로 배열을 반환하고 싶을 때 또는, Array에서 기본으로 내포되어있는 기능을 제공하고 싶지 않거나 Array에 내포되어있지 않은 기능을 제공하고 싶을 때 사용한다.

 

차이점

 

A) 배열 유사 객체의 인덱스 범위는 0≤I≤2^53–1인 반면 배열의 인덱스 범위는 0≤ I <2^32–1이다.

B) 유사배열은 Array.prototype 객체에서 파생되지 않는다. 따라서 push, pop, forEach 등과 같은 순회 및 리모델링 작업을 수행할 수 없다.

유사 배열에서는 배열처럼 push, pop, join, map과 같은 메서드 사용은 불가하며, 일반 객체처럼 프로퍼티로 접근할 수 없다. 대표적으로 볼 수 있는 유사 배열 객체에는 함수의 arguments, HTMLCollection, NodeList가 있다.

유사배열의 각 요소를 수정하고 싶다면 어떤 과정을 거쳐야 할까요?

  1. Array.from() 메서드 사용하기

유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사해 새로운 Array  객체를 만든다 ⇒ 유사배열을 배열로 만든 후 배열 메서드를 사용하면 된다.

 

HTMLCollection 예제에 대해 다음을 수행할 수 있다.

const collection = Array.from(document.getElementsByTagName('li'))

HTMLCollection 예제에 대해 개발자 검사에서 console로 예제를 할 수 있다.

__proto__의 값을 확인하면 Array이다.

 

  1. ES6 스프레드 연산자 사용하기

ES6 확산 연산자([...array-like])를 사용하여 유사 배열을 배열로 변환할 수 있다.

예를 다시 살펴보자.

function checkArgs() {
  // Using spread operator
  [...arguments].forEach((elem) => {
    console.log(elem);
  });
}

여기서 인수에 대해 스프레드 연산자를 사용하고 있으며 이제 이에 대해 forEach를 사용할 수 있다.

checkArgs(1,45);

1과 45를 넣으면

1
45

이렇게 나오게 된다.

 

3.• Spread operator : 0개 이상의 인수가 필요할 때마다 iterable이 요소를 확산할 수 있다. 세 개의 점(…)으로 표현한다. 두 개의 배열을 결합하는 데 주로 사용된다.

let str = "Javascript";
console.log("Is array before applying spread operator: ", Array.isArray(str));
str = [...str];
console.log(
  "Is array after applying spread operator: ",
  str,
  ":",
  Array.isArray(str)
);
function func() {
  console.log("arguments object: ", typeof [...arguments], " : ", [
    ...arguments,
  ]);
}
func("One", 1, true);

출력: 확산 연산자(…)를 사용하여 유사배열을 배열로 변환

 

  1. Object.values() : 객체의 모든 열거 가능한 속성 값을 포함하는 배열을 반환한다. 루프처럼 순서를 유지하지만 프로토타입 체인의 속성은 제외한다.
let baseObj = { 0: "Array", 1: "Array-like", length: 2 };
console.log(
  "Is array before calling Object.values(): ",
  Array.isArray(baseObj)
);
let result = Object.values(baseObj);
console.log(
  "Is array after calling Object.values(): ",
  result,
  ":",
  Array.isArray(result)
);
function func() {
  let arg = Object.values(arguments);
  console.log("arguments object: ", typeof arg, " : ", arg);
}
func("One", 1, true);

출력: Object.values()를 사용하여 유사 배열을 배열로 변환

 

요약

  • 배열은 요소라고 하는 배열 인덱스 속성 키와 길이라고 하는 구성할 수 없는 속성이 있는 이국적인 개체다.
  • 배열과 유사한 객체는 보기의 배열과 유사하지만 Array.prototype 객체에서 파생되지 않다. 따라서 배열의 순회 및 리모델링 기능을 적용할 수 없다.
  • 문자열은 숫자 인덱스와 문자열의 길이 속성 반환 길이를 사용하여 각 문자에 액세스할 수 있는 배열과 유사한 객체로 처리된다.
  • Array.from(), 스프레드 연산자 및 Object.values()를 사용하여 배열과 유사한 객체를 배열로 변환할 수 있다.
  • 내장 배열 함수를 적용하기 전에 배열과 유사한 객체를 배열로 변환하는 것이 가장 좋다.

출처 : https://medium.com/globant/array-vs-array-like-objects-in-javascript-cc1523e21089

 

Array vs Array-like objects in JavaScript

The invisible and the non-existent look very much alike. — Author: Delos McKown

medium.com

 🔐 부모 컴포넌트 A와 자식 컴포넌트 B가 있습니다. 컴포넌트 A는 state로 {name: "르탄이"}를 가지고 있고, 자식인 컴포넌트 B에게 name 값을 넘겨주었습니다. 컴포넌트 B는 받아온 name을 화면에 뿌려주고 있습니다. 컴포넌트 A의 state가 {name: "진도사우르스"}로 바뀌었을 때, 어떤 과정을 거쳐 바뀐 값을 화면에 보여주는지 라이프 사이클 흐름을 그려볼까요?

 

<수정 전>

import React from "react";

function Child(props) {
  return <div>{props.motherName}</div>;
}

function Mother() {
  const name = '르탄이';
  return <Children motherdName={name} />;
}

function App() {
  return <Mother />;
}
export default App;

<수정 후>

import React from "react";

function Child(props) {
  return <div>{props.motherName}</div>;
}

function Mother() {
  const name = '진도사우르스';
  return <Child motherName={name} />;
}

function App() {
  return <Mother />;
}
export default App;

Mother 컴포넌트에서 name = ‘르탄이’이라는 state를 ‘진도사우르스’로 바꾸면 마운트(생성)에서getDeriveStateFromProps()가 발생하고 Mother 컴퍼넌트에서 업데이트(갱신)될 때 shouldComponentUpdate()가 실행되면서 불필요한 리렌더링을 걸러내게 되며 <Child motherName={name} />에서 name=’진도사우르스’로 바뀐 props를 Mother 컴포넌트로 렌더링하고 Child 컴포넌트가 props를 받아 렌더링을 실행해서 ‘르탄이’에서 ‘진도사우르스’로 바뀌어 보이게 된다.

 

lifecycle 흐름도

React에서 lifecycle은 **마운트(생성)→업데이트(갱신)→언마운트(제거)**로 진행

 

마운트(생성)

컴포넌트가 생성되어 DOM에 추가되어 나타날 때 발생한다. 마운트 될 때 호출되는 메서드는 아래와 같다.

 

constructor()

마운트가 시작될 때 컴포넌트의 생성자가 맨 처음 호출되고 생성자에서는 state를 초기화하거나 이벤트 바인딩을 처리한다. 생성자에서 setState()를 호출해서는 안되며 필요한 경우 state에 직접 할당해야 한다. 생성자 외에 메서드에서는 setState()를 호출하여 state를 변경해야 한다.

 

getDeriveStateFromProps()

해당 v16.3부터 생긴 매서드. 마운트, 업데이트가 발생할 때 모두 발생한다. state를 갱신하기 위해 객체를 반환할 때 사용된다.

 

render()

마운트, 업데이트에서 모두 발생한다. 브라우저에 보일 화면을 구성한다. props와 state를 활용하여 엘리멘트를 반환하거나 문자, 숫자 또는 null이나 boolean, 배열, Fragment, 다른 컴포넌트를 반환해야 한다. state가 변경되면 안 되고 브라우저와 상호작용하는 작업을 하면 안 된다. 브라우저와 상호작용을 해야 한다면 componentDidMount()에서 하거나 다른 라이프사이클 메서드에서 해야 한다.

 

componentDidMount()

컴포넌트가 마운트 된 후 호출되는 메서드. DOM 노드가 만들어지고 필요한 작업이 있다면 해당 메서드에서 진행하면 된다. setInterval(), setTimeout(), 네트워크 요청 등

 

업데이트(갱신)

업데이트는 props, state가 변경될 때, 부모 컴포넌트가 리렌더링할 때와 this.forceUpdate로 강제로 리렌더링을 할 때 발생한다. 업데이트가 발생할 때 호출되는 메서드는 아래와 같다.

 

getDerivedStateFromProps()

마운트, 업데이트가 발생할 때 호출된다. 마운트에서 설명한 것과 동일하다.

 

shouldComponentUpdate()

props, state가 변경될 때 getDerivedStateFromProps() 메서드가 호출된 후 호출된다. 컴포넌트를 리렌더링 할지 여부를 지정한다. 컴포넌트에 정의되어있지 않으면 기본값 true를 반환한다. 해당 메서드에서 false를 반환하면 리렌더링이 되지 않고 중지된다. 리액트 문서에 따르면 성능 최적화를 위한 메서드라고 한다.

 

getSnapshotBeforeUpdate()

render() 메서드가 진행 후 호출되는 메서드. 렌더링 결과가 DOM에 반영되기 전에 호출된다. 리렌더링이 끝나기 전에 DOM의 정보를 참조해야 할 때 사용할 수 있다.(스크롤 위치 작업 등등) null 또는 값을 반환한다.

 

componentDidUpdate()

리렌더링이 끝나면 호출된다. 컴포넌트가 업데이트되고 DOM을 조작하기 위해 사용한다. 메서드에서 인자로 이전 props, state를 사용할 수 있다. 세 번째 인자로 getSnapshotBeforeUpdate()에서 반환한 값이 snapshot 인자로 넘어온다.

 

언마운트(제거)

컴포넌트가 모두 사용이 끝나 DOM에서 제거될 때 발생한다. 언마운트가 발생할 때 호출되는 메서드는 componentWillUnmount()이다.

 

componentWillUnmount()

컴포넌트가 제거되기 직전에 호출된다. 타이머를 제거하거나 componentDidMount() 메서드에서 생성되어 정리가 필요한 작업을 진행한다.

 

3주차를 맞이했다. 이번 주엔 주특기로 리액트에 대해 공부했다. 개인과제와 팀 과제가 있었는데 팀 과제는 구글링으로 어떻게든 할 수 있었지만 개인과제는 정말 멍해지는 것이었다. 기초 강의 문서를 주고선 리액트를 만들어서 제출하라는데 정말... 미니카 만드는 법을 알려주고는 자동차 만들어서 제출하라고 하는 것과 비슷했다. 그래서 리액트가 뭔지 검색해서 읽어보고 유튜브로 찾아서 강의를 듣는 등 많이 힘든 리액트의 시작이었다. 버티고 버티면 된다고 생각하는데 잘해나갈지 아직도 조금의 의문이 들고 있다... 지금의 내가 미친 듯이 공부해야 미래의 내가 편할 것 같기에 어떻게든 이해하려고 하는 한 주였다....