Ellis 11日目リアルタイムレッスンのjavascript
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」:外部からアクセスできません
コールバック関数:後で実行する関数(私が呼び出すのではなくシステム(ブラウザ)によって呼び出されます)
ブラウザは、最初のパラメータでイベントオブジェクトを渡します.target:現在のイベントが発生したターゲット
daynight.jsfunction 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)関数しか使わないので、それをエクスポートします.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()のようにチェーンしてコードを書くことができます.
新しいインデックス.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}" onclick="
event.preventDefault();
console.log(event.target.id);
for (let i = 0; i < topics.length; i++) {
if (topics[i].id === Number(event.target.id)) {
document.querySelector('article').innerHTML = '<h2>${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()で機能を停止し、リンクを移動しません.
ドアの周りをテーマにしているので[i].idはeventです.target.id(${topics[i].id
)と同じ場合、articleタグにinnerHTMLをトピックとして使用する[i].title, topics[i].bodyを充填します.これにより関数を指定し、以下でnav()呼び出し関数で実行します.
2.コーチの講義
https://codepen.io/bee-arcade/pen/EmvQax/78575ded5baba8aa15642037c298d9b4?editors=0010
module
htmlに次のコードを記述し、モジュールにインポートします.<script type="module" src="main.js"></script>
default module exportexport default randomSquare;
default module importimport randomSquare from './modules/square.js';
named module exportexport 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 importimport { 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 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です.
コンストラクタ
コンストラクション関数メソッドは、クラスによって生成されたオブジェクトを作成および初期化するための特別な方法です.
クラスには1つしか存在しません.
スーパーキーを使用して、親クラスのコンストラクション関数を呼び出すことができます.
プロトタイプメソッド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
静的メソッドとプロパティ
静的はクラスインスタンス化なしで呼び出され、インスタンスで呼び出されません.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
このバインディング
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メソッドを受け入れるボタンである.ただしbind(this)コマンドで「onclickにthisの現在値を書く」.現在の値はobject、すなわちclass Button自体です.コンストラクション関数内部のこれなので.
bind(this):クラスとして指定されたthis
this:クラス自体
code -> data
function:ダイナミック->変数:静的
本説明:https://codingapple.com/unit/es6-2-eventlistener-constructor-this/
静的メソッドまたはプロトタイプメソッドがこの値なしで呼び出されると、メソッドは定義されていません.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-structモードで書き換えると、初期にこの値にバインドされます.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]
このコードでnumberspush(数字)とnumbers.pop()の仕組みがわかりません.直訳するとnumbers=[1,2,3,4,5]配列の中で各要素1,2,3,4,5を押すのはどういう意味ですか?
またreturnnumber*numberという要素は数字なので数字形式のはずですが、結果は配列なので何なのか知りたいです.
->アリスと一緒にいた人が答えた.
これはMDN Webドキュメントの例で、公式ドキュメントを読むと役に立ちます.以上のコードは、mapプロセスで要素を追加および削除したときに返される配列が何であるかを知るコードです.
簡単に言えば、マッピングを適用する場合、ソース配列のサイズは固定されます.上の数字の並びの大きさは5ですよね?したがって、マッピングが開始されると、コルベック関数は番号の5番目の値にのみ適用されます.map中にpushは最初の5つの値にのみ適用されるため、result配列は数値の5番目の平方である.出力numbersは[1,2,3,4,5,1,2,3,4,5]を出力する.
要素を変更する場合も同様です.mapの始点では、数値配列のサイズは5です.したがってmapは合計5回コルベック関数を呼び出す.ただし、map内部ではnumbersの最後の要素が削除されています.
最初のコルベック関数の結果numbers=[1,2,3,4 empy],resultの最初の値は1であった.numbersの最初の値の二乗だからです.
2番目のコルベック関数の結果はnumber=[1,2,3,empty,empty]であり,結果の2番目の値は4である.numberの2番目の値の平方だからです.
3番目のコルベック関数はよく見る必要があります.コルベック関数を呼び出す前のnumber=[1,2,3,empty,empty]です.mapはこの配列を参照します.しかし、map内部にpopが最初に現れるとnumbers=[1,2,empty,empty]となる.ただし、mapが参照する配列は[1,2,3,empty,empty]であるため、戻り値は3番目の値の平方9になる.
numbersの4番目または5番目の値は空であるため、4番目からコルベック関数の結果も空になります.
returnnumber*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
Reference
この問題について(Ellis 11日目リアルタイムレッスンのjavascript), 我々は、より多くの情報をここで見つけました
https://velog.io/@chss3339/엘리스-11일차-실시간-강의-javascript
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
<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>
<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">
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();
}
}
<!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}" onclick="
event.preventDefault();
console.log(event.target.id);
for (let i = 0; i < topics.length; i++) {
if (topics[i].id === Number(event.target.id)) {
document.querySelector('article').innerHTML = '<h2>${topics[i].title}</h2>${topics[i].body}';
break;
}
}
">
${topics[i].title}
</a>
</li>`;
}
document.querySelector('nav ol').innerHTML = navTag;
}
nav();
</script>
</body>
</html>
https://codepen.io/bee-arcade/pen/EmvQax/78575ded5baba8aa15642037c298d9b4?editors=0010
module
htmlに次のコードを記述し、モジュールにインポートします.
<script type="module" src="main.js"></script>
default module exportexport default randomSquare;
default module importimport randomSquare from './modules/square.js';
named module exportexport 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 importimport { 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 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です.コンストラクタ
コンストラクション関数メソッドは、クラスによって生成されたオブジェクトを作成および初期化するための特別な方法です.
クラスには1つしか存在しません.
スーパーキーを使用して、親クラスのコンストラクション関数を呼び出すことができます.
プロトタイプメソッド
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
静的メソッドとプロパティ
静的はクラスインスタンス化なしで呼び出され、インスタンスで呼び出されません.
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
このバインディング
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メソッドを受け入れるボタンである.ただしbind(this)コマンドで「onclickにthisの現在値を書く」.現在の値はobject、すなわちclass Button自体です.コンストラクション関数内部のこれなので.bind(this):クラスとして指定されたthis
this:クラス自体
code -> data
function:ダイナミック->変数:静的
本説明:https://codingapple.com/unit/es6-2-eventlistener-constructor-this/
静的メソッドまたはプロトタイプメソッドがこの値なしで呼び出されると、メソッドは定義されていません.
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-structモードで書き換えると、初期にこの値にバインドされます.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]このコードでnumberspush(数字)とnumbers.pop()の仕組みがわかりません.直訳するとnumbers=[1,2,3,4,5]配列の中で各要素1,2,3,4,5を押すのはどういう意味ですか?
またreturnnumber*numberという要素は数字なので数字形式のはずですが、結果は配列なので何なのか知りたいです.
->アリスと一緒にいた人が答えた.
これはMDN Webドキュメントの例で、公式ドキュメントを読むと役に立ちます.以上のコードは、mapプロセスで要素を追加および削除したときに返される配列が何であるかを知るコードです.
簡単に言えば、マッピングを適用する場合、ソース配列のサイズは固定されます.上の数字の並びの大きさは5ですよね?したがって、マッピングが開始されると、コルベック関数は番号の5番目の値にのみ適用されます.map中にpushは最初の5つの値にのみ適用されるため、result配列は数値の5番目の平方である.出力numbersは[1,2,3,4,5,1,2,3,4,5]を出力する.
要素を変更する場合も同様です.mapの始点では、数値配列のサイズは5です.したがってmapは合計5回コルベック関数を呼び出す.ただし、map内部ではnumbersの最後の要素が削除されています.
最初のコルベック関数の結果numbers=[1,2,3,4 empy],resultの最初の値は1であった.numbersの最初の値の二乗だからです.
2番目のコルベック関数の結果はnumber=[1,2,3,empty,empty]であり,結果の2番目の値は4である.numberの2番目の値の平方だからです.
3番目のコルベック関数はよく見る必要があります.コルベック関数を呼び出す前のnumber=[1,2,3,empty,empty]です.mapはこの配列を参照します.しかし、map内部にpopが最初に現れるとnumbers=[1,2,empty,empty]となる.ただし、mapが参照する配列は[1,2,3,empty,empty]であるため、戻り値は3番目の値の平方9になる.
numbersの4番目または5番目の値は空であるため、4番目からコルベック関数の結果も空になります.
returnnumber*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/5acafb05f24445001b8d796dReference
この問題について(Ellis 11日目リアルタイムレッスンのjavascript), 我々は、より多くの情報をここで見つけました https://velog.io/@chss3339/엘리스-11일차-실시간-강의-javascriptテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol