이벤트버블링이란?

- 하위 DOM에 연결된 이벤트가 상위로 전파되는 것.

 

이벤트캡쳐란?

- 상위 DOM에 연결된 이벤트를 하위 DOM으로 전파시키는 것. addEventListener를 할 때 옵션객체에서 capture: true로 지정해서 수행한다.

 

이벤트위임(Delegation) 이란?

- 상위 DOM에서 하위 DOM의 이벤트를 제어하도록 위임하는 것. 이렇게 하면 DOM마다 이벤트를 연결하지 않아도 되서 코드 양과 이벤트리스너마다 할당될 메모리 사용량이 줄어들고, 버튼 등의 DOM의 추가와 삭제가 유연해진다.

 

event.stopPropagation()

- 상위나 하위 DOM으로의 이벤트 전파(버블링 or 캡쳐)을 막는다.


event.stopImmediatePropagation()

- 같은 DOM의 다른 이벤트들의 발생을 막는다.

 

event.preventDefault()

- 태그의 기본 이벤트 수행을 막는다. ex) a 태그의 href 이동 기능을 preventDefault로 방지

 

return false; (jQuery에서)

- event.stopPropagation + event.preventDefault (원하는 DOM의 한 이벤트만 동작시키고 싶을 때)

기본적으로 웹 컨텐츠는 모든 브라우저에서 같게 보여야 한다. 

하지만 IE와 같은 구버전 브라우저의 경우 지원하지 않는 기능들이 있고, 

현실적으로 구버전이나 특정 기능이 지원되지 않는 브라우저에서 어떻게 보이게 할 것인가에 대한

방법론으로 점진적 향상법과 우아한 성능저하법이 있다.

 

점진적 향상법

구버전 브라우저에서는 기본적인 컨텐츠 가독이 가능하도록 하면서,

최신버전 브라우저에서는 부가효과 및 기능 또한 가능하도록 개발하는 방법이다.

 

우아한 성능저하법

최신버전 브라우저를 기준으로 개발을 하고,

구버전 브라우저에서는 대체되는 다른 방법을 사용하거나 구버전이 지원되지 않는다는 메시지를 표시하는 방법이다.

 

 

점진적 향상법은 구버전(기본적인 컨텐츠 가독)에서 > 최신버전(부가효과 및 기능)

우아한 성능저하법은 최신버전에서 > 구버전(대체방법 사용 혹은 지원되지 않음 표시)로 정리하면 될 듯하다.

 

 

참고

https://blog.sonim1.com/214

'프론트엔드 > 이론' 카테고리의 다른 글

Content-Security-Policy 정의하기  (0) 2023.04.13

아래 코드는 간단하게 numbers 배열을 순회하면서 출력하는 코드이다. for - of 문을 사용하면 간결하게 쓸 수 있다.

const numbers = [10, 20, 30, 40, 50];

for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

// output:
// 10
// 20
// 30
// 40
// 50

 

 

아래 코드는 위 코드를 for - of를 사용해 간결하게 바꾼 코드이다. 파이썬의 for와 비슷하다.

 

 

const numbers = [10, 20, 30, 40, 50];

for (let number in numbers) {
  console.log(number);
}

// output:
// 10
// 20
// 30
// 40
// 50

 

 

그렇다면 for - in 은 무엇일까? 바로 오브젝트에서 key를 가져오는 것이다. 

line 7~9의 console.log는 doggy 오브젝트에서 키, 밸류, 키와 밸류 모두를 가져오는 다양한 방법을 보여준다.

그리고 가장 아래의 for - in 문은 for - in이 오브젝트에서 key 값을 가져온다는 것을 보여주기 위한 예시이다.

const doggy = {
  name: "멍멍이",
  sound: "멍멍",
  age: 2
};

console.log(Object.entries(doggy));  // dict.items() in python
console.log(Object.keys(doggy));     // dict.keys() in python
console.log(Object.values(doggy));   // dict.values() in python

// output:
// [Array[2], Array[2], Array[2]] <- iterate할 수 있는 배열
// ["name", "sound", "age"]
// ["멍멍이", "멍멍", 2]

for (let key in doggy) {
  console.log(`${key}: ${doggy[key]}`);
}

// output:
// name: 멍멍이
// sound: 멍멍
// age: 2

array라는 배열이 있고, 이 배열 안에 있는 모든 값들의 제곱을 얻어서 squared라는 배열에 저장하려고 한다.

이럴 때 여러 가지 방법이 있다.

 

1. for문

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const squared = [];
for (let i = 0; i < array.length; i++) {
  squared.push(array[i] * array[i]);
}

 

2. forEach문

