본문 바로가기
javascript

2024-02-26

by rewind 2024. 2. 26.

https://caniuse.com/

 

"let" | Can I use... Support tables for HTML5, CSS3, etc

CSS Initial Letter Method of creating an enlarged cap, including a drop or raised cap, in a robust way.

caniuse.com

 

위사이트에서 let var const 사용여부 확인(브라우저별 문법사용 확인사이트 , 브라우저 버전에 따라 지원여부가 다르다)

녹색 :지원 , 빨간색 : 지원x , 카키색 : 일부지원(가능하면 지양)

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <h1>Modern 자바스크립트에선 bind가 엄청나게 중요하다!</h1>
    <button id ="sunhe">눌러봐</button>
</body>
<script>
function fCk(pName){
    console.log("this-> " , this);
    alert(`${pName} 너가 눌렀어`);
    return;
}
// bind 아주중요 , 사용문법은 call과 똑같으나 실행이 다름
const mySunhe = document.querySelector("#sunhe");

// mySunhe.addEventListener("click" , undefined);
//mySunhe.addEventListener("click" , fCk("지은 정지!"));  // ? -> 실행 후 버튼 눌렀을때 실행되지 않는 이유?
var shJy = {who:"선혜지은"};
// bind는 내부적으로 해당함수를 만들어서 그 함수의 포인터(FP , 함수이름)를
// 되돌려준다!
mySunhe.addEventListener("click" , fCk.bind(shJy , "선혜"));  // ?


</script>

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <h1>Modern 자바스크립트에선 bind가 엄청나게 중요하다!</h1>
    <button id ="sunhe">눌러봐</button>
</body>
<script>
// document.write는 쓰는데 주의해야 한다
// document.write("<h1>난 최고의 프로그래머다</h1>");
function smWrt(msg){
    document.write(msg);
}
// smWrt("<h1>현재시간 9시 35분</h1>");
// document객체의 write 메소드 안에 this란 키워드가 사용되었다면 this가 가리키는 객체는? -> document

// 함수말고 참조를 해도 될거같은데? 해서 아래처럼 써본다
const yjWrt = document.write;   // 참조방식이라 이렇게 사용가능(전혀 문제 x)
yjWrt("<h1>현재시간 9시 38분</h1>"); // -> Illegal invocation : 문법적으로 문제(오류)는 없으나 불법 호출?

/*
function fCk(pName){
    console.log("this-> " , this);
    alert(`${pName} 너가 눌렀어`);
    return;
}
// bind 아주중요 , 사용문법은 call과 똑같으나 실행이 다름
const mySunhe = document.querySelector("#sunhe");

// mySunhe.addEventListener("click" , undefined);
//mySunhe.addEventListener("click" , fCk("지은 정지!"));  // ? -> 실행 후 버튼 눌렀을때 실행되지 않는 이유?
var shJy = {who:"선혜지은"};
// bind는 내부적으로 해당함수를 만들어서 그 함수의 포인터(FP , 함수이름)를
// 되돌려준다!
mySunhe.addEventListener("click" , fCk.bind(shJy , "지은"));  // ?

// bind를 call로 바꾸면 버튼을 누르지 않아도 실행하게 된다, 이후 클릭시엔 작동하지 않음(클릭시 undifined를 불러라)
mySunhe.addEventListener("click" , fCk.call(shJy , "선혜"));  // ?
*/
</script>

 

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <h1>Modern 자바스크립트에선 bind가 엄청나게 중요하다!</h1>
    <button id ="sunhe">눌러봐</button>
</body>
<script>
// document.write는 쓰는데 주의해야 한다
// document.write("<h1>난 최고의 프로그래머다</h1>");
function smWrt(msg){
    document.write(msg);
}
// smWrt("<h1>현재시간 9시 35분</h1>");
// document객체의 write 메소드 안에 this란 키워드가 사용되었다면 this가 가리키는 객체는? -> document

// 아래처럼 bind를 이해해서 사용한다면 회사에서 건들지 않는다?!
const yjWrt = document.write.bind(document); //
yjWrt("<h1>현재시간 9시 47분</h1>"); // -> Illegal invocation : 문법적으로 문제(오류)는 없으나 불법 호출?
// 함수말고 참조를 해도 될거같은데? 해서 아래처럼 써본다
//const yjWrt = document.write;   // 참조방식이라 이렇게 사용가능(전혀 문제 x)
//yjWrt("<h1>현재시간 9시 38분</h1>"); // -> Illegal invocation : 문법적으로 문제(오류)는 없으나 불법 호출?
// document.write 말고 yjWrt만으로 사용되면 window가 생략되어있다
//const yjWrt = document.write.call(document); // call을 써도 되나? -> X

/*
function fCk(pName){
    console.log("this-> " , this);
    alert(`${pName} 너가 눌렀어`);
    return;
}
// bind 아주중요 , 사용문법은 call과 똑같으나 실행이 다름
const mySunhe = document.querySelector("#sunhe");

// mySunhe.addEventListener("click" , undefined);
//mySunhe.addEventListener("click" , fCk("지은 정지!"));  // ? -> 실행 후 버튼 눌렀을때 실행되지 않는 이유?
var shJy = {who:"선혜지은"};
// bind는 내부적으로 해당함수를 만들어서 그 함수의 포인터(FP , 함수이름)를
// 되돌려준다!
mySunhe.addEventListener("click" , fCk.bind(shJy , "지은"));  // ?

// bind를 call로 바꾸면 버튼을 누르지 않아도 실행하게 된다, 이후 클릭시엔 작동하지 않음(클릭시 undifined를 불러라)
mySunhe.addEventListener("click" , fCk.call(shJy , "선혜"));  // ?
*/
</script>

 

function을class로.html 생성

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 자바스크립트에서 function키워드가 class키워드의 의미로도 사용됨
// 정확히는 생성자(Constructor)함수라고 하고 , 그냥 함수로 쓰일 때와 헷갈리니 잘 구분한다
function Saram(pName , pAge){
    this.name = pName;
    this.age = pAge;
    return this;
// 원래 function에는 return이 생략되어있는데 생성자로 쓰일때는 return this가 생략되어있다(안써도 된다!)
}

var juHee = new Saram("주희" , 23);
var junSuk = new Saram("준석" , 25);

console.log("체크1 : " , juHee);
console.log("체크2 : " , junSuk);

</script>

 

아래처럼 메소드추가도 가능

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 자바스크립트에서 function키워드가 class키워드의 의미로도 사용됨
// 정확히는 생성자(Constructor)함수라고 하고 , 그냥 함수로 쓰일 때와 헷갈리니 잘 구분한다
function Saram(pName , pAge){
    this.name = pName;  // 속성추가
    this.age = pAge;
    // 메소드
    this.getName = function(){  // 메소드추가
        return this.name;
    }
    return this;
// 원래 function에는 return이 생략되어있는데 생성자로 쓰일때는 return this가 생략되어있다(안써도 된다!)
}

var juHee = new Saram("주희" , 23);
var junSuk = new Saram("준석" , 25);

console.log("체크1 : " , juHee);
console.log("체크2 : " , junSuk.getName());
</script>

 

위에서 name , age , getName()을 매 객체마다 따로 작성해줘야 하는가? -> x

name , age는 상태값이기 때문에 각각 작성하는게 맞지만 getName같은 경우는 상태가 아닌

행위(비유하자면)?이기 때문에 따로 작성 할 필요가 없다

 

자바스크립트에서는 따로 선언을 해줘야 한다.(생성자 prototype)

생성자 prototype -> 메소드 공유(참조)

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 자바스크립트에서 function키워드가 class키워드의 의미로도 사용됨
// 정확히는 생성자(Constructor)함수라고 하고 , 그냥 함수로 쓰일 때와 헷갈리니 잘 구분한다
function Saram(pName , pAge){
    this.name = pName;  // 속성추가
    this.age = pAge;
    // 메소드를 이렇게 사용하면 메모리가 낭비된다
    // why?? 메소드는 특별한 상태를 저장하는게 아니기 때문에
    //(도구로써의 의미 , 필요한 순간에만 입력에 대해 출력결과물을 만들어 주면 됨)
    // 출력 결과물이 없거나 , 있다면 속성에 저장해서 상태를 저장하면 됨!
    this.getName = function(){  // 메소드추가
        return this.name;
    }
    return this;
// 원래 function에는 return이 생략되어있는데 생성자로 쓰일때는 return this가 생략되어있다(안써도 된다!)
}

