Set Object in JS

Set은 Javascript 표준 내장 객체로, 원시값(primitive)과 객체 참조 모두 유일한 값을 저장할 수 있다.

Array와 다르게 중복된 값을 허용하지 않는다.

 

const set = new Set();

console.log(typeof set); // object
console.log(set); // Set(0){ size : 0 }

 

Set의 type은 object이며, Set의 내장 메서드는 아래와 같다.

  1. Set.prototype.add() : set에 값 추가한다.
  2. Set.prototype.clear() : set을 비워준다.
  3. Set.prototype.delet() : set에서 특정 값을 삭제한다.
  4. Set.prototype.entries() 
  5. Set.prototype.forEach()
  6. Set.prototype.has()
  7. Set.prototype.keys()
  8. Set.prototype.values()

Set.prototype.add(value) : Set 값 추가하기

const set = new Set();
set.add(1);
set.add('string');
set.add(['a','r','r','a','y']);
set.add({ "0" : "object" });

console.log(set); // Set(4) { 1, 'string', Array(5), {...} }

set에는 객체(object), 배열(array), 숫자(number), 문자열(string)등 다양한 값을 추가할 수 있다.

 

Set.prototype.clear() : Set 비워주기

const set = new Set();
set.add(1);
set.add(2);

console.log(set); // Set(2) { 1, 2 }

set.clear();
console.log(set); // Set(0) {size : 0}

 

Set.prototype.delete(value) : Set  특정 값 삭제하기

return false or true ( 삭제 성공 시 true, 삭제 실패 시 false )

const set = new Set();
set.add(1);
set.add('string');
set.add(['a','r','r','a','y']);
set.add({ "0" : "object" });

console.log(set); // Set(4) { 1, 'string', Array(5), {...} }

set.delete("string"); // true
set.delete("string"); // false

console.log(set); // Set(3) { 1, Array(5), {...} }

 

Set.prototype.entries() : Set 순회하기

entries() method는 Set 객체의 각각의 요소를 삽입순서대로 [ 값, 값 ]의 형태로 가진 배열의 새로운 iterator 객체를 반환한다.

Set 객체에는 Map 객체처럼 Key가 존재하지 않는다. 그러나 Map 객체의 API와 비슷하게 유지하기 위해, 각각의 "요소"는 "키"와 "값"자리에 같은 값을 가지게 된다. 결과적으로 entries는 [ 값, 값 ] 형태의 배열을 반환한다. 

 

const set = new Set();

set.add(1);
set.add(2);
set.add(3);

const iterator = set.entries();

console.log(iterator);
// output : SetIterator {1 => 1, 2 => 2, 3 => 3}

for(const entry of iterator ){
	console.log(entry);
}

// output 
// [1, 1]
// [2, 2]
// [3, 3]

console.log(iterator); // SetIterator {}
// output : undefined

for .. of .. 문법으로 entries() 함수로 반환된 iterator를 순회하면서 console.log()로 찍어본 결과 [ 값, 값 ] 의 형태로 set에 추가했던 1, 2, 3이 순서대로 나오는 것을 확인할 수 있다. 

이후 iterator를 다시 console.log()로 확인해보면 해당 iterator가 비어있는 것을 확인할 수 있다.

이것은 iteration protocols 를 확인해보면 더 자세히 알 수 있다.

쉽게 생각하면 iterator는 한번 가리켰던 value는 다음 value를 가리키게 되는 순간 다시 바라볼 수 없다. 즉 한번 순회하면 다시 반복할 수 없는 것이다.

 

 iterator에 우리가 set에 값을 넣은 순서대로 [1,1], [2,2], [3,3]이 들어있다. 처음에 iterator는 [1,1]을 가리키고있다. 다음에 [2,2]를 가리키게 되면 iterator에서 [1,1]은 사라지고 [2,2], [3,3]만 남아있다. 

아래 코드를 통해서 확인할 수 있다.

const set = new Set();
set.add(1);
set.add(2);
set.add(3);

for(const entry of iterator){
    console.log(entry);
    console.log(iterator);
}

// output
// [1,1]
// SetIterator {2 => 2, 3 => 3}

// [2,2]
// SetIterator {3 => 3}

