1. 클래스

클래스 , 익명클래스 , 기명클래스, 동적생성 클래스

생성 방법에 따라 이름을 나눠보았습니다

클래스

class Student{
    constructor(name){

        // 생성자는 1개이상 정의 될 수 없고 생략할 경우 암묵적으로 정의, 
        this.group = 1;
        this.name = name
        // 암묵적으로 this 반환 중
    }

    // 메소드
    introduce(){
        console.log(`저는 ${this.group}반 학생 ${this.name} 입니다!`);
    }
    // 암묵적으로 this 반환 하는 중 
    
}
//  결과 

console.log(new Student());            // constructor 실행 ,  Student { group: 1, name: undefined }
console.log(typeof Student);         // function
console.log(Student === Student.prototype.constructor);        // true
console.log(Student.prototype.introduce); // 클래스 내부에 정의한 메소드는 클래스, prototype에 저장 ,Array.prototype 처럼

익명클래스

// 1. 익명클래스 표현식     클래스 이름이 없으니까 생성자선언 + 바로사용 하는 용도 ??  (일회용)
let Tutor = class {
    teach(){
        console.log(`이해되시나요`);
    }
}
console.log('여기');
console.log(Tutor);       //  [class Tutor]
console.log(new Tutor());   //    Tutor {}
new Tutor().teach();    //   이해되시나요

기명클래스

// 2. 기명클래스 표현식
let Tutee = class MyTutee {
    learn(){
        console.log('이해 했습니다');
        console.log(MyTutee);   
    }
}

// console.log(MyTutee);      // 클래스 밖에서 사용불가
new Tutee().learn();     
//   이해 했습니다
//  [class MyTutee]

동적 생성 클래스

// 3. 클래스 동적 생성
function makeTutee(message) {  
    return class {
        feedback(){
            console.log(message);
        }
    }
    
}

let secondTutee = makeTutee("10점 맍점");
new secondTutee().feedback();       // 10점 맍점

get set

class Product{

    constructor(name, price){
        this.name = name;
        this.price = price;
    }

    get name(){
        console.log('get name동작');
        return this._name;   
        // 언더바를 붙이지 않으니 무한루프에 빠져버린다 .. 
        // this.name (언더바없음) 을 호출 할때 get (같은이름)의 함수가 호출된다고 한다. (작동원리)
        // 그래서 프로퍼티 이름을 일부러 다르게 써서 무한루프 방지를 한다.

    }

    get price(){
        console.log('get price동작');
        return this._price;  
    }

    set name(value){
        console.log('set name동작');
        this._name = value;  
    }
    set price(value){
        console.log('set price동작');
        if(value < 0){
            console.log('가격은 음수가 아닙니다');
            this._price = 0;
            return;
        }
        this._price = value;  
    }

}

// get은 프로퍼티를 읽으려 할 때   set은 프로퍼티에 값을 할당하려 할 때  자동으로 실행 됨

let phone = new Product('전화기', 23000);         // set 동작    음수처리 기능이 있다 !!!
console.log(phone.name + ',' + phone.price);           // get 동작

// 결과
set name동작
set price동작
get name동작
get price동작
전화기,23000

클래스 상속

class Animal{
    constructor(name, weight){
        this.name = name;
        this.weight = weight;
    }

    eat(foodWeight){
        this.weight = this.weight + foodWeight;
        console.log(`${this.name}(은)는 ${foodWeight}kg의 식사를 하고 ${this.weight}kg이 되었습니다.`);
    }

    move(lostWeight){
        if(this.weight > lostWeight)
        this.weight = this.weight - lostWeight;
        console.log(`${this.name}(은)는 움직임으로 인해 ${lostWeight}kg 감량되어 ${this.weight}kg이 되었습니다.`)
    }
}

let animal = new Animal('동물', 30);

animal.eat(1);   //  동물(은)는 1kg의 식사를 하고 31kg이 되었습니다.
animal.move(0.5);  //   동물(은)는 움직임으로 인해 0.5kg 감량되어 30.5kg이 되었습니다.

class Human extends Animal{