- forEach는 매개변수에 함수를 넣어서, 배열에서 하나씩 꺼내 함수에 집어넣는다. forEach의 리턴 값은 undefined이므로, 함수 실행 결과를 새로운 배열에 저장하고 싶으면 squared.push()처럼 함수 내에서 넣어주어야 한다.

- 주석 처리한 부분은 화살표 함수로 쓴 것

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const squared = [];

array.forEach(function(n) {
  squared.push(n * n);
});

/*
array.forEach(n => {
  squared.push(n * n);
});
*/

 

3. map

- map은 배열에서 하나씩 꺼내서 괄호 안에 있는 함수에 집어넣은 결과를 리턴한다.

- 아래 코드처럼 화살표 함수를 사용해 square 함수를 정의한 후, map에 square 함수를 콜백으로 넣어줄 수도 있고,

- 간결하게 쓰려면 주석처럼 square 함수를 따로 정의 안 하고 바로 map 안에 넣어줄 수도 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const square = n => n * n;
const squared = array.map(square);

// const squared = array.map(n => n * n);

https://programmers.co.kr/learn/courses/30/lessons/49993

def solution(skill, skill_trees):
    answer = 0

    for skill_tree in skill_trees:
        buf = []
        for each_skill in skill_tree:
            if each_skill in skill:
                buf.append(each_skill)
        if buf == list(skill[:len(buf)]):
            answer += 1

    return answer

 

skill_trees에는 여러 스킬 트리들이 저장되어 있고, 이 각각의 스킬트리들이 skill의 순서대로 놓여있는지 판단해야 한다.

 

선후 관계의 순서가 지켜져야 하니까 처음에는 위상 정렬을 떠올렸다. 스킬트리는 실제로 위상 정렬의 대표적인 예시니까 말이다. 하지만 이 문제는 정렬의 문제가 아니라 제대로 정렬되어 있는지 판단하는 문제이므로 위상 정렬과는 달리 단순한 비교로 끝날 수 있다고 생각했다.

 

A와 B가 있을 때 B가 A 순서대로 놓여있는지 확인하기 위해서는 우선 B의 원소들이 A에 있는지를 확인해야 한다.

A에 존재하는 B의 원소들을 buf 라는 새로운 리스트에 추가한 뒤, 나중에 A와 buf를 비교해서 일치하면 True다.

단, buf ⊂ A 일 수 있으므로 A는 buf의 길이까지만 비교한다. 

'알고리즘 > 문자열' 카테고리의 다른 글

문자열 내 마음대로 정렬하기 (Python)  (0) 2020.07.03

2020. 07. 06

 

자바스크립트는 Java, Python와는 달리 비동기 언어이다.

쉽게 말해서 동기 방식은 시킨 대로 일을 하는 것이고, 비동기 방식은 동시에 일을 처리하고 대기하는 것이다.

즉, 내가 시킨 대로 일을 하지 않고 처리 시간이 짧은 일 먼저 끝나는 등 순서가 뒤죽박죽이 될 수 있다는 점을 유의해야 한다. 

예를 들어 1) console.log(1); 2) 파일 스트림 열어서 읽기 3) console.log(2);

이렇게 코딩을 했는데 1->3->2 이렇게 결과가 나올 수 있다.

 

이런 성질 때문에 에러가 발생할 수 있는데 이것은

동기적 함수

callback

promise

async / await 등으로 동기적으로 코딩할 수 있다.

 

https://programmers.co.kr/learn/courses/30/lessons/42839

 

문자열 형태로 주어지는 숫자로 만들 수 있는 모든 수에서 소수의 갯수를 찾는 문제이다. 이 문제를 두 개로 나누어보자. 

1) 문자열 형태로 주어지는 숫자로 만들 수 있는 모든 수를 구하기.

2) 소수를 찾기.

 

먼저 1)번을 보자. 문자열 형태로 주어지는 숫자란, "17", "011" 등을 말한다. 만약 "17"이 주어졌다면 "1", "7"로 만들 수 있는 모든 수를 구해야 한다.

문자열 형태든 무슨 형태든 일단 헷갈리니까  1과 7을 가지고 모든 수를 구하는 방법을 생각해보자.

모든 수를 구한다는 것은 가능한 모든 경우의 수를 구한다는 것이다. 순열을 구하는 방식으로 가능한 모든 경우의 수를 구할 수 있겠다. (조합이 아님)

그리고 매개변수가 문자열 형태로 주어지므로, "17"을 "1"과 "7"로 만들기 위해서 간단히 문자열을 리스트로 감싸주자. 

ex) list("17") --> ["1", "7"]

 

1)번 문제는 for문을 직접 돌며 재귀로 구할 수도 있고, itertools의 permutation을 이용해서 풀 수도 있다.

itertools 방식이 훨씬 깔끔하긴 하다.

 