// [3,3]
// SetIterator {}

 

Set.prototype.forEach(callbackFunction) : Set 반복하기

set의 forEach method는 Array의 forEach method와 동일하다.

set의 value들을 순차적으로 한번씩 순회한다. forEach대신 위에서 사용했던 for..of를 사용해서도 set을 반복할 수 있다.

const set = new Set();

set.add(1);
set.add(2);
set.add(3);

set.forEach((s)=>{
	console.log(s);
});

// output : 
// 1
// 2
// 3

for(const entry of set){
    console.log(entry);
}

// output : 
// 1
// 2
// 3

 

Set.prototype.has(value) : Set에 특정 value 존재 여부 확인하기

Set 객체에 특정 value가 존재하는지 확인하기 위한 함수이다. 특정 value가 존재한다면 true, 존재하지 않는다면 false를 반환한다.

const set = new Set();
set.add(1);
set.add(2);
set.add(3);

console.log(set.has(1)); // true
console.log(set.has(4)); // false

 

Set.prototype.values() : Set의 value iterator 반환한다. 

Set 객체의 value들에 대한 iterator를 반환한다.

const set = new Set();
set.add(1);
set.add(2);
set.add(3);

let valueIterator = set.values();

console.log(valueIterator); // SetIterator {1, 2, 3}

for(const entry of valueIterator){
	console.log(entry);
}

// output
// 1
// 2
// 3

valueIterator = set.values();

console.log(valueIterator.next()); // {value: 1, done: false}
console.log(valueIterator.next()); // {value: 2, done: false}
console.log(valueIterator.next()); // {value: 3, done: false}
console.log(valueIterator.next()); // {value: undefined, done: true}

next()는 iterator의 method이다. 참고

 

Set.prototype.keys() : Set의 key iterator 반환한다. 

❗️Set object에서는 keys() 메서드와 values() 메서드는 동일한 기능을 한다. 왜냐하면 Set 객체의 경우 value 값을 키값으로 사용하기 때문에 [ key, value ] 쌍의 값으 [ value, value]와 동일하기 때문이다.

const set = new Set();
set.add(1);
set.add(2);
set.add(3);

console.log(set.keys());
// output : SetIterator {1, 2, 3, 'string'}
728x90

VanillaJS를 이용하여 Tooltip Input Component 만들기

/**
 * (required) type : number | text
 * (required) id : text
 * (optional) blank : boolean
 * (optional) blankMessage : text
 * (optional) disabled: boolean
 * (optional) regExp : tooltip message view condition : regExp ( 양끝 / 제거한 값을 넣어줘야함 )
 * (optional) regExpMessage : tooltip message
 * (optional) frontLabel : text
 * (optional) backLabel : text
 * * */
class TooltipInput extends HTMLElement {
  /**
     * constructor : 최초 실행 생성 Method
     * */
  constructor() {
    super();
    this.render();
  }

  /**
     * render() : 해당 tag에 넣을 html tag를 rerendering한다.
     * */
  render() {
    this.innerHTML = this.getTemplate();
  }