    develop(language){
        console.log(`${this.name}(은)는 ${language}로 개발을 합니다. 정말 즐겁습니다^.^`);
    }
}

let human = new Human('수강생', 70);

human.eat(2);    //   수강생(은)는 2kg의 식사를 하고 72kg이 되었습니다.
human.move(1);     //    수강생(은)는 움직임으로 인해 1kg 감량되어 71kg이 되었습니다.

human.develop('javascript') 
//    수강생(은)는 javascript로 개발을 합니다. 정말 즐겁습니다^.^

class Tiger extends Animal{
    attack(target){
        console.log(`${this.name}은 ${target}을 공격합니다`);
    }

    move(target){
        super.move(0.1);  // 부모 move 실행 
        this.attack(target);   // Tiger 만의 기능
    }
}

let tiger = new Tiger("호랭이", 90);
tiger.move('사슴');    
//   호랭이(은)는 움직임으로 인해 0.1kg 감량되어 89.9kg이 되었습니다.
//   호랭이은 사슴을 공격합니다

class Deer extends Animal{
    constructor(name, weight, leglength){
        super(name, weight); // 부모 생성자, 반드시 this 호출 전에 super 사용
        this.leglength = leglength;
    }

    hide(place){
        console.log(`${this.name} 은 ${place}에 숨습니다`);
    }
}

let deer = new Deer('사슴2', 100, 15);
deer.hide('나무밑');   //   사슴2 은 나무밑에 숨습니다

2. 화살표 함수 ( 보기 어려워 죽겠다 )

함수의 형식을 파괴해버리고

매개변수와 반환값만 적어주는 엄청 축약된 형태의 함수 입니다

(매개변수) ⇒ ( { 반환값 } ) ;

기본 구문 (MDN 문서 내용 중)

`(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 다음과 동일함:  => { return expression; }

// 매개변수가 하나뿐인 경우 괄호는 선택사항:
(singleParam) => { statements }
singleParam => { statements }

// 매개변수가 없는 함수는 괄호가 필요:
() => { statements }`
// 객체 리터럴을 반환하는 경우 소괄호로 감싸주는것이 좋다.    
const createUser = (id, name) => ({id, name});
console.log(createUser(1,'이효리'));
//   { id: 1, name: '이효리' }

// 고차함수에 인수로 전달 가능하고 일반 함수 표현식 보다 간결하여 자주 사용
// map : 배열 요소 전체를 대상으로 콜백 함수 호출후 반환값들로 구성된 새로운 배열 반환
console.log([1,2,3,4,5].map(val => val * 10));
//   [ 10, 20, 30, 40, 50 ]    map 은 배열순회 함수

// 화살표 함수는 this를 가지지 않는다!!!!
// 객체 리터럴 (대문자가 아니니 생성자는 아님)
let theater = {
    store : '건대점',
    titles : ['어벤져스', '겨울왕국', '스파이더맨', '라이언킹', '알라딘'],

    // this는 자신의 상위를 뜻한다 ??
    // 외부에서 값을 가져온다 ?? 상위타입을 가져온다 ??

    // 일반함수에서의 this 는 전역(global) 을 가리킨다 ??

    // forEach : 배열 순회 함수
    showMovieList(){
        this.titles.forEach(
            title => console.log(this.store + ' : ' + title)
        );
    }
}

theater.showMovieList();
//  건대점 : 어벤져스
//  건대점 : 겨울왕국
//  건대점 : 스파이더맨
//  건대점 : 라이언킹
//  건대점 : 알라딘

// 화살표 함수는 new와 함께 호출할 수 없다

const arrowFunc = () => {};
// new arrowFunc();           //TypeError: arrowFunc is not a constructor
console.log(arrowFunc.hasOwnProperty('prototype')); //  false
console.log(arrowFunc.constructor);     // [Function: Function]

// 화살표 함수는 arguments 지원하지 않음    화살표함수 너무 보기힘드네요 무슨뜻일까요 이게
(function(){
    const arrowFunc = () => console.log(arguments);

    arrowFunc(3,4)
}(1,3));
//    [Arguments] { '0': 1, '1': 3 }

