ํ๋ก ํธ์๋ ๋ผ์ด๋ธ ์ฝ๋ฉ์ด๋ ํ์ดํธ๋ณด๋ ํ ์คํธ์์ ์์ฃผ ๋์ค๋ ๊ณผ์ ์ค ํ๋๊ฐ DOM API๋ฅผ ์ง์ ๊ตฌํํด๋ณด๋ ๋ฌธ์ ์ ๋๋ค. ๊ทธ์ค ๋ํ์ ์ธ ๊ฒ์ด document.getElementsByClassName์ ์ง์ ๋ง๋ค์ด๋ณด๋ผ๋ ๊ณผ์ ์ ๋๋ค. ์ด๋ฒ ๊ธ์์๋ ์ด ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ์ ๊ทผํ๋ฉด ์ข์์ง ๋ฒ ์ด์ค์ผ์ด์ค → ์ฃ์ง์ผ์ด์ค → ํจ์จ์ฑ → ๊ฐ๋ ์ฑ ์์๋ก ํ์ด๋ด ๋๋ค.
๋ฌธ์ ์ดํด
๋ชฉํ๋ ์ฃผ์ด์ง className์ ๊ฐ์ง ๋ชจ๋ ์์๋ฅผ ์ฐพ์ ๋ฐฐ์ด๋ก ๋ฐํํ๋ ํจ์์
๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก๋ DOM ํธ๋ฆฌ๋ฅผ ์ํํ๋ฉด์ ์กฐ๊ฑด์ ๋ง๋ ์์๋ฅผ ๋ชจ์ผ๋ฉด ๋ฉ๋๋ค.
function getElementsByClassName(className) {
const bodyChildrenEls = document.body.children;
const result = [];
const stack = [...bodyChildrenEls];
while (stack.length) {
const currentElement = stack.pop();
const currentElementChildren = currentElement.children;
for (let i = 0; i < currentElementChildren.length; i++) {
const currentChildrenEl = currentElementChildren[i];
stack.push(currentChildrenEl);
}
if (currentElement.classList.contains(className)) {
result.push(currentElement);
}
}
return result;
}
1. ๋ฒ ์ด์ค์ผ์ด์ค
- ์ต์์ ์์์๋ง ํด๋์ค๊ฐ ๋ถ์ ๊ฒฝ์ฐ
- DOM์ด ๋น์ด์์ ๋ (<body></body>)
- ์ฐพ๋ ํด๋์ค๊ฐ ์๋ ๊ฒฝ์ฐ
function getElementsByClassName(className) {
const bodyChildrenEls = document.body.children;
const result = [];
for (let i = 0; i < bodyChildrenEls.length; i++) {
const currentEl = bodyChildrenEls[i];
const currentElClassName = currentEl.className;
if (currentElClassName === className) {
result.push(currentEl);
}
}
return result;
}
2. ์ณ์ง ์ผ์ด์ค
- ํด๋์ค๊ฐ ์ฌ๋ฌ๊ฐ ๋ถ์ ๊ฒฝ์ฐ
- ์ค์ฒฉ๋ ์์์ผ ๊ฒฝ์ฐ
- ์ค์ฒฉ ๋์ค๊ฐ ๊น์ด์ง ๊ฒฝ์ฐ ... ๋ฑ ๊ทธ ์ธ์ ์ค์๊ฐ์ผ๋ก ์ถ๊ฐ๋๋ ์กฐ๊ฑด๋ค .. ?
2-1. ์ค์ฒฉ๋ ์์๊น์ง ์ํ (DFS / Stack)
๋ชจ๋ ํ์ ๋ ธ๋๊น์ง ํ์ํ ์ ์๋๋ก stack์ ๋์ ํฉ๋๋ค.
function getElementsByClassName(className) {
const bodyChildrenEls = document.body.children;
const result = [];
const stack = [...bodyChildrenEls];
while (stack.length) {
const currentElement = stack.pop();
const children = currentElement.children;
// ์์ ์์ ์คํ์ ์ถ๊ฐ
for (let i = 0; i < children.length; i++) {
stack.push(children[i]);
}
if (currentElement.className === className) {
result.push(currentElement);
}
}
return result;
}
โ
๋์: ์ค์ฒฉ ๊ตฌ์กฐ๊น์ง ํ์ ๊ฐ๋ฅ
โ ๋ฌธ์ : className์ด "a b"์ฒ๋ผ ์ฌ๋ฌ ๊ฐ์ผ ๊ฒฝ์ฐ ์ ํํ ์ผ์นํ์ง ์์
2-2 ๋ค์คํด๋์ค ๋์ ("a b")
function getElementsByClassName(className) {
const bodyChildrenEls = document.body.children;
const result = [];
const stack = [...bodyChildrenEls];
while (stack.length) {
const currentElement = stack.pop();
const children = currentElement.children;
for (let i = 0; i < children.length; i++) {
stack.push(children[i]);
}
// classList.contains๋ก ํน์ ํด๋์ค๋ง ๊ฒ์ฌ
if (currentElement.classList.contains(className)) {
result.push(currentElement);
}
}
return result;
}
โ ๋์: <div class="a b"> ์์ getElementsByClassName("a") ํธ์ถ ์ ์ ์์ ์ผ๋ก ๋งค์นญ๋จ
3. ํจ์จ์ฑ (์๊ฐ๋ณต์ก๋ & ๊ณต๊ฐ๋ณต์ก๋)
- ์๊ฐ๋ณต์ก๋: ๋ชจ๋ ๋ ธ๋๋ฅผ ํ ๋ฒ์ฉ ๋ฐฉ๋ฌธํ๋ฏ๋ก O(N) (N์ DOM ๋ ธ๋ ์)
- ๊ณต๊ฐ๋ณต์ก๋: ์คํ๊ณผ ๊ฒฐ๊ณผ ๋ฐฐ์ด์ ์ต๋ O(N)๊น์ง ์ ์ฅ ๊ฐ๋ฅ
4. ๊ฐ๋
์ฑ
๋ฉด์ ํ๋ฐ์๋ ์ฝ๋์ ๊น๋ํจ๋ ํ๊ฐ ์์๊ฐ ๋ ์ ์์
- stack → pendingNodes
- result → matchedElements
- currentElementChildren → children
+ ์ ์ฌ๋ฐฐ์ด ์ ๋ฆฌ
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฐ๋ค ๋ณด๋ฉด ๋ฐฐ์ด์ฒ๋ผ ๋ณด์ด๋๋ฐ ๋ฐฐ์ด์ ์๋ ๊ฐ๋ค์ ์ข
์ข
๋ง๋ฉ๋๋ค. ํํ ์ ์ฌ๋ฐฐ์ด(array-like) ์ด๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ๋ค์
๋๋ค. ์ด๋ฒ ๊ธ์์๋ ์ ์ฌ๋ฐฐ์ด๊ณผ ๋ฐฐ์ด์ ์ฐจ์ด๋ฅผ ์ ๋ฆฌํ๊ณ , ์ ์ฌ๋ฐฐ์ด์ ๋ฐฐ์ด๋ก ๋ณํํ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ ์ฌ๋ฐฐ์ด์ด๋?
์ ์ฌ๋ฐฐ์ด์ length ์์ฑ๊ณผ ์ธ๋ฑ์ค ๋ฒํธ๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ ๋๋ค. ๊ฒ๋ชจ์ต์ ๋ฐฐ์ด ๊ฐ์ง๋ง ์ค์ ๋ฐฐ์ด ๋ฉ์๋(map, forEach, filter ๋ฑ)๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ํ์ ์ธ ์์:
- ํจ์ ์์ arguments
- document.querySelectorAll ๊ฐ์ DOM API ๊ฒฐ๊ณผ๊ฐ
- HTMLCollection
function example() {
console.log(arguments); // [Arguments] { '0': 1, '1': 2, '2': 3 }
}
example(1, 2, 3);
const divs = document.querySelectorAll('div');
console.log(divs); // NodeList(3) [div, div, div]
๋ฐฐ์ด๊ณผ์ ์ฐจ์ด
๋ฐฐ์ด์ Array.prototype์ ์์๋ฐ์ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ธ ์ ์์ต๋๋ค. ๋ฐ๋ฉด ์ ์ฌ๋ฐฐ์ด์ ๋จ์ ๊ฐ์ฒด๋ผ ๋ฉ์๋๋ฅผ ์ง์ ์ฌ์ฉํ๋ฉด ์๋ฌ๊ฐ ๋ฉ๋๋ค.
const arr = [1, 2, 3];
arr.forEach(x => console.log(x)); // ์ ์ ๋์
const divs = document.querySelectorAll('div');
divs.forEach(x => console.log(x));
// TypeError: divs.forEach is not a function
์ ์ฌ๋ฐฐ์ด → ๋ฐฐ์ด ๋ณํ ๋ฐฉ๋ฒ
1. Array.from()
ES6์์ ๋์ ๋ ๊ฐ์ฅ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.
const divs = document.querySelectorAll('div');
const divArray = Array.from(divs);
divArray.forEach(div => console.log(div));
2. ์คํ๋ ๋ ์ฐ์ฐ์ [... ]
๋ ๊ฐ๊ฒฐํ๊ฒ ๋ฐฐ์ด๋ก ๋ง๋ค ์ ์์ต๋๋ค.
const argsToArray = (...args) => {
const arr = [...arguments];
console.log(arr);
};
argsToArray(1, 2, 3); // [1, 2, 3]
3. Array.prototype.slice.call()
ES6 ์ด์ ์ ๋ง์ด ์ฐ์ด๋ ๋ฐฉ์์ ๋๋ค.
function oldSchool() {
const arr = Array.prototype.slice.call(arguments);
console.log(arr);
}
oldSchool('a', 'b', 'c'); // ['a', 'b', 'c']
๊ทธ ์ธ ์ค์ ํ์ฉ ์์
DOM ์กฐ์
querySelectorAll๋ก ์ ํํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํด map์ ์ธ ์ ์์ต๋๋ค.
const buttons = document.querySelectorAll('button');
// ์ ์ฌ๋ฐฐ์ด ๊ทธ๋๋ก๋ map ๋ถ๊ฐ
// buttons.map(...) -> ์๋ฌ ๋ฐ์
// ๋ณํ ํ ์ฌ์ฉ
const texts = [...buttons].map(btn => btn.innerText);
console.log(texts);
ํจ์ ์ธ์ ์ฒ๋ฆฌ
arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ฐ๊พธ๋ฉด ํธ๋ฆฌํ๊ฒ ์กฐ์ํ ์ ์์ต๋๋ค.
function sum() {
const nums = Array.from(arguments);
return nums.reduce((acc, cur) => acc + cur, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
ํ์ ํ๋ณํ๊ธฐ
์ ์ฌ๋ฐฐ์ด์ธ์ง ๋ฐฐ์ด์ธ์ง ํท๊ฐ๋ฆด ๋๋ Array.isArray()๋ฅผ ์ฐ๋ฉด ๋ฉ๋๋ค.
Array.isArray([1, 2, 3]); // true
Array.isArray(document.querySelectorAll('div')); // false
'Frontend > ๐จ JS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Three.js ๋ก ์์ง์ด๋ ์ง๊ตฌ๋ณธ ๋ง๋ค๊ธฐ (0) | 2022.10.22 |
---|---|
[js library] AOS ์คํฌ๋กค ์ ๋๋ฉ์ด์ ๊ตฌํํ๊ธฐ (0) | 2022.08.10 |
[Javascript plugin] Masonry Layout ์ ์ฉํ๊ธฐ (0) | 2022.07.07 |
๋๊ธ