  /**
     * 해당 컴포넌트가 mount될 때 불러진다.
     * * */
  connectedCallback() {
    const attrList = this.attributes;
    const input = this.getElementsByClassName('tooltip-input');

    let front = attrList.frontLabel;
    let back = attrList.backLabel;

    if (front === undefined) {
      front = this.getElementsByClassName('front');
      front[0].className = 'display-none';
    }
    if (back === undefined) {
      back = this.getElementsByClassName('back');
      back[0].className = 'display-none';
    }

    /**
         * input eventListener
         * * */
    input[0].addEventListener('input', (e) => {
      const { blank } = e.path[3].attributes;
      const { blankMessage } = e.path[3].attributes;
      const rex = e.path[3].attributes.regExp;
      const rexMessage = e.path[3].attributes.regExpMessage;

      /* input.value 빈칸인 경우 */
      if (e.currentTarget.value.length === 0) {
        if (blank !== null && blank !== undefined && (blank.value === 'true' || blank.value === '')) {
          const tooltipMessage = this.getElementsByClassName('tooltip-message');
          tooltipMessage[0].className = 'tooltip-message';
          if (blankMessage === undefined) {
            tooltipMessage[0].innerHTML = '값을 입력해주세요.';
          } else {
            tooltipMessage[0].innerHTML = blankMessage.value;
          }

          console.log(tooltipMessage[0].classList);
        }
      } else {
        /* input.value 빈칸이 아닌 경우 */
        /* attr 에 정규식이 있는 경우 */
        if (rex !== null && rex !== undefined) {
          const regExp = new RegExp(rex.value);
          console.log(!regExp.test(e.currentTarget.value));
          if (!regExp.test(e.currentTarget.value)) {
            // 정규식 만족 X
            const tooltipMessage = this.getElementsByClassName('tooltip-message');
            tooltipMessage[0].className = 'tooltip-message';
            if (rexMessage !== undefined && rexMessage !== null) {
              tooltipMessage[0].innerHTML = rexMessage.value;
            } else {
              tooltipMessage[0].innerHTML = '조건을 만족하지 않습니다.';
            }
          } else if (blank !== null && blank !== undefined && (blank.value === 'true' || blank.value === '')) {
            const tooltipMessage = this.getElementsByClassName('tooltip-message');
            tooltipMessage[0].className = 'tooltip-message display-none';
          }
        }
      }
    });

    /**
         * disabled 값이 존재하는지 체크
         * disabled 값이 존재 == true 인경우 input의 disabled attr 활성화
         * disabled 값이 존재하지 않거나 ( null ) false인 경우 input의 disabled attr 비활성화(삭제)
         * * */

    if (attrList.getNamedItem('disabled') !== null && (attrList.getNamedItem('disabled').value === 'true' || attrList.getNamedItem('disabled').value === '')) {
      /**
             * disabled 값이 true인 경우 input의 disabled attr 활성화
             * */
      input[0].setAttribute('disabled', 'disabled');
    }

    /**
         * input값이 빈칸인 경우 확인해야하는지 체크
         * blank === true && blankMessage === undefined => "입력값이 필요합니다."
         * blank === true && blankMessage !== undefined => "blankMessage"
         * * */

    if (attrList.getNamedItem('blank') !== null && (attrList.getNamedItem('blank').value === 'true' || attrList.getNamedItem('blank').value === 'blank')) {
      /**
             * blank === true
             * * */
      if (input[0].value === '') {
        const tooltipMessage = this.getElementsByClassName('tooltip-message');
        if (attrList.getNamedItem('blankMessage') !== null) {
          // blank === true && blankMessage === undefined => "입력값이 필요합니다."
          tooltipMessage[0].innerHTML = attrList.getNamedItem('blankMessage').value;
        } else {
          // blank === true && blankMessage !== undefined => "blankMessage"
          tooltipMessage[0].innerHTML = '입력값이 필요합니다.';
        }
      }
    }
  }

  /**
     * 해당 tag에 attributes를 observing한다.
     * * */
  static get observedAttributes() {
    return ['type', 'id', 'blank'];
  }