// 1,3 지우니까 출력이 안됨

MDN 문서 내용 중

화살표 함수는 자신의 arguments 객체가 없지만, 대부분의 경우에 나머지 매개변수가 좋은 대안입니다:

`function foo(n) { var f = (...args) => args[0] + n; return f(2); }

foo(1); // 3`

이전 예제를 '나머지 매개변수' 라는 좋은 대안으로 고친 코드

// 화살표 함수는 arguments 지원하지 않음    화살표함수 너무 보기힘드네요 무슨뜻일까요 이게
(function(){
    // const arrowFunc = () => console.log(arguments);
    const arrowFunc = (...args) => console.log(args);

    arrowFunc(3,4)   // 함수 실행을 하는 문장이긴한데 (위에 문장으로 실행하면) 매개변수 무시되고 있는듯
}(1,3));

// [ 3 , 4 ]

3. 심볼 (Symbol) 중요도 하

MDN 문서 내용 중

"심볼" 데이터 형식은 값으로 익명의 객체 속성(object property)을 만들 수 있는 특성을 가진 원시 데이터 형식(primitive data type)입니다

심볼  데이터 형식은 고도로 특화된 용도로 쓰이며, 범용성은 현저히 떨어집니다. 심볼 의 인스턴스에 L값(L-value)을 할당할 수 있고 식별자로 이용할 수 있습니다. 그게 전부입니다. 적용할 수 있는 연산자도 없습니다.

대놓고 쓰지 말라고 적어 놓은 듯한 데요. 허허허허허

중요하지 않은것 같으니 패스

//Symbol << 외부코드에서 접근 불가능 , 값도 덮어쓸 수 없는 숨김 프로퍼티를 만들 수 있다.

let student = {
    name : '홍길동'
}

let id = Symbol('id');
student[id] = 500; 

// student  [key] = value   로 프로퍼티 추가하는 문법
let name = 'name';
student[name] = '이대엽';

console.log(Object.keys(student));
console.log(student[id]);
console.log(student);

let student2 = {
    name : '홍길동',
    age : 15,
    [id] : 2 // 객체 리터럴 안에서 사용할 경우 대괄호를 사용해 심볼형 키를 만들 수 있다.
}

console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);
// 프로퍼티 이름 출력하는 반복문
for(let key in student2) console.log(key); // for in 반복문에서 키가 심볼인 경우 배제된다.
console.log(student2[id]);

console.log(Object.getOwnPropertySymbols(student));
console.log(Object.getOwnPropertySymbols(student2));

// 심볼은 유일무이하다 !!
let symbol1 = Symbol('mySymbol');
let symbol2 = Symbol('mySymbol');

console.log(symbol1 === symbol2);   // false

console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);

// Symbol.for(key) 를 사용해 심볼을 전역 레지스트리에 만들고 읽는다. 
// 그래서 동일한 이름으로 존재하지 않으면 새로운 심볼을 만들고, 이름이 있다면 심볼을 다시 읽어온다

// 음 그래서 심볼의 용도가 무엇일까 ?????????   >>     나중에 찾아보기
let symbol = Symbol.for('id1');
let id1 = Symbol.for('id1');
console.log(symbol === id1);  // true

// 이름이 같더라도 값이 항상 다르므로 이름이 같을때 값도 같기를 원한다면 전역 레지스트리에 생성해서 사용해야함

4. 이터레이터 , 이터러블

/* 01_iterable (이터러블)
ES6 이전의 순회 가능한 데이터 컬렉션, 배열, 문자열, 유사 배열 객체, DOM 컬렉션 등은 
통일 된 규약 없이 for문, for...in문, forEach 메서드 등 다양한 방법으로 순회 할 수 있었다.

ES6에서는 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 
for...of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화했다.
*/  // 이터레이션 프로토콜

let range = {
    from : 1,
    to : 5
};

