??
왼쪽 피연산자가 null 또는 undefined인 경우에 오른쪽 피연산자를 반환하며 그 외에는 왼쪽 피연산자를 반환한다.
const a = null;
const b = undefined;
const c = 'es6';
console.log(a ?? b ?? c); // "es6"
// 값이 확정되어있는 변수의 값을 리턴한다.
// null과 undefined는 리턴 X
const a = null;
const b = undefined;
const c = 'es6';
const d = 'JS';
console.log(a ?? b ?? d ?? c); // "JS"
// null 과 undefined가 아닌 값이 여러개 존재할 경우
// 가장 왼쪽에 있는 값을 리턴한다.
...
반복이 가능한 객체, 배열에 적용 가능한 문법이며 요소를 각각 꺼내 전개하는 문법
const numbers = [1,2,3,4,5];
console.log(...numbers); // 1 2 3 4 5
console.log(numbers); // [1,2,3,4,5]
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4, 5]; //numbers 요소를 복사 후 새로운 요소 추가
console.log(newNumbers);// [1,2,3,4,5]
const numbers1 = [1,2,3,4,5];
const numbers2 = [6,7,8,9,10];
const newNumbers = [...numbers1,...numbers2];
console.log(...newNumbers); // 1 2 3 4 5 6 7 8 9 10
const arr1 = [1,2,3];
const arr2 = [4,5,6];
const newArr = [0,...arr1,...arr2,7,8,9];
console.log(newArr); // Array[0,1,2,3,4,5,6,7,8,9]
const print = (a,b,...rest) =>{
console.log(a);
console.log(b);
console.log(rest);
};
print(1,2,3,4,5,6,7,8,9,10);
// 파라미터로 고정된 a와 b는 각각 출력되지만
// 전개연산자를 활용한 나머지 파라미터들은 배열로 출력된다.
const print = (a,b,...rest) =>{
console.log(a);
console.log(b);
console.log(...rest);
}
print(1,2,3,4,5,6,7,8,9,10);
// rest 요소를 전개연산자를 활용한 모습
const printName = (name) =>{
console.log("안녕하세요 " + name + "님 반갑습니다.");
}
printName("Jake");
// 문자열을 ""(더블 쿼테이션)으로 감싸고, 변수는 따로 작성하며 문자열과 변수를 분리해야한다.
const printName = (name) =>{
console.log(`안녕하세요 ${name}님 반갑습니다.`);
}
printName('Jake');
//``(백틱)을 활용하여 문자열과 변수를 백틱안에 작성하고 변수는 ${} EL태그로 감싸준다.
2개 이상의 파라미터가 필요한 함수를 작성하는 경우 파라미터가 부족하게 입력되어도, 자바스크립트는 컴파일러가 존재하지 않아 에러를 발생시키지 않는다.
const sum = (a,b) =>{
console.log(a+b);
}
sum(10); // NaN ==> 10 + undefined
-----------------------
const sum = (a,b=10) =>{
console.log(a+b);
}
sum(10); // 20 ==> 10(a) + 10(default value)
-----------------------
const sum = (a,b=10) =>{
console.log(a+b);
}
sum(10,5);//15 ==> 파라미터가 모두 들어오는 경우 default value는 무시됩니다.
-----------------------
const printName = (name) =>{
console.log(`Hello ${name}`);
}
printName(); //Hello undefined
-----------------------
const hello = (name="Jake") =>{
console.log(`Hello ${name}`);
}
hello(); //Hello Jake ==> default value가 문자열인 경우 반드시 "",'' 감싸줘야한다.
-----------------------
const hello = (name="Jake") =>{
console.log(`Hello ${name}`);
}
hello('IU');//Hello IU
객체나 배열에서 값을 추출하여 변수에 할당할 수 있으며, 객체의 경우 프로퍼티명이 일치해야한다.
const person = {
name: "John",
age: 30
};
console.log(name, age);
// name과 age는 person 객체의 프로퍼티이기 때문에 정의되어있지 않다.
console.log(person.name,person.age); //John 30
// 객체에 존재하는 프로퍼티를 사용하고자 할경우 위와같은 방식으로 객체를 명시해야한다.
객체에서 구조 분해 할당을 사용할 경우 {} 중괄호를 사용한다.
const person = {
name: "John",
age: 30
};
const { name, age } = person;
console.log(name, age); // John 30
const myDog = {
name: "nuri",
age : 9,
height : 100,
weight : 6
}
const {name,weight,age,height} = myDog;
// 순서는 신경쓰지 않아도 되며, 변수명이 일치해야한다.
// 변수명이 일치하지 않는경우 오브젝트에 존재하는 프로퍼티를 가져오지 못해 undefined가 출력된다.
console.log(name,age,height,weight); //nuri 9 100 6
const {name:hello, weight:world, age, height=200} = myDog;
// 키값을 추출하고 변수명을 바꿀 수 있다. key : 바꿀 변수명
// 키 = 값, 기본값(default) 설정 불가능.
console.log(hello,world,height) //nuri 6 100
const obj = {
one : {
two : {
three: "Hello"
}
}
}
console.log(obj.one.two.three); //"Hello"
const {one : {two : { three }}} = obj;
console.log(three); "Hello"
const obj = {
x: 10,
y: 20
}
const sum = (obj) =>{
return obj.x + obj.y;
}
console.log(sum(obj)); // 30
---------------------------------------
const sum = ({x,y}) =>{
return x+y;
}
console.log(sum(obj)); //30
배열에서 구조 분해 할당을 사용할 경우 [] 대괄호를 사용한다.
배열의 경우 배열의 순서를 고려하여 변수에 대입한다.
사용하고자 하는 변수명을 마음대로 사용할 수 있으며, 각 순서에 맞게 변수에 배열이 할당된다.
알파벳 a~j 까지 배열의 요소를 대입하기 위한 방법.
const arr = [1,2,3,4,5,6,7,8,9,10];
const a = arr[0];
const b = arr[1];
const c = arr[2];
...
const j = arr[9];
const arr = [1,2,3,4,5,6,7,8,9,10];
const [a,b,c,d,e,f,g,h,i,j] = arr;
console.log(a,b,c,d,e,f,g,h,i,j); // 1 2 3 4 5 6 7 8 9 10
const[one,,three,,five] = arr; // 모든 인덱스에 접근하지 않아도 할당이 가능하다.
console.log(one,three,five);// 1 3 5
const[one,two,...others] = arr; // 구조 분해 할당과 전개연산자를 같이 사용할 수 있다.
console.log(one);
console.log(two);
console.log(others);
let a = 10;
let b = 20;
let temp = a;
a = b;
b = temp;
-----------------------
[a,b] = [b,a];
console.log(a); //20
console.log(b); //10
자바스크립트는 함수도 객체로 여기며, new 생성자를 통해 객체가 생성되며 인스턴스에 객체가 담긴다.
function User(name,age,...skills){
this.name = name;
this.age = age;
this.skills = skills;
}
const user1 = new User('jake',25,'html','css','java','javascript');
const user2 = new User('nuri',9,'bark');
const user3 = {...user1};
//전개 연산자와 구조 분해 할당을 통해 user1을 복사한다.
console.log(user1);
console.log(user2);
// 전개연산자를 통해 파라미터를 받으면 배열로 받게된다.
console.log(user3); //user1과 동일하다.
let user = {name : "jake"};
const info = {age:25};
const fe = ["JS","React"];
const lang = ["Korean", "English"];
user = {
...user,
...info,
skills : [...fe,...lang];
}
문자열을 검색하는 함수 hasCola(str)
function hasCola(str) {
if(str.indexOf("콜라")){
console.log("금칙어가 있습니다.");
} else{
console.log("통과");
}
}
hasCola("사이다가 짱이다."); //금칙어가 있습니다.
hasCola("코크가 짱이다."); //금칙어가 있습니다.
hasCola("코카콜라가 짱이다."); //금칙어가 있습니다.
// if문 조건 값이 0일경우 false이지만 0이 아닌경우는 다 true로 반환된다.
// -1도 true로 판단되기 때문에, 주의해야한다.
function hasCola(str) {
if(str.indexOf("콜라") !== -1){
console.log("금칙어가 있습니다.");
} else{
console.log("통과");
}
}
hasCola("사이다가 짱이다."); //통과
hasCola("코크가 짱이다."); //통과
hasCola("코카콜라가 짱이다."); //금칙어가 있습니다.
Array.forEach((item,index)=>{
// 함수로직
})
// 첫번째 파라미터로 배열의 요소가 들어가고, 두번째 파라미터로 인덱스가 들어간다.
const users = ['Mike','Tom','Jane'];
users.forEach((name,index)=>{
console.log(`index ${index}에 존재하는 요소는 ${name}입니다.`);
})
const arr = [1,2,3,4,5,6,7,8,9,10];
arr.forEach((item,index) =>{
if(item%2===0){
console.log(`${index}에 있는 숫자는 짝수입니다.`);
} else{
console.log(`${index}에 있는 숫자는 홀수입니다.`);
}
})
Array.filter() 메소드는 주어진 함수를 사용하여 배열의 요소를 필터링하여 배열의 각 요소에 대해 호출되며, 함수가 참을 반환하는 요소만 새로운 배열로 반환한다.
const arr = [1,2,3,4,5,6,7,8,9,10];
const newArr = arr.filter((item)=>{
return item%2===0
})
console.log(arr);
console.log(newArr);
배열을 조작하고 변환할 때 많이 사용하는 메소드
Array.map() 메소드는 배열의 모든 요소에 대해 주어진 함수를 호출하여, 원래 배열은 그대로 유지되며, 각 요소에 대한 변환된 값으로 이루어진 새로운 배열이 반환한다.
const arr = [1,2,3,4,5,6,7,8,9,10];
const newArr = arr.map((item)=>{
return item **2;
})
console.log(arr);
console.log(newArr);
map() 과 filter()는 새로운 배열를 반환하지만, sort()는 기존 배열이 변경된다.
const arr = [2,5,4,8,3,6,9,7,1];
arr.sort(); //배열 자체가 변경되므로 조심해야한다.
console.log(arr);
배열의 합을 구하기 위한 forEach
const arr = [2,5,4,8,3,6,9,7,1];
let sum = 0;
arr.forEach((num) => {
sum += num;
})
console.log(sum); //45
이 과정을 간단히 만든것이 reduce() 함수이다.
배열의 요소만큼 반복하면서 누적된 계산 값과 현재 값을 파라미터로 받고 로직을 수행한다.
const result = arr.reduce((누적된 계산값, 현재값)=>{
// 로직
},초기값(default))
const result = arr.reduce((prev, cur)=>{
return prev + cur;
},0)
// default값 0에 현재값(cur)을 더해서 리턴하며 반복한다.
const userList = [
{name : "Mike" , age:30},
{name : "Tom" , age:10},
{name : "Jane" , age:27},
{name : "Sue" , age:26},
{name : "Harry" , age:18},
{name : "Steve" , age:60},
];
const adult = userList.reduce((prev,user)=>{
if(user.age >= 19){
prev.push(user);
}
return prev;
},[])
console.log(adult);
// age>=19 user만 배열에 추가된다.
만약 결과값을 배열로 하고 싶은 경우 default값으로 빈배열 []을 선언 해주어야한다.
const userList = [
{name : "Mike" , age:30},
{name : "Tom" , age:10},
{name : "Jane" , age:27},
{name : "Sue" , age:26},
{name : "Harry" , age:18},
{name : "Steve" , age:60},
];
const adultAge = userList.reduce((prev,user)=>{
if(user.age >= 19){
prev += user.age;
}
return prev;
},0)
console.log(adultAge); // 143
함수.call(객체);
call() 메서드를 통해 객체를 this 취급할 수 있다.
const mike = {
name : "Mike"
}
const jake = {
name : "Jake"
}
function showThisName(){
console.log(this.name);
}
showThisName(); //""
showThisName.call(mike) // "Mike"
showThisName.call(jake) // "Jake"
화살표 함수에서 call메서드를 사용해도 객체를 this로 지정해줄 수 없다.
const showThisName = () =>{
console.log(this.name);
}
showThisName(); //""
showThisName.call(mike) // ""
showThisName.call(jake) // ""
첫번째 파라미터에 객체를 넣어주고, 두번째 부터 파라미터를 작성한다.
함수.call(객체,파라미터1,파라미터2,...)
function update(height, age){
this.height = height;
this.age = age;
}
update.call(mike,170,20) == update.apply(mike,[170,20])
update.call(jake,180,25) == update.apply(jake,[180,25])
// call() 메서드는 파라미터를 하나씩 넣어주지만,
// apply() 메서드는 파라미터를 배열로 넣어준다.
// call과 apply에 첫번째로 들어오는 파라미터는 this로 칭할 오브젝트가 들어온다.
배열에서 call(), apply() 사용
const arr = [1,2,3,4,5,6,7,8,9,10];
const min = Math.min(arr);
const max = Math.max(arr);
console.log(min); //NaN, Object인 배열 자체에 대한 최소값은 존재하지 않는다.
console.log(max); //NaN, Object인 배열 자체에 대한 최대값은 존재하지 않는다.
const min = Math.min(...arr);
const max = Math.max(...arr);
console.log(min); //1
console.log(max); //10
const min = Math.min.apply(null,arr); //apply는 파라미터를 배열로 받고,
const max = Math.max.call(null,...arr); //call은 파라미터를 하나씩 받는다.
console.log(min); //1
console.log(max); //10
const user = {
name: "Mike",
showName : function(){
console.log(`Hi! ${this.name}`);
}
}
user.showName(); //"Hi! Mike"
let fn = user.showName;
fn(); // "Hi! "
fn.call(user); //"Hi! Mike"
fn.apply(user); //"Hi! Mike"
변수 fn에 user.showName 메서드를 할당할 때 this의 값을 유지하지 않는 이유는, 함수를 호출하는 방법에 따라 this가 다르게 바인딩되기 때문입니다.
user.showName()을 호출할 때, this는 user 객체를 가리킵니다. 하지만 let fn = user.showName; 코드에서 fn은 user 객체의 메서드를 참조하지만, this는 fn을 호출한 주체에 따라 결정됩니다.
일반적으로 함수를 호출할 때 this는 전역 객체(window)를 가리키게 됩니다. 따라서 fn()을 호출하면 this는 window 또는 global을 가리키게 됩니다.
let fn = user.showName(); fn(); --> TypeError, showName()은 return이 존재하지 않기 때문에 변수 fn은 undefined
class User{
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
console.log(this.name);
}
}
const jake = new User("jake",25);
const mike = new User("mike",30);
console.log(jake);
console.log(mike);
jake.showName(); //jake
mike.showName(); //mike
for(const property in jake){
console.log(property);
} //name, age만 출력 > 메소드는 생략된다. 열거 가능한 프로퍼티만 리턴한다.
class Car{
constructor(color){
this.color = color;
this.wheels = 4;
}
drive(){
console.log("drive...");
}
stop(){
console.log("stop...");
}
}
class Bmw extends Car{
constructor(color){
super(color);
this.navigation = 1; //super()없는경우 Error
}
park(){
console.log("park...");
}
// 메서드 오버라이딩
stop(){
super.stop();
console.log('외제차 stop'); //메서드 재정의
}
}
const bmw = new Bmw('blue');
bmw.drive();
bmw.park();
bmw.stop();
//생성자가 존재하지 않으면 부모 생성자를 그대로 사용한다.
//생성자를 재정의할 경우 부모의 생성자를 super()로 가져오고 재정의한다.