  /**
     * getTemplate() : rendering될 html tag에 대한 template이다.
     * * */
  getTemplate() {
    let frontLabel;
    let backLabel;

    const type = this.attributes.type.value || '';
    const id = this.attributes.id.value || '';

    frontLabel = this.attributes.frontLabel !== undefined ? this.attributes.frontLabel.value : '';
    backLabel = this.attributes.backLabel !== undefined ? this.attributes.backLabel.value : '';

    return `
            <style>
                input[type="number"]::-webkit-outer-spin-button,
                input[type="number"]::-webkit-inner-spin-button {
                    -webkit-appearance: none;
                    margin: 0;
                }
                
                div{
                    width : 100%;
                }
                
                .tooltip-input{
                    width : 100%;
                    height : 26px;
                    border-radius: 4px;
                    box-shadow: inset 0 3px 2px 0 rgba(49,49,49,0.13);
                    border : solid 1px #b4b4b4;
                    background: #fff;
                    padding-left : 12px;
                    
                    /* font */
                    font-style : normal;
                    font-size : 12px;
                    font-family: 'Roboto';
                    color : #6e6e6e;
                }
                
                .label-text{
                    font-style : normal;
                    font-size : 12px;
                    font-weight : 600;
                    font-family: 'Roboto';
                    color : #6e6e6e;
                }
                
                .disabled{
                    background: #e6e6e6;
                }
                
                .display-none{
                    display : none;
                }
                
                .display-block{
                    display: block;
                }
                
                .tooltip-message{
                    width : auto;
                    height : 16px;
                    border : 1px solid #ede381;
                    background: #f7f2c0;
                    color : #9d870e;
                    
                    white-space: nowrap;
                    
                    position : absolute;
                    right : -15px;
                    top : -32px;
                    padding : 7px 13px 7px 18px;
                    z-index : 30; 
                }
                
                .tooltip-box{
                    min-width : 50px;
                    display: block;
                    position : relative;
                }
                
                .tooltip-box-container{
                    width : 100%;
                    display: flex;
                    flex-direction: row;
                    align-items: center;
                }
                
                .front{
                    width : auto;
                    white-space: nowrap;
                    margin-right : 10px;
                }
                
                .back{
                    width : auto;
                    white-space: nowrap;
                    margin-left : 25px;
                }
                
            </style>
            
            <div class="tooltip-box-container">
                <label for="${id}" class="label-text front">${frontLabel}</label>
                <div class="tooltip-box">
                    <input id="${id}" type="${type}" class="tooltip-input"/>
                    <span class="tooltip-message display-none"></span>
                </div>
                <label for="${id}" class="label-text back">${backLabel}</label>
            </div>
        `;
  }

  /**
     * 해당 컴포넌트가 unmount될 때 불리어 진다.
     * * */
  disconnectedCallback() {

  }

  /**
     * attributes가 수정된다면 수정된 갯수만큼 불리어 진다.
     * * */
  attributeChangedCallback(name, oldValue, newValue) {

  }
}

/**
 * tool-tip 이라는 tag가 customElements에 있는가? 없다면 새롭게 define하라는 코드로,
 * 동일 tag가 2번 define하면 오류가 날 수 있으므로, component가 여러차례 사용되면서 define되는 것을 막기 위한 용도이다.
 * * */

// Define the new web component
if ('customElements' in window) {
  customElements.define('tooltip-input', TooltipInput);
}

과정과 더 자세한 설명은 다음에 쓸 예정

 

참고 블로그 링크 

 

728x90

'Language > Javascript' 카테고리의 다른 글

[ Javascript ] Set Object  (0) 2022.11.02
[ Javascript ] setTimeout, setInterval  (0) 2022.07.27
[ Javascript ] Array.prototype Methods  (0) 2022.03.08
[ Javascript ] async/await  (0) 2022.03.07
[ Javascript ] Promise  (0) 2022.03.06

setTimeout()

setTimeout() 메서드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정한다.

어떤 코드를 바로 실행하지 않고 일정 시간 기다린 후 실행해야하는 경우가 존재한다. 이러한 경우 setTimeout 함수를 사용하여 첫 번째 인자로 받은 실행할 코드를 두번째 인자로 받은 delay time 후에 실행한다. 

delay time은 밀리초(ms) 단위이다. 

var timeoutID = setTimeout( function [, delaty, arg1, arg2, ... ] );
var timeoutID = setTimeout( function [, delay]);
var timeoutID = setTimeout( code [, delay ]);

 

매개변수

function

지정된 delay 시간이 지난 후 실행할 function을 의미한다.

 

code 

함수 대신 문자열을 지정하는 대체 구문으로, 타이머가 만료될 때 코드로 컴파일 후 실행한다. ➡️ 사용을 별로 권장하지 않음.

 

delay  ( optional )

주어진 함수 또는 코드를 실행하기 전에 기다릴 시간이다. 생략하거나 0으로 지정할 경우 "즉시" 실행한다는 뜻이다.

 

arg1, ... , argN

function에 전달할 추가 매개변수이다.

 

반환값

timeoutID는 양의 정수로 setTimeout()이 생성한 타이머를 식별할 때 사용한다. 해당 값을 clearTimeout()에 전달하면 타이머를 취소할 수 있다.

 


setInterval()