range[Symbol.iterator] = function () {
    return {
        current : this.from,
        last : this.to,

        // done : Iterator(반복자)가 마지막 반복 작업을 마쳤을 경우 true
        // value : Iterator(반복자)으로부터 반환되는 모든 자바스크립트 값
        next(){ // 인덱스마다 호출되는 함수
            if (this.current <= this.last){
                return {done : false , value : this.current++};     
            } else{
                return {done : true};
            }
        }
    }
}

// TypeError: range is not iterable
for(let num of range){
    console.log(num);
}

// 유사 배열 객체
let arrayLike = {
    0: '배열같은',
    1: '배열아닌',
    2: '배열이다',
    length : 3
}

// 배열 메서드 사용 불가
console.log(arrayLike);   
// { '0': '배열같은', '1': '배열아닌', '2': '배열이다', length: 3 }

console.log(typeof arrayLike);
//  object

// console.log(arrayLike.pop());

// 메서드는 유사 배열 객체(array-like object)나 
// 반복 가능한 객체(iterable object)를 얕게 복사해 새로운Array 객체를 만듭니다.
let arr = Array.from(arrayLike);
console.log(arr.pop());
// 배열이다

let arr2 = Array.from(range);
console.log(arr2);
//  [ 1, 2, 3, 4, 5 ]

// from 설명
// (iterable: Iterable<any> | ArrayLike<any>   ,     mapfn: (v: any, k: number) => any, thisArg?: any)
          // 이터러블 | 유사배열 ,  매개변수 => 리턴값                 화살표좀 작작써라!!!!!!!!!!   
let arr3 = Array.from(range, num => num * num);
console.log(arr3);
//  [ 1, 4, 9, 16, 25 ]

5. 스프레드 문법 ( 나머지 매개변수 ) [ …args]

// 스프레드 문법, 전개 문법

// max 안에는 숫자들만 들어갈 수 있다.
console.log(`가장 큰 값 : ${Math.max(10,20,30)}`); // 가장 큰 값 : 30

// max 안에는 배열은 들어갈 수 없다.
let arr = [10, 20, 30];
console.log(`가장 큰 값 : ${Math.max(arr)}`);   가장 큰 값 : NaN

// Spread!!!!!!!!!!!!!!!!!!!
console.log(`가장 큰 값 : ${Math.max(...arr)}`);  // 가장 큰 값 : 30

let arr1 = [10, 20, 30];
let arr2 = [100, 200, 300];

console.log(`가장 큰 값 : ${Math.max(...arr1, ...arr2)}`);    // 가장 큰 값 : 300
console.log(`가장 큰 값 : ${Math.max(...arr1, ...arr2, 500000)}`);
//  가장 큰 값 : 500000

let merged = [0, ...arr, 2, arr2]  //  (일부러 이상하게 합침)
console.log(merged);   //   [ 0, 10, 20, 30, 2, [ 100, 200, 300 ] ]

let str = "JavaScript";
console.log([...str]);
/**
[
  'J', 'a', 'v', 'a',
  'S', 'c', 'r', 'i',
  'p', 't'
]
*/

console.log(Array.from(str));
/**
[
  'J', 'a', 'v', 'a',
  'S', 'c', 'r', 'i',
  'p', 't'
]
*/

구조 분해 distructuring-assignment

MDN 문서 내용 중

구조 분해 할당  구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식입니다.

 

배열 구조 분해

// 배열 구조 분해 할당

let nameArr = ['길동', '홍'];

// let firstName = nameArr[0]
// let lastName = nameArr[1]

let [firstName, lastName] = nameArr;

console.log(firstName);   // 길동
console.log(lastName);    //  홍

let [firstName2, lastName2] = '길 동'.split(' ');

console.log(firstName2);    //길
console.log(lastName2);     //동

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ');
// 쉼표를 사용해서 필요하지 않은 배열요소는 버릴 수 있다
let [firstName3,      ,lastName3] = ['firstName', 'middleName', 'lastName'];
console.log(firstName3);        //firstName
console.log(lastName3);         //lastName

// 대입 연산자를 기준으로 우측에는 모든 이터러블 가능, 좌측에는 객체 프로퍼티도 가능
let user = {};
[user.firstName, user.lastName] = '길동 홍'.split(' ');