2)번 소수를 찾는 문제에 대해 얘기해보자. 만약 작은 수부터 차례대로 소수를 구하는 문제였다면 소수 판별을 위해서 더 작은 소수로만 나눠보려고 했을 것이다.

하지만 이 문제에서는 "17"처럼 7보다 작은 소수인 2, 3, 5가 등장하지 않고 7이 제일 먼저 등장할 수도 있다.

그래서 자기보다 작은 소수로 나눠보는 방식으로 판별은 불가능하고(아니 복잡해지고), 1보다는 크고, 자신의 제곱근보다 같거나 작은 수로 나눠봐야 한다.

 

 

itertools를 사용하지 않은 코드

def dfs(n_list, checked, true_cnt, primes, selected):
    if true_cnt > 0:
        n = int("".join(selected))
        if is_prime(n):
            primes.add(n)
        if true_cnt == len(n_list):
            return

    for idx, ch in enumerate(checked):
        if not checked[idx]:
            checked[idx] = True
            selected.append(n_list[idx])
            dfs(n_list, checked, true_cnt+1, primes, selected)
            checked[idx] = False
            selected.pop()

    return primes


def solution(numbers):
    n_list = list(numbers)  # numbers의 길이를 알아내기 위해 리스트로 바꾼다.
    checked = [False for _ in n_list]
    return len(dfs(n_list, checked, 0, set(), []))

 

 

itertools를 사용한 코드

from itertools import permutations


def is_prime(n):
    prime = True
    if n < 2:
        prime = False
    for i in range(2, int(n ** 0.5)+1):  # n의 0.5제곱 = 제곱근
        if n % i == 0:
            prime = False
    return prime


def solution(numbers):
    answer = set()
    for i in range(1, len(numbers)+1):
        for p in permutations(numbers, i):
            n = int("".join(p))
            if is_prime(n):
                answer.add(n)
    return len(answer)

 

 

'알고리즘 > 브루트포스' 카테고리의 다른 글

16637. 괄호 추가하기 (2)  (0) 2020.05.12
16637번. 괄호 추가하기  (0) 2020.05.11
12100번. 2048 (Easy)  (0) 2020.05.04
17609번. 회문  (0) 2020.04.19
12100. 2048 (Easy)  (0) 2020.01.07

programmers.co.kr/learn/courses/30/lessons/42576

from collections import Counter


def solution(participant, completion):
    return list((Counter(participant) - Counter(completion)).keys())[0]

 

Level 1 문제라 그런지 코드가 매우 짧다. 파이썬으로 이 문제를 푸는 방법은 두 가지가 있다. 완전탐색, 그리고 딕셔너리끼리의 뺄셈.

 

완전탐색은 for문 안에 if ~ in 문을 넣어서 풀면 된다.

for c in completion:
    if c in participant:
        participant.remove(c)
return participant[0]

participant는 참가자 전원의 리스트이고 completion은 완주한 선수들의 리스트이다. participant보다 한 명이 적다.

졸려서 그랬는지 처음에는 participant를 순회하려고 했다. 그렇게 하면 participant를 순회하는 도중에 participant에서 remove를 하게 되어 에러가 발생한다. 리스트를 순회하는 도중에 값의 변경이 일어나면 안되기 때문이다.

대신에, completion을 순회하면서 그 값이 participant에 존재하면 participant에서 remove해주는 방식으로 해야 한다.

즉, 완주한 선수들의 이름을 하나씩 부르면서 참가자 전원 리스트에서 하나씩 소거해 나가는 것이다.

완주한 선수들의 이름을 모두 다 불렀는데도 참가자 리스트에 남아있는 선수가 바로 완주하지 못한 선수가 된다.

아무튼 설명이 길었지만 결론은 완전탐색 방식으로 하면 시간이 O(n^2)이 걸리게 되어 시간초과가 난다.

 

그럼 어떻게 해야 할까? 파이썬에서는 collections 모듈에서 Counter 함수를 제공한다.

Counter 함수에는 여러가지 사용법이 있는데, 매개변수로 리스트를 넣어주면 {값: 갯수}의 형태의 딕셔너리를 반환한다.

ex) collections.Counter(["leo", "kiki", "eden"]) ----> {"leo": 1, "kiki": 1, "eden": 1}

 

중요한 점이 여기서 등장한다. 원래 파이썬에서 set과는 달리 딕셔너리끼리 뺄셈을 지원하지 않는다.

그런데 Counter로 반환된 딕셔너리 모양의 오브젝트끼리는 더하기, 빼기, 차집합, 합집합이 가능하다.

따라서, 참가자 전원 Counter에서 완주한 선수 Counter를 빼 주면 이름이 중복되는 선수까지 다 계산해서 최종적으로 완주하지 못한 선수가 리턴된다.

맨 처음에 올린 코드처럼!

 

Counter 개념을 익혀놓자.

+ Recent posts