setInterval() 메서드는 주기적으로 발생해야 하는 부분이 있을 때 사용한다. 예를 들어 어떤 API로부터 변경된 데이터를 주기적으로 받아온다던가, 특정 부분을 주기적으로 업데이트를 해줘야 하다던가 할때 사용할 수 있다.

setInterval() 메서드는 해당 객체 ID를 반환하므로 setTimeout() 메서드의 clearTimeout()과 같이 clearInterval() 함수를 호출하여 제거할 수 있다. 

 

setInterval() 함수는 어떤 코드를 일정한 시간 간격을 두고 반복해서 실행하고 싶을 때 사용한다. 첫 번째 인자로 실행할 코드를 담고, 두 번째 인자로 반복 주기 시간을 밀리초(ms)단위로 받는다.

 

매개변수, 반환값은 setTimeout과 거의 동일하다.

728x90

'Language > Javascript' 카테고리의 다른 글

[ Javascript ] Set Object  (0) 2022.11.02
[ VanillaJS ] Create Tooltip Input Component using VanillaJS  (0) 2022.10.12
[ Javascript ] Array.prototype Methods  (0) 2022.03.08
[ Javascript ] async/await  (0) 2022.03.07
[ Javascript ] Promise  (0) 2022.03.06

Array.prototype.at(index);

Array.prototype.at(index); method는 parameter로 반환받고 싶은 element의 index값을 넘겨주며, parameter로 음수와 정수 모두 사용가능하며 음수인 경우 배열의 뒤에서부터 indexing한다.

const array = ["apple", "banana", "lemon"];

console.log(array.at(0)); // "apple"
console.log(array[0]); // "apple"

console.log(array.at(-1)); // "lemon"
console.log(array[array.length -1]); // "lemon"

 

Array.prototype.concat(elements);

Array.prototype.concat(elements); method는 기존 배열에 인자로 들어온 요소나 배열을 합하여 새로운 배열을 반환하는 메서드이다.

- 기존 배열을 변경하지 않는다.

- 인자가 추가된 새로운 배열을 반환한다.

const array = ["apple", "samsung"];
const array2 = ["LG"];

console.log(array.concat(array2)); // [ "apple", "samsung", "LG" ]
console.log(array); // ["apple", "samsung"]

const array3 = array.concat(array2);
console.log(array3); // ["apple", "samsung", "LG"]

 

Array.prototype.copyWithin(target, start [,end]);

Array.prototype.copyWithin(target, start [,end]); method는 배열의 일부를 얕게 복사한 뒤, 동일한 배열의 다른 위치에 덮은 후 해당 배열을 반환한다. 이때 배열의 길이는 변경되지 않는다.

const array = ['a','b','c','d','e','f'];
const array2 = ['a','b','c','d','e','f','g'];
array.copyWithin(2,5); // ['a','b','f','d','e','f']
array2.copyWithin(1,2,5); // ['a','c','d','e','e','f','g']

console.log(array); // ['a','b','f','d','e','f']
console.log(array2); // ['a','c','d','e','e','f','g']

 

Array.prototype.entries()

Array.prototype.entries(); method는 배열의 각 인덱스에 대한 키/값 쌍을 가지는 새로운 Array Iterator 객체를 반환한다.

const array = ["apple", "lemon", "orange", "strawberry"];
const iterator = array.entries();

console.log(iterator.next().value)); // [0, "apple"] => Array
console.log(iterator.next().value)); // [1, "lemon"] => Array
console.log(iterator.next().value)); // [2, "orange"] => Array
console.log(iterator.next().value)); // [3, "strawberry"] => Array
console.log(iterator.next().value)); // undefined

 

Array.prototype.every(function)

Array.prototype.every(function) method는 배열의 모든 요소가 주어진 판별함수를 통과하는지 테스트하는 메서드로, 반환값은 boolean이다.

const isTenOver = (element) => element > 10;
const array = [11,12,14,20];

array.every(isTenOver); // true

 

Array.prototype.fill(value [, start [ , end] ] );

Array.prototype.fill() method는 배열의 시작부터 끝 이전까지 정적인 값 하나로 모두 채우는 메서드이다.

* parameter

- value : 배열을 채울 값

- start : 시작 인덱스 기본값 0

- end : 끝 인덱스 기본값 array.length

const array = [1,2,3,4,5];

