엘리스 11일차 월요일 실시간 강의 javascript

치즈말랑이·2022년 4월 18일
0

엘리스

목록 보기
12/47
post-thumbnail

1. 이고잉님 강의

addEventListener

<html>
    <body>
        <input type="button" id="btn1" value="egoing">
        <input type="button" id='btn2' value="duru">
        <script>
            function l(evt) {
                alert(evt.target.value);
            }
            function l2() {
                alert(2);
            }

            document.querySelector('#btn1').addEventListener('click', l)
            // document.querySelector('#btn1').addEventListener('click', l2)
            document.querySelector('#btn2').addEventListener('click', l)
        </script>
    </body>
</html>

addEventListener로 click 이벤트 속성을 부여할 수 있다.

module import export jQuery

index.html

<script type="module">
    import {dayNight} from './daynight.js';
    console.log(dayNight);
    function listener(evt) {
        if(evt.target.value === 'night') {
            dayNight('night');
            evt.target.value = 'day';
        } else {
            dayNight('day');
            evt.target.value = 'night';
        }
    }
    document.querySelector('#dayNightBtn').addEventListener('click', listener);
</script>

<input type="button" value="night" id="dayNightBtn">

type="module" : 외부에서는 접근불가
콜백함수: 나중에 실행되는 함수 (내가 아니라 시스템(브라우저)가 호출)
브라우저가 첫번째 파라미터로 event객체를 넘겨준다. target: 현재 이벤트가 발생한타겟

daynight.js

function night() {
    document.querySelector('body').style.backgroundColor = 'black';
    // $('body').css('background-color', 'black').css('color', 'white');
    // $('body').css('background-color', 'black');
    document.querySelector('body').style.color = 'white';
    // $('body').css('color', 'white');
    // $('a').css('color', 'white').css('text-decoration', 'underline');
    let as = document.querySelectorAll('a');
    for(let i = 0; i<as.length; i++) {
        as[i].style.color = 'white';}
}
function day() {
    document.querySelector('body').style.backgroundColor = 'white';
    document.querySelector('body').style.color = 'black';
    let as = document.querySelectorAll('a');
    for(let i = 0; i<as.length; i++) {
        as[i].style.color = 'black';}
}
export function dayNight(mode) {
    if(mode === 'night') {
        night();
    } else {
        day();
    }
}

html파일에서 dayNight(mode) 함수만 사용할거라서 이걸 export 해준다. html에서는 import {dayNight} from '.daynight.js'; 로 함수를 불러온다.

주석처리한거는 jQuery인데, html head에다가 <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script> 넣으면 사용할 수 있다. 문법이 약간 다르고 .css().css() 처럼 chain해서 코드를 작성할 수 있다.

새로운 index.html

<!DOCTYPE html>
<html>
    <head>
        <script>
            let topics = [
                {id:1, title:'html', body:'html is ..'},
                {id:2, title:'css', body:'css is ..'},
                {id:3, title:'js', body:'js is ..'}
            ]
            
        </script>
    </head>
    <body>
        <h1><a href="index.html" onclick="
            event.preventDefault();
            document.querySelector('article').innerHTML = '<h2>Welcome</h2>' + 'Hello, WEB';
            ">WEB</a></h1>
        <nav>
            <ol>
                <!-- <li><a href="1.html">html</a></li>
                <li><a href="2.html">css</a></li>
                <li><a href="3.html">javascript</a></li> -->
            </ol>
        </nav>
        <article>
            <h2>Welcome</h2>
            Hello, WEB
        </article>

        <script>
            // function nav() {}
            // let nav = function() {}

//             function callback(e){
//                 console.log(e);
//                 return `<li>${e}</li>`;
//             }
//              nums.map(callback).join('');
//              callback=function(e){
//                  console.log(e);
//                  return `<li>${e}</li>`;
//              }
//              nums.map(callback).join('');
//              nums.map((e)=>{
//              return `<li>${e}</li>`;
//              }).join('');
//              nums.map(e=>{
//              return `<li>${e}</li>`;
//              }).join('');
//              nums.map(e=>`<li>${e}</li>`).join('');

            let nav = () => {
                let navTag = '';
            for(let i = 0; i<topics.length; i++) {
                navTag += `<li>
                    <a href="/read/${topics[i].id}" id="${topics[i].id}"token interpolation">${topics[i].title}</h2>${topics[i].body}';
                                break;
                            }
                        }
                    ">
                            ${topics[i].title}
                        </a>
                    
                    </li>`;
            }
            document.querySelector('nav ol').innerHTML = navTag;
            
            }

            nav();
        </script>
    </body>
</html> 

