pass by reference in 중고거래
오늘은 fetch API를 이용해 간단한 상점 페이지를 구현하는 강의를 들었다.
그리고 과제를 구현하면서 궁금했던 사항이 있어 적어보려고 한다.
이전 강의에도 흘러가듯이 나왔던 것 같은데 기록을 안하니 머리에 안남은 것 같아서 정리해보려고 한다.
HTML5 에서 새로 도입된 속성으로 HTML 요소에 커스텀 속성을 표시하는 표준화된 방법을 제시한다.
어떤 요소던 간에 data-
로 시작하는 속성을 붙이면 사용할 수 있다.
<div id="example" data-index="7" data-creator="thru" >요론 느낌으로</div>
자바스크립트에서는 DOM 생성 시점에 해당 속성들을 dataset
맵에 하나로 모아서 관리한다.
접근할 때는 기존처럼 getAttribute
를 사용할 수도 있지만, 객체의 속성을 읽는 것처럼 $element.dataset.name
과 같은 형식으로 접근할 수 있다.
이 때 name은 data-
뒤에 붙은 이름을 사용하는데 대시-
가 있는 경우 자동으로 camelCase로 변환된다.
읽을 수만 있는 건 아니고 새로 값을 넣어주는 것도 가능하다.
HTML 요소에 붙어있는 속성이므로 CSS에서도 속성 선택자 등으로 접근이 가능하다.
#example[data-index='7'] {
display: flex;
}
접근 보조 기술이 접근할 수 없기 때문에 접근 가능해야 하는 내용은 데이터셋 속성으로 표시하면 안된다.
마찬가지로 검색 크롤러도 인덱싱하지 않으므로 관련 컨텐츠 표시용으로 사용하는 건 부적합하다.
그렇다고 아예 노출되면 안되는 값을 넣는 용도로 쓰면 안되는데 개발자 도구로는 보이기 때문이다.
매개변수로 받은 CSS 선택자에 일치하는 요소를 찾을 때 까지 자신을 포함해서 조상 요소를 순회하는 메서드이다.
필요한 부모 노드를 찾을 때 parentNode 같은 걸로 반복문을 돌리지 않아도 된다는 장점이 있다.
기본 메서드를 잘 알고있으면 유용하게 쓸 수 있을 것 같다.
과제하는 중에 parameter의 동작 관련해서 이해되지 않았던 사항이 있었다.
자바스크립트의 변수 할당 방식을 곰곰히 생각해보다가 해결되서 정리해보려고 한다.
먼저 문제가 되었던 코드는 대략 다음과 같다.
function TodoList() {
this.state = [1, 2, 3];
this.setState = (nextState) => {
this.state = nextState;
}
}
function TodoCount({todoState}) {
this.print = () => {
console.log(todoState);
}
}
const todoList = new TodoList();
const todoCount = new TodoCount({
todoState: todoList.State,
});
todoList.setState([4, 5, 6]);
todoCount.print(); // [1, 2, 3] 이 출력된다.
todoCount
의 매개변수로 todoList.State
의 값을 가진 todoState
라는 배열을 전달하고 내부에서 사용한다.
내가 착각한 것은 todoState
가 todoList.state
의 주소값이 전달된 것이므로 todoList
에서 setState
로 state
를 변화시키더라도 todoCount
내부에서 변화된 state
값에 접근이 가능할거라는 점이다.
핵심은 setState
에서 state
자체를 변경시켰다는 것이다.
state
의 내부 요소를 변경했다면 todoCount
가 접근 가능한 게 맞지만 자체를 바꿔버리면서 state
가 새로운 주소를 가리키게 됐고, todoCount
의 todoState
와 todoList.state
는 서로 다른 주소를 가리키는 상태가 된다.
결과적으로 todoCount
에서는 todoList.state
의 초기값만 볼 수 있다.
내가 해결한 방식은 함수를 전달하는 것이다.
function TodoCount({getTodoState}) {
this.print = () => {
console.log(getTodoState());
}
}
const todoCount = new TodoCount({
getTodoState: () => todoList.state,
}
이렇게 하면 print
를 실행한 시점의 todoList.state
를 가져오므로 문제를 해결할 수 있다.
pass by reference는 사실상 동기화라는 관념으로 고민없이 사용했던 건데 immutable update를 지향하는 프론트엔드 특성상 고심해서 사용해야겠다.
위 과제관련 내용은 사실 과제할 때는 마음이 급해서 이유를 안찾아보고 바로 엎어버린 뒤 다른 방법으로 구현했다. 그런데 TIL 작성하면서 이걸 고민해보면 좋겠다는 생각에 파본건데 내 고정관념을 고치는 기회가 된 것 같다.