변수의 생성과정은 선언단계 - 초기화단계 - 할당 단계로 이루어져 있다.
var
의 경우 선언 및 초기화가 같이 진행된다.
let
의 경우 선언 - 초기화 - 할당이 이루어진다.
const
의 경우 세가지 단계가 한번에 이루어진다.
var
는 함수스코프(함수 내에서만 지역변수, 블록에서 사용했을 경우 밖에서도 사용 가능)이고,
let
,const
는 블록스코프(블록 안에서 생성된 것은 지역변수로 밖에서 사용 불가)이다.
const person = {
name : "카타리나",
age : 29
}
function Human(name, age){
this.name = name;
this.age = age;
this.print = function(){
console.log(`나는 ${name}, ${age}살!`)
}
}
let person1 = new Human("쥐도리", 20);
console.log(person1) // Human { name: '쥐도리', age: 20, print: [Function (anonymous)] }
person1.print(); // 나는 쥐도리, 20살!
let person2 = Human("쥐순이", 20); // new 키워드를 사용하지 않아 객체 미 생성
console.log(person2); // undefined
person2.print(); // TypeError: Cannot read properties of undefined (reading 'print')
위 코드와 같이 생성자 함수를 만들 수 있으며, 사용할 때에는 new
키워드를 사용하여 변수에 할당해야 한다.
const 새로운객체 = Object.assign({}, 복사할객체);
// {} + {복사할객체} = {새로운객체}
console.log(JSON.stringify(비교할 객체 1) === JSON.stringify(비교할 객체 2)); // true 출력
객체는 비교연산자를 사용할 수 없기 때문에 객체를 JSON으로 변환시켜 비교한다.
let 새로운객체명 = {...병합할객체1, ...병합할객체2}
전개연산자를 이용하여 객체를 병합할 수 있다.
Object.keys(객체명);
// ['키명1','키명2',...]
Object.vlaues(객체명);
// ['값1','값2',...]
Object.entries(객체명);
// [['키명1','값1'],['키명2','값2'],[...]]
let n = 1;
n.tostring(); // "10"
let n = 1;
n.tostring(2); // "1010"
let s1 = "hello";
s1.length // 5
let s1 = "hello";
console.log(s1[2]); // l 출력
let s1 = "hElLo";
console.log(s1.toUpperCase()); // HELLO
console.log(s1.toLowerCase()); // hello
// 치환되는 것이 아님.
// 유지하고 싶으면 다른 변수에 담아야 함/
let s1 = "hello. My name is GDORI";
s1.indexOf('GDORI'); // 18
s1.indexOf('GSOONI'); // -1 (없는 경우)
let s1 = "hello. My name is GDORI";
s1.includes('GDORI'); // true
s1.includes('GSOONI'); // false
let s1 = "hello. My name is GDORI";
s1.slice(2) // "llo. My name is GDORI"
s1.slice(0,5) // "hello"
//1번째 인자 인덱스에서 2번째 인자 인덱스 앞까지 자름.
s1.slice(7,-8) // "My name"
// -의 경우 뒤에서부터 세면 됨
let s1 = "hello. My name is GDORI";
s1.substr(0,5) // "hello"
// 0번 인덱스부터 5글자 가져오라는 뜻
let s1 = " hello. ";
s1.trim(); // hello.
"a".codePointAt(0); // 97
String.formCodePoint(97); // "a"
let n1 = 1.1;
let n1 = 1.6;
Math.ceil(n1); // 2
Math.ceil(n2); // 2
let n1 = 1.1;
let n1 = 1.6;
Math.floor(n1); // 1
Math.floor(n2); // 1
let n1 = 1.1;
let n1 = 1.6;
Math.round(n1); // 1
Math.round(n2); // 2
let n1 = 1.1355;
Number(n1.toFixed(2)) // 1.14
let n1 = "2024Y";
parseInt(n1); // 2024
let n2 = "Y2024";
parseInt(n2); // NaN
let n3 = "ff77";
parseInt(n2,16); // 65399
let n4 = "1010";
parseInt(n2,2); // 10
let n5 = "80%";
parseFloat(n5); // 80
Math.floor(Math.random()*100)+1
// 1~100 사이의 숫자를 출력할 때
const arr = [1, 2, 3, 4, 5];
Math.max(...arr) // 5
Math.min(...arr) // 1
Math.abs(-1); // 1
Math.pow(2,3); // 8, 2의 3승
Math.sqrt(4); // 2
const arr = [ 1, 2, 3 ];
arr.push(4);
console.log(arr) // [1, 2, 3, 4]
const arr = [ 1, 2, 3 ];
arr.pop();
console.log(arr) // [1, 2]
const arr = [ 1, 2, 3 ];
arr.unshift(0);
console.log(arr) // [0, 1, 2, 3]
const arr = [ 1, 2, 3 ];
arr.shift();
console.log(arr) // [2, 3]
const arr = [ 1, 2, 3, 4, 5 ];
arr.splice(1,2);
console.log(arr) // [1, 4, 5]
const arr2 = [ 1, 2, 3, 4, 5 ];
let returnIdx = arr2.splice(1,2,6,7);
console.log(arr2); // [1, 6, 7, 4, 5]
console.log(returnIdx); // [2, 3]
// splice는 제거된 요소를 반환한다.
const arr = [ 1, 2, 3, 4, 5 ];
arr.slice(1,2);
console.log(arr); // [ 1, 2, 3, 4, 5 ]
console.log(arr.slice(1,2)); // [2]
let returnIdx = arr.slice();
console.log(returnIdx); // [ 1, 2, 3, 4, 5 ]
/* slice 1번 인자에서 2번인자 앞까지 제거
slice는 원형을 건들이지 않음
slice 메서드에 인자를 안넘기면 배열 복사 */
const arr = [ 1, 2, 3, 4, 5 ];
const res = arr.filter((idx)=>{
return idx % 2 == 0 ? true : false;
});
console.log(res); // [2, 4] 출력
const arr = [ 1, 2, 3, 4, 5 ];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1] 출력
const obj_arr = [
{ name: "Gdori", age:20 },
{ name: "Gsooni", age:17 },
{ name: "Hodori", age:30}
];
const obj_arr2 = obj_arr.map((human, idx)=>{
return Object.assign({}, human, {
isAdult: human.age>=20
})
});
console.log(obj_arr2);
/*[
{ name: 'Gdori', age: 20, isAdult: true },
{ name: 'Gsooni', age: 17, isAdult: false },
{ name: 'Hodori', age: 30, isAdult: true }
]*/
const arr = [ 1, 2, 3, 4, 5 ];
const str = arr.join();
console.log(str); // "1,2,3,4,5"
const str2 = arr.join("");
console.log(str2);// "12345"
const str = "1,2,3,4,5";
const arr = str.split(",");
// 쉼표(,) 기준으로 잘라서 배열로 만들어라
console.log(arr); // ['1','2','3','4','5']
let arr = [ 17, 12, 13, 41, 55 ];
arr.sort((a,b)=> a-b);
console.log(arr);
let arr = [ 17, 12, 13, 41, 55 ];
arr.sort((a,b)=> b-a);
console.log(arr);
let arr = [ 1, 2, 3, 4, 5 ];
let sum = arr.reduce((prev, current)=> prev+current,0)
// reduce(함수,초기값)
console.log(sum); // 15
const obj_arr = [
{ name: "Gdori", age:20 },
{ name: "Gsooni", age:17 },
{ name: "Hodori", age:30}
];
const adult_obj = obj_arr.reduce((prev, current)=>{
if(current.age >=20) prev.push(current.name);
return prev;
},[])
console.log(adult_obj); // [ 'Gdori', 'Hodori' ]
let human = ["Gdori", "Gsooni", "Hodori"];
let [p1,p2,p3] = human;
console.log(p1); // "Gdori"
console.log(p2); // "Gsooni"
console.log(p3); // "Hodori"
let a= 10;
let b= 20;
[a, b] = [b, a];
console.log(a, b); // 20 10
let person = {name: 'Gdori', age:20}
let {name, age} = person;
let {name: newName, age: newAge} = person;
console.log(name, age); // Gdori 20
console.log(newName, newAge); // Gdori 20
let num;
num = 10;
function sum_ten(arg){
console.log( num + arg );
}
sum_ten(10); // 20
전역 Lexical : num = 10;
/ function sum_ten
함수 내부 Lexical : arg = 10;
함수 내부 - 외부 - 전역 순으로 참조를 한다.
function calc(x){
return function(y){
return x+y;
}
}
const add_one = calc(1);
console.log(add_one(3)); // 4
호이스팅으로 인해 전역 Lexical 환경에 최초
calc:function
과 add_one:undefined
가 들어간다.
const add_one = calc(1);
라인에 도달하면
calc Lexical 환경에 x=1 이 생기고
console.log(add_one(3));
라인에 도달하면
익명함수 lexical 환경에 y=3 이 생긴다.
따라서 익명함수->calc->전역 순으로 참조하여
값이 도출될 수 있다.
function count(){
let cnt = 0;
return function(){
return ++cnt;
}
}
const counter = count();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
위 코드로 진행 순서를 살펴보면, 호이스팅
전역 Lexical ->count:function
,counter:undefined
const counter = count()
라인에 도달하면
전역 Lexical ->count:function
,counter:function
count Lexical -> cnt : 0
console.log(counter());
행에 도달하면
function(){
return ++cnt;
} // counter 안에 들어있는 함수
익명함수 내에 cnt가 선언되지 않았으니 바로 위 스코프인 count Lexical 환경에서 참조
count Lexical -> cnt : 1
위와 같이 클로저를 사용하게 되면 cnt 변수는 익명성을 가져 외부에서 접근할 수 없고, 오직 counter 함수로만 접근이 가능한 상태가 된다.
const gdori = {
name: "Gdori"
}
function showName(){
console.log(this.name);
}
showName(); // undefined
showName.call(gdori); // "Gdori"
function update(age, job){
this.age = age;
this.job = job;
}
update.call(gdori, 20, "도적"); //{ name: 'Gdori', age: 20, job: '도적' }
console.log(gdori);
위의 경우 showName 함수는 전역스코프이기 떄문에 그냥 호출하였을경우 undefined가 나오게 된다.
이럴 때 call은 this 바인딩해줄 수 있다.
객체 정보를 업데이트 해주는 함수의 경우에도 call
메서드를 사용하여 바인딩 해줄 수 있다.
const gdori = {
name: "Gdori"
}
function update(age, job){
this.age = age;
this.job = job;
}
update.apply(gdori, [20, "도적"]); //{ name: 'Gdori', age: 20, job: '도적' }
console.log(gdori);
apply 의 경우 call메서드와 같으나 매개변수를
배열로 넘겨준다는 점만 다르다.
const gdori = {
name: "Gdori"
}
function update(age, job){
this.age = age;
this.job = job;
}
const bindGdori = update.bind(gdori);
bindGdori(29, "도적");
console.log(gdori); // { name: 'Gdori', age: 29, job: '도적' }
bind는 this를 고정시켜줄 수 있는 메서드이다.
객체 내 메서드를 복사하여 다른 변수에 넣어줄경우 bind가 되지 않을 때 사용한다.
class human {
constructor(name, age){
this.name = name;
this.age = age;
}
callName() {
console.log(this.name);
}
}
const gdori = new human("gdori",20);
console.log(gdori); // human { name: 'gdori', age: 20 }
gdori.callName(); // gdori
클래스는 다음과 같이 생성하며, new
키워드를 통해 변수에 할당할 수 있다.
class human {
constructor(name, age){
this.name = name;
this.age = age;
}
callName() {
console.log(this.name);
}
}
class human2 extends human{
constructor(name, age, gender){
super(name, age);
this.gender = gender
}
gas(){
console.log("push");
}
}
const gdori = new human2("gdori",20,"male");
console.log(gdori); // human2 { name: 'gdori', age: 20, gender: 'male' }
gdori.callName(); // gdori
gdori.gas(); // push
부모 클래스의 내용을 상속받아 오버라이딩할수도 있다.