array.fill(5);
console.log(array); // [5,5,5,5,5]

array.fill('a',2,4); // [5,5,'a','a',5]

 

Array.prototype.filter( callback(element [ , index [ , array ] ] ) [ , thisArg ]);

Array.prototype.filter() 메서드는 매개변수로 주어진 callback 함수의 테스트를 통과한 요소들만 모아 새로운 배열을 반환한다. 

- callback : true 를 반환하면 요소를 유지 false를 반환하면 요소를 버린다. 

- element : 현재 처리할 요소

- index : 현재 처리할 요소의 인덱스

- array : filter를 호출한 배열

- thisArg : callback을 실행할 때 this로 사용하는 값

const number = [1,2,3,"4",5,6];
const newNumber = number.filter( (element) => typeof element === "number" );

console.log(newNumber); // [1,2,3,5,6]

 

Array.prototype.find( callback [ , thisArg ] )

Array.prototype.find() 메서드는 주어진 판별함수를 만족하는 첫 번째 요소의 값을 반환한다. 해당하는 요소가 없다면 undefined를 반환한다.

const array = ["a",3,4,"b"];
const found = array.find((element) => typeof element === "number");

console.log(found); // 3

const fruits = [
	{ name : "banana", quantity : 3 },
    { name : "apple", quantity : 5 },
    { name : "lemon", quantity : 2 }
];

function findApple(fruit){
	return fruit.name === "apple";
}

const Apple = fruits.find(findApple);
console.log(Apple); // {name: 'apple', quantity: 5}

 

Array.prototype.findIndex( callback(element [ , index [ , array ] ]) [ , thisArg ] );

Array.prototype.findIndex() 메서드는 주어진 판별함수를 만족하는 첫 번째 요소의 인덱스를 반환한다. 배열의 첫 번째 요소가 존재하지 않는다면 -1을 반환한다.

const fruits = [
	{ name : "banana", quantity : 3 },
    { name : "apple", quantity : 5 },
    { name : "lemon", quantity : 2 }
];

function findApple(fruit){
	return fruit.name === "apple";
}

function findCherry(fruit){
	return fruit.name === "cherry";
}

const Apple = fruits.findIndex(findApple);
console.log(Apple); // 1

const Cherry = fruits.findIndex(findCherry);
console.log(Cherry); // -1

 

Array.prototype.forEach(callback(currentValue [ , index [ , array ]] ) [ , thisArg ] );

Array.prototype.forEach(); method는 주어진 함수를 배열 요소 각각에 대해 실행한다.

const array = ["apple", "banana", "lemon", "cherry"];
array.forEach( fruit => console.log(fruit) );
// "apple"
// "banana"
// "lemon"
// "cherry"

 

Array.prototype.includes(valueToFind [, fromIndex ]);

Array.prototype.includes(); method는 배열이 특정 요소를 포함하고 있는지를 판별한다. 반환값은 boolean이다.

- valueToFind : 찾고자하는 요소

- fromIndex : 검색을 시작할 위치 

const array = ["apple", "banana", "lemon"];
array.includes("apple"); // true
array.includes("cherry"); // false
array.includes("apple",0); // true
array.includes("apple",2); // false
array.includes("lemon",1); // true

 

Array.prototype.indexOf(searchElement [, fromIndex])

Array.prototype.indexOf(element, [fromIndex]); 메서드는 배열에서 지정된 요소를 찾을 수 있는 첫 번재 인덱스를 반환하고 존재하지 않으면 -1을 반환한다.

const array = [ "a", "b", "c", "d", "e" ];
console.log( array.indexOf("e") ); // 4
console.log( array.indexOf("f") ); // -1
console.log( array.indexOf("a",2) ); // -1

 

Array.isArray(obj);

Array.isArray() 메서드는 메서드의 인자가 Array인지 아닌지를 판별한다. 반환값은 Boolean이다.

const array = [1,2,3];

Array.isArray(array); // true
Array.isArray(3); // false

[ + ] 계속 추가할 예정

Array.prototype.join()

Array.prototype.map()

...

push()

pop()

reduce()

reverse()

shift()

slice()

some()

sort()

unshift()

toString()

values()

 

 

728x90

+ Recent posts