var juHee = new Saram("주희" , 23);
var junSuk = new Saram("준석" , 25);

console.log("체크1 : " , juHee);
console.log("체크2 : " , junSuk.getName());
</script>

 

prototype은 생성자로 쓰일때만 의미가 있다?

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 자바스크립트에서 function키워드가 class키워드의 의미로도 사용됨
// 정확히는 생성자(Constructor)함수라고 하고 , 그냥 함수로 쓰일 때와 헷갈리니 잘 구분한다
function Saram(pName , pAge){
    this.name = pName;  // 속성추가
    this.age = pAge;
    // 메소드를 이렇게 사용하면 메모리가 낭비된다
    // why?? 메소드는 특별한 상태를 저장하는게 아니기 때문에
    //(도구로써의 의미 , 필요한 순간에만 입력에 대해 출력결과물을 만들어 주면 됨)
    // 출력 결과물이 없거나 , 있다면 속성에 저장해서 상태를 저장하면 됨!
    /*
    this.getName = function(){  // 메소드추가
        return this.name;
    }
    */
    return this;
// 원래 function에는 return이 생략되어있는데 생성자로 쓰일때는 return this가 생략되어있다(안써도 된다!)
}
// 메소드를 참조방식으로 공유하기 위해서는 prototype에 저장(선언)해야한다!
Saram.prototype.getName = function(){
    return this.name;
}
var juHee = new Saram("주희" , 23);
var junSuk = new Saram("준석" , 25);

console.log("체크1 : " , juHee);
console.log("체크2 : " , junSuk.getName());
</script>

 

prototype을 이용해 간략히 jQuery 핵심 코어 만들어보기

DOM (Document Object Model)

HTML문서 객체 기반 표현 방식?

Window - Document

 

jQuery

 

-> JS 문법에 일관성이 없다 라고 판단 , 일관성을 주기위해 jQuery를 만들었다.

제이쿼리는 자바스크립트 라이브러리이다(언어가 아니다!)

JavaScript >> jQuery(자바스크립트의 일부만 사용)

 

jQuery초간략만들어보기.html 생성

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// 간략히 jQuery핵심 코어 만들어보기
const myDom = function(cssSel){
    let domElems = document.querySelectorAll(cssSel);   //
    // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
    this.length = domElems.length;
    for(let i = 0; i < domElems.length; i){
        this[i] = domElems[i];
    }
    return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)

}
</script>

 

위 내용은 단순하게 JSON의 배열식 접근법(옮겨담기만 한다)

body추가(script 윗부분에 작성)

<body>
    <div class="coldSpring">조</div>
    <div class="coldSpring">한</div>
    <div class="coldSpring">봄</div>
    <div class="coldSpring">성배</div>
</body>

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <div class="coldspring">조</div>
    <div class="coldspring">한</div>
    <div class="coldspring">봄</div>
    <div class="coldspring">성배</div>
</body>
<script>
// 간략히 jQuery핵심 코어 만들어보기
const myDom = function(cssSel){
    let domElems = document.querySelectorAll(cssSel);   //
    // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
    this.length = domElems.length;
    for(let i = 0; i < domElems.length; i++){   // 그저 옮겨 담는것 뿐
        this[i] = domElems[i];
    }
    return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
}
const divs1 = new myDom("div");         // 태그로 가져오기
const divs2 = new myDom(".coldspring"); // 

console.log("체크1", divs1);
console.log("체크1", divs2);
</script>

 

const divs1 = myDom("div");

 

new를 지우면 window가 생략(console.log 찍어보면 window가 찍힌다)

 

new를 사용하지 않고 사용하려면? (new를 감추기 위해)

factory pattern (공장 패턴)

// 간략히 jQuery핵심 코어 만들어보기

const withoutNew = function(cssSel){
    return new myDom(cssSel);
}
const divs1 = withoutNew("div");         // 태그로 가져오기
const divs2 = withoutNew(".coldspring"); //

 

객체 생성을 다른 객체(메소드)에 위임

자바스크립트에서 변수명에 사용 가능한 특수문자 2개 $ , _