여기서 href는 그냥 써놓은거고 preventDefault()로 기능을 정지시켜서 링크이동 안한다.
for문을 돌아서 topics[i].id가 event.target.id (${topics[i].id)와 같다면 article태그안에 innerHTML로 topics[i].title, topics[i].body를 채워넣는다. 함수를 그렇게 지정해놓고 아래에 nav()로 함수호출해서 실행시킨다.

2. 코치님 강의

https://codepen.io/bee-arcade/pen/EmvQax/78575ded5baba8aa15642037c298d9b4?editors=0010

module

html에 다음 코드를 작성하여 모듈로 import 해온다

<script type="module" src="main.js"></script>

default module export

export default randomSquare;

default module import

import randomSquare from './modules/square.js';

named module export

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return {
    length: length,
    x: x,
    y: y,
    color: color
  };
}

named module import

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
import { name } from './modules/square.js';

모듈 설명: https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Modules
깃허브 예시: https://github.com/mdn/js-examples/blob/master/modules/basic-modules/main.js

arrow funciton

function car(a, b) {
	return a+b
}
var car = function(a, b) {
	return a+b
}
var car = (a, b) => {
	return a+b
}

class

객체를 생성하기 위한 템플릿

클래서 정의방법 2가지

1. class 선언

class Rectangle {
	constructor(height, width) {
      this.height = height;
      this.width = width;
    }
}

함수는 정의하기전에 호출할 수 있지만, 클래스는 반드시 정의한 후에 사용할 수 있다.

2. class 표현식

//unnamed
let Rectangle = class {
	constructor(height, width) {
    	this.height = height;
      	this.width = width;
    }
};

console.log(Rectangle.name);
// 출력: "Rectangle"

//named
let Rectangle = class Rectangle2 {
	constructor(height, width) {
    	this.height = height;
      	this.width = width;
    }
};
console.log(Rectangle.name);
// 출력: "Rectangle2"

클래스에서 {}로 묶여있는 부분은 body 이다.

constructor(생성자)

constructor 메서드는 class로 생성된 객체를 생성하고 초기화 하기 위한 특수한 메서드 이다.
클래스안에 한개만 존재할 수 있다.

부모 클래스의 constructor를 호출하기위해 super 키워드를 사용할 수 있다.

프로토타입 메서드

class Rectangle {
	constructor(height, width) {
    	this.height = height;
      	this.width = width;
    }
}
// Getter
get area() {
	return this.calArea();
}
// 메서드
calcArea() {
	return this.height * this.width;
}

const square = new Rectangle(10,10);
console.log(square.area); // 100

static 메서드와 속성

static은 클래스의 인스턴스화 없이 호출되며 인스턴스에서는 호출할 수 없다.

class Point {
	constructor(x, y) {
    	this.x = x;
      	this.y = y;
    }
  
  	static displayName = "Point";
	static distance(a, b) {
    	const dx = a.x - b.x;
      	const dy = a.y - b.y;
      
      	return Math.hypot(dx, dy);
    }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance;    // undefined
p2.displayName; // undefined
p2.distance;    // undefined


console.log(Point.displayName);      // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755

this 바인딩

class Menu {
  constructor() {
    this.buttonContainer = document.querySelector('#menu');
    this.statusBar = document.querySelector('#status-bar');
    
    this.showButtonClicked = this.showButtonClicked.bind(this);
    
    this.buttons = [
      new Button(this.buttonContainer, 'A', this.showButtonClicked),
      new Button(this.buttonContainer, 'B', this.showButtonClicked),
      new Button(this.buttonContainer, 'C', this.showButtonClicked)
    ];
  }
  
  showButtonClicked(buttonName) {
    this.statusBar.textContent = buttonName + ' was clicked';
  }
}

class Button {
  constructor(containerElement, text, onClickedCallback) {
    this.containerElement = containerElement;
    this.text = text;
    this.onClickedCallback = onClickedCallback;
    
    this.onClick = this.onClick.bind(this);
    
    const button = document.createElement('button');
    button.textContent = text;
    button.addEventListener('click', this.onClick);
    this.containerElement.append(button);
  }
  