console.log(user.firstName);        //    길동
console.log('ㅡㅡㅡㅡㅡㅡㅡㅡkey valㅡㅡㅡㅡㅡㅡㅡㅡ');

//   entries  : Returns an array of key/values of the enumerable properties of an object
for(let [key,value] of Object.entries(user)){
    console.log(`${key} : ${value}`);
}
//    firstName : 길동
//    lastName : 홍

let student = '유관순';
let teacher = '홍길동';

[student, teacher] = [teacher, student];

console.log(`stu : ${student} ,tea : ${teacher}`);
//  stu : 홍길동 ,tea : 유관순

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡrestㅡㅡㅡㅡㅡㅡㅡㅡ');

let [sign1, sign2, ...rest] = ['양자리', '황소자리', '쌍둥이자리', '개자리',]
console.log(sign1);   //  양자리
console.log(sign2);    //    황소자리
console.log(rest);     //   [ '쌍둥이자리', '개자리' ]

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ');

let [firstName4 ='아무개', lastName4 = '김'] = ['길동'];
console.log(firstName4);    // 길동
console.log(lastName4);     //    김   (기본값으로 할당)

 

객체 구조 분해

// 객체 구조분해 할당

let pants = {
    productName : '팬츠',
    color : '검정색',
    price : 30000
}


let {productName, color, price} = pants;

console.log(productName);
console.log(color);
console.log(price);
/*
팬츠
검정색
30000
*/

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ');
let { color : co, price : pr, productName : pn } = pants;

console.log(co);
console.log(pr);
console.log(pn);
/*
검정색
30000
팬츠
*/

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ');

let shirts = {
    productName : '베이직 셔츠'
}

// 초기값 할당 가능
let { productName : productName2 = '어떤상품', color : color2 = '어떤색상' , price : price2 = 0} = shirts;

console.log(productName2);
console.log(color2);
console.log(price2);

/*
베이직 셔츠
어떤색상
0
*/

console.log('ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ');

// pants 로 초기화 ????
let {productName : productName3} = pants;
console.log(productName3);   // 팬츠


let {productName : productName4, ...r} = pants;
console.log(productName4);
console.log(r.color);
console.log(r.price);

/*
팬츠
검정색
30000
*/

// 프로퍼티 값에 직접 그냥 할당하고 있음, 기본값도 할당하고
let productName5, color5, price5;
({productName : productName5 , color : color5 , price : price5 = 0} = pants);
console.log(productName5);
console.log(color5);
console.log(price5);

/*
팬츠
검정색
30000   (pants 에 30000이 있으니까 기본값 할당x )
*/


console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);
// 중첩 구조 분해

let product = {
    size : {
        width : 10,
        height : 30
    },
    items : ['doll', 'robot']
};

let {
    size : {
        width,
        height
    },
    items : [item1, item2]          
} = product;   //  할당


// console.log(product.size.height);


console.log(width);
console.log(height);
console.log(item1);
console.log(item2);
/*
10
30
doll
robot
*/

console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);
let {
    size , 
    items 
} = product;   // 할당

console.log(size.width);   // 10



// 함수의 매개변수에 적용
// 함수의 매개변수가 많거나 기본 값이 필요한 경우 활용, 순서도 고정되지 않아도 됨
// 구조분해 = 중괄호  {} 로 감싸주기가 중요
function displayProduct({producer = '아무개', width =0, height=0, items = []}) { 
    console.log(`${producer}, ${width}, ${height}`);
    console.log(items);
} ;
console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡ조금 이상하게ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);
displayProduct({width:'이대엽',producer: undefined, undefined, items:['Coffee', 'Donut']});
//  순서를 안맞게 해도 프로퍼티 값에 맞게 잘 들어가고있다.
//   아무개, 이대엽, 0
//    [ 'Coffee', 'Donut' ]


console.log(`ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ`);  
// 객체 하나 임의로 생성
// 매개변수 순서가 맞지않아도 됨
let exProduct = {
    items : ['이효리', '도넛'],
    producer : '커피'
}

displayProduct(exProduct);
//  커피, 0, 0
//   [ '이효리', '도넛' ]

+ Recent posts