jQuery의 탄생 -> 변수명 $로 사용

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <div class="coldspring">조</div>
    <div class="coldspring">한</div>
    <div class="coldspring">봄</div>
    <div class="coldspring">성배</div>
</body>
<script>
// 간략히 jQuery핵심 코어 만들어보기
const $ = function(cssSel){
    return new myDom(cssSel);
}
const myDom = function(cssSel){
    let domElems = document.querySelectorAll(cssSel);   //
    // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
    this.length = domElems.length;
    for(let i = 0; i < domElems.length; i++){   // 그저 옮겨 담는것 뿐
        this[i] = domElems[i];
    }
    return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
}

// jQuery의 탄생 -> 변수명 $로 변경
const divs1 = $("div");         // 태그로 가져오기
const divs2 = $(".coldspring"); //

//const divs1 = new myDom("div");         // 태그로 가져오기
//const divs2 = new myDom(".coldspring"); // 

console.log("체크1", divs1);
console.log("체크1", divs2);
</script>

 

즉각실행함수 선언하기 -> 라이브러리에는 거의 꼭 보인다

(function(){
    alert("바로 실행 가능")
})();
또는 아래처럼
!function(){
    alert("바로 실행 가능")
}();

 

// 핵심 부분을 코드 블럭처리
(function(){

    const $ = function(cssSel){
        return new myDom(cssSel);
    }

    const myDom = function(cssSel){
        let domElems = document.querySelectorAll(cssSel);   //
        // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
        this.length = domElems.length;
        for(let i = 0; i < domElems.length; i++){   // 그저 옮겨 담는것 뿐
            this[i] = domElems[i];
        }
        return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
    }   
})();

 

이렇게 작성하고 실행시 $가 정의되어있지 않아서 에러 발생

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <div class="coldspring">조</div>
    <div class="coldspring">한</div>
    <div class="coldspring">봄</div>
    <div class="coldspring">성배</div>
</body>
<script>
// 간략히 jQuery핵심 코어 만들어보기
// 즉각 실행함수는 라이브러리에는 거의 꼭 보인다!
// 핵심 부분을 코드 블럭처리
// let $;  // 전역 변수 처리 -> window.$
(function(){
    const $ = function(cssSel){
        return new myDom(cssSel);
    }
    const myDom = function(cssSel){
        let domElems = document.querySelectorAll(cssSel);   //
        // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
        this.length = domElems.length;
        for(let i = 0; i < domElems.length; i++){   // 그저 옮겨 담는것 뿐
            this[i] = domElems[i];
        }
        return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
    }
    window.$ = $;
    // $->const $를 가리킴, 참조방식이어서 지역변수 $와 전역변수 $가 가리키는 곳이 같다
})();
// jQuery의 탄생 -> 변수명 $로 변경
const divs1 = $("div");         // 태그로 가져오기
const divs2 = $(".coldspring"); //

//const divs1 = new myDom("div");         // 태그로 가져오기
//const divs2 = new myDom(".coldspring"); // 

console.log("체크1", divs1);
console.log("체크1", divs2);
</script>

 

한가지 문제 발생

 

생성되는 객체가 공유할 메소드 작성시 항상 window.$=$ 아랫부분에 작성해야한다?

 

사용자가 직접 필요한 메소드들을 추가 가능하게 만들고 싶다?

jQuery 플러그인 만들기 -> myDom.prototype을 밖으로 빼주어야 가능하다

 

<!DOCTYPE html>
<meta charset="UTF-8">
<body>
    <div class="coldspring">조</div>
    <div class="coldspring">한</div>
    <div class="coldspring">봄</div>
    <div class="coldspring">성배</div>