  onClick() {
    this.onClickedCallback(this.text);
  }
}

new Menu();

this.onClick = this.onClick.bind(this); 이 코드를 작성하기 전까지 onClick() 함수 내부의 this는 addEventListener메서드를 받는 button이였다. 하지만 bind(this)로 "onclick에서 this의 현재값을 써라" 라고 명령했다. this의 현재값은 object, 즉 class Button 그 자체이다. constructor 내부의 this이기 때문이다.

bind(this): 이 클래스의 this로 지정
this: 클래스 그 자체

code -> data
function:동적 -> 변수:정적

this 설명: https://codingapple.com/unit/es6-2-eventlistener-constructor-this/

static 메서드나 프로토타입 메서드가 this 값 없이 호출될때 메서드 안에서 undefined가 된다.

class Animal {
	speak() {
    	return this;
    }
  	static eat() {
    	return this;
    }
}

let obj = new Animal();
obj.speak(); // the Animal object
let speak = obj.speak;
speak(); // undefined

Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined

non-strict mode로 재작성하면 초기 this값에 바인딩된다.

function Animal() {}
Animal.prototype.speak = function() {
	return this;
}

Animal.eat = function() {
	return this;
}
44
let obj = new Animal();
let speak = obj.speak;
speak(); // global object (in non–strict mode)

let eat = Animal.eat;
eat(); // global object (in non-strict mode)

forEach()

arr.forEach(item, index, array);
// 마지막 인자 array는 forEach()를 호출한 배열로 거의 사용 안함

https://goddino.tistory.com/132

map()

배열.map((요소, 인덱스, 배열) => { return 요소 });
// array 요소가 추가되는 경우 
const numbers = [1, 2, 3, 4, 5]; 
const result = numbers.map(number => { 
  numbers.push(number); 
  return number * number; 
}); 
console.log(result); 
// [1, 4, 9, 16, 25]; 

// array 요소가 수정되는 경우 
const numbers = [1, 2, 3, 4, 5]; 
const result = numbers.map(number => { 
  numbers.pop(); 
  return number * number; }
); 
console.log(result); 
// [1, 4, 9, empty × 2];

출처: https://7942yongdae.tistory.com/48 [프로그래머 YD]

이 코드에서 numbers.push(number) 와 numbers.pop()가 동작하는 원리를 모르겠습니다. 직역하면 numbers= [1,2,3,4,5] 배열에다가 각 원소 1 , 2, 3, 4, 5를 push한다는건데 무슨말인가요??
그리고 return number*number 이거는 원소가 숫자니까 숫자형태가 나와야할거같은데 결과는 배열이나와서 그이유도 궁금합니다

-> 같이 엘리스 하는 분의 답변:
MDN 웹문서에 나오는 예제코든데 공식문서 읽어보시면 도움될거 같아요. 위 코드는 map 도중에 원소를 추가 및 제거할때 반환하는 배열이 어떻게 되는지 알아보는 코드입니다.

간단하게 말하자면 map을 적용할때 원본 배열의 크기는 고정입니다. 위에서 numbers 배열의 크기는 5죠? 따라서 map을 한번 시작하면 numbers의 5번째 값까지만 콜벡함수가 적용됩니다. map 도중에 push를 해도 처음 다섯 개의 값에 대해서만 적용되기 때문에 result 배열은 numbers의 5번째까지 값들의 제곱입니다. numbers를 출력하면 [1,2,3,4,5,1,2,3,4,5]가 출력될 것입니다.

요소가 수정되는 경우도 마찬가지입니다. map의 시작점에서 numbers 배열의 크기는 5입니다. 따라서 map 에서 총 다섯 번의 콜벡함수가 호출됩니다. 그런데 map 내부에서 numbers의 마지막 요소가 삭제되고 있습니다.
첫번째 콜벡함수 결과 numbers = [1,2,3,4,empy]가 될 것이고 result의 첫번째 값은 1이 됩니다. numbers의 첫번째 값의 제곱이니깐요.

두번째 콜벡함수 결과 numbers=[1,2,3,empty,empty]가 될 것이고 result의 두번째 값은 4가 됩니다. number의 두번째 값의 제곱이니깐요.
세번째 콜벡함수는 좀 자세히 볼 필요가 있습니다. 콜벡함수 호출 직전의 number = [1,2,3,empty,empty]입니다. map은 이 배열을 참조합니다. 그런데 map 내부에서 pop이 먼저 일어나면 numbers = [1,2,empty,empty]가 됩니다. 하지만 map이 참조하는 배열은 [1,2,3,empty,empty]이므로 리턴값은 세번째 값의 제곱인 9가 됩니다.
numbers의 네,다섯번째 값이 empty이므로 네번째부터는 콜벡함수 결과 또한 empty가 됩니다.

return number*number 이거는 원소가 숫자니까 숫자형태가 나와야할거같은데 결과는 배열이나와서 그이유도 궁금합니다

이거에 대한 답변을 드리자면 반환값은 배열의 원소에 콜벡함수를 적용한 결과값입니다. 그러니깐 배열의 모든 원소에 콜벡함수를 적용한게 map 메소드라고 생각하시면 돼요!

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map

reduce()

배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);

https://www.zerocho.com/category/JavaScript/post/5acafb05f24445001b8d796d

profile
공부일기

0개의 댓글