</body>
<script>
// 간략히 jQuery핵심 코어 만들어보기
// 즉각 실행함수는 라이브러리에는 거의 꼭 보인다!
// 핵심 부분을 코드 블럭처리
// let $;  // 전역 변수 처리 -> window.$
(function(){
    const $ = function(cssSel){
        return new myDom(cssSel);
    }
    const myDom = function(cssSel){
        let domElems = document.querySelectorAll(cssSel);   //
        // 편리한 기능을 객체에 추가하기 위해서 가져온 값들을 생성되는 객체에 옮겨 담음
        this.length = domElems.length;
        for(let i = 0; i < domElems.length; i++){   // 그저 옮겨 담는것 뿐
            this[i] = domElems[i];
        }
        return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
    }
    window.$ = $;
    // $->const $를 가리킴, 참조방식이어서 지역변수 $와 전역변수 $가 가리키는 곳이 같다
    $.fn = myDom.prototype;    // 이게 밖으로 빠지면 , 사용자도 쉽게 메소드 추가 가능!

    // 생성되는 객체가 공유할 메소드, 라이브러리 제공자가 처음부터 제공(Built-In)하는 메소드
    myDom.prototype.msg = function(pArg){
        alert("메세지야 " + pArg);
    }
})();

// 이렇게 추가하는 것을 jQuery 플러그인 개발이라고 부름 -> 별거 없다
$.fn.tooSleepy = function(){
    alert("졸리다");
}
// jQuery의 탄생 -> 변수명 $로 변경
const divs1 = $("div");         // 태그로 가져오기
const divs2 = $(".coldspring"); //

divs2.tooSleepy();
divs1.msg("인호 분해");


//const divs1 = new myDom("div");         // 태그로 가져오기
//const divs2 = new myDom(".coldspring"); // 

console.log("체크1", divs1);
console.log("체크1", divs2);
</script>

 

제이쿼리 플러그인 직접 만들어보기

jQuery필수메소드.html 생성

 

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
// jQuery 핵심 코어부분(간략버전 , 흐름 이해하기)
(function(){
const $ = function(cssSel){
    return new myDom(cssSel);
}
const myDom = function(cssSel){
    let domElems = document.querySelectorAll(cssSel); 
    this.length = domElems.length;
    for(let i = 0; i < domElems.length; i++){
        this[i] = domElems[i];
    }
    return this;    // class의 의미로(생성자로 쓰겠다는 명시적 표현)
}
window.$ = $; // $->const $를 가리킴, 참조방식이어서 지역변수 $와 전역변수 $가 가리키는 곳이 같다
$.fn = myDom.prototype;    // 이게 밖으로 빠지면 , 사용자도 쉽게 메소드 추가 가능!
})();

// jQuery Plug-in 방식을 이용해서 필수 메소드 몇개만 직접 만들어보자

</script>

 

jquery 사이트 접속

ex) html 검색 -> attributes

제이쿼리 기본 규칙

1. 읽기 -> 매개변수 없을때

2. 전부쓰기 -> 매개변수값이 오면

3. 부분조작 -> 매개변수로 함수(콜백함수)

 

1. 읽기

 

2. 전부쓰기 , 부분조작

 

// jQuery Plug-in 방식을 이용해서 필수 메소드 몇개만 직접 만들어보자
// html() , innerHTML 속성을 편하게 제어해주는 메소드!
// html() -> 읽기 , html("asd") -> 전부쓰기 , html(function(pIdx , pVal){}) -> 부분조작

 

html메소드 직접 구현하기 , JS에는 overloading이 없다 , override는 존재

overloading -> 분기처리 해서 직접 구현 , 매개변수가 최대 1개 (없거나 , 문자열 , 메소드) 이기때문에 3가지 경우

// html메소드 직접 구현하기
$.fn.html = function(){
    // pArg가 안 넘어 왔을 때(pArg == undefined) -> 읽기 동작(여러개 있을 때는 무조건 첫번째)
    if(!pArg){
        return this[0].innerHTML;
    }
    // pArg에 문자열이 넘어왔을 때 , 전부 쓰기
    if(typeof(pArg) == 'string'){
        for(let i = 0; i < this.length; i++) {
            this[i].innerHTML = pArg;
        }
        return; // 끝내기
    }
    // pArg에 function(콜백함수)이 넘어왔을때 , 부분조작
    if(typeof(pArg) == "function" ){
        for(let i = 0; i < this.length ; i++){
            pArg(i , this[i].innerHTML);
        }
        return;     // 끝내기
    }
}

 

 

<meta charset="UTF-8">
<body>
    <div id="hian">희환</div>
    <div id="hian">인호</div>
    <div id="hian">소희</div>
    <div id="hian">초록</div>
</body>
<script>