arr.sort();
console.log(arr); // 1,2,3,4,5
주의! 배열 자체가 변경 됨. 꼭 기억할것. 문자열도 알파벳 순서대로 정렬이된다.
let arr = [27,8,5,13];
arr.sort();
console.log(arr); // 13,27,5,8
위와 같이 나오는 이유는 배열안에 있는 숫자를 문자열로 취급하기 때문에 1(3),2(7),5,8
이런식으로 배열이 정렬이 된다.
값을 정확하게 비교하기 위해선 sort에서 함수를 전달 받아야 한다.
let arr = [27,8,5,13];
arr.sort((a,b)=>{
console.log(a,b);
return a-b;
});
console.log(arr); //5,8,1,3,27
내부 로직 원리는 2개씩 콘솔에 찍힌 값끼리 서로 비교하면서 자리를 찾아간다.
실무에서는 보통 Lodash라는 라이브러리를 다운받아서 _.sortBy(arr)을 사용하여 sort에 함수 전달 없이 사용한다.
let arr = [1,2,3,4,5];
let result = 0;
arr.forEach(num=>{
result += num;
});
console.log(result); //15
이 작업을 한번에 처리할 수 있는게 reduce 이다.
// 배열의 모든 수 합치기
let arr = [1,2,3,4,5];
const result = arr.reduce((prev,cur)=>{
return prev +cur
},0); 함수값 다음에 오는 인자는 초기값을 나타내는데, defult는 배열의 첫번째 요소가 들어가게 된다. 배열 자체의 합을 구할 때는 0은 안적어줘도 된다는 뜻.
ex) reduce의 유용한 쓰임
let userList = [
{name:"Mike",age:30},
{name:"Tom",age:10},
{name:"Jane",age:27},
{name:"Sue",age:26},
{name:"Harry",age:43},
{name:"Steve",age:60},
];
let result = userList.reduce((prev,cur)=>{
if(cur.age>19) {
prev.push(cur.name);
}
return prev;
},[]);
console.log
let str = "Mike-Tom-Jane";
let [user1,user2,user3] = str.split('-') << 이것도 위에거와 마찬가지로 배열 구조가 '-' 단위로 분해되어 배열에 저장이 된다.
if 해당 하는 값이 없다면??
let [a=3, b=4,c=5] = [1,2];
c에 기본값을 설정 함으로써 undefined가 되는 상황을 방지 하기위해 기본값을 설정해놓으면 미연에 방지 할 수 있다.
let[u1, ,u2] = ['1','2',3,] 이런식으로 중간을 비우게 되면 1이랑 3이 들어가게 된다.
function showName(name){
console.log(arguments.length);
console.log(arguments[0]);
console.log(arguments[1]);
}
showName('Mike','Tom');
// 2
// 'Mike'
// 'Tom'
function showName(...names){
console.log(names);
}
showName('Mike','Tom') // 'Mike', 'Tom'
앞에서와 다르게 reduce, forEach를 ...방식은 모두 사용이 가능하다.
function add(...numbers) {
let result = numbers.reduce((prev,cur) => prev +cur);
console.log(result)
}
add(1,2,3) // 6
add(1,2,3,4,5,6,7,8,9) //55
##// 화살표 함수의 유일한 문장이 'return'일 때 'return'과
// 중괄호({})를 생략할 수 있다.
elements.map(element => element.length); // [8, 6, 7, 9]
유용한 예제
function User(name,age, ...skills){
this.name = name;
this.age = age;
this.skill = skills;
}
const user1 = new User('Mike',30,'html','css');
const user2 = new User('Tom',20,'JS','React');
const user3 = new User('Jane',10,'English');
이런식으로 나머지 매개변수는 항상 마지막에 위치해야 한다.
let user = {name:'Mike', age:30};
let user2 = {...user};
user2.name = "Tom"
console.log(user2.name); // Tom
// .unshift() : 배열의 맨 앞에 값을 추가한다.
전개구문의 쓰임으로 만약에
let arr1 = [1,2,3];
let arr2 = [4,5,6];
arr2.reverse().forEach((num)=>{
arr1.unshift(num);
});
console.log(arr1); // [4,5,6,1,2,3]
이런식으로 값을 얻어야 하는 부분을
arr1 = [...arr2,...arr1]
이런식으로 같은 값을 얻을 수 있다.
let one = 1;
function addOne(num) {
// let one = 2
console.log(one + num)
}
addOne(5);
처음에 전역 Lexical 환경에서 one : 1 , addOne:function 이 두개의 값을 가지고 있다가, 내부 Lexical 환경에서는 num:5를 가지고있음, 내부 Lexical이 전역 Lexical을 참조 > num에 대한 정보는 있지만 one은 없기 때문에 전역에서 값을 찾은후 대입, 내부에서 만약 one을 선언 해줄 시에 우선적으로 one의 값은 내부에서 지정해준 값으로 사용된다.
어휘적 환경(Lexical Envionment)
function makeAdder(x) {
return function (y) {
return x + y;
}
}
const add3 = makeAdder(3);
console.log(add3(2)); // 5, add3 함수가 생성된 이후에도 상위함수인 makeAdder의 x에 접근 가능
Closure = 함수와 렉시컬 환경의 조합 , 함수가 생성될 당시의 외부 변수를 기억 생성 이후에도 계속 접근 가능
객체에는 자신이 property로 가지고 있는지 확인하는 메소드가 있는데,
hasOwnProperty() 이다.
hasOwnProperty의 위치는 proto:라는 객체가 있는데, 이것을 프로토타입이라고 한다. 일단 객체에서 property를 읽으려고 하는데 없으면
프로토타입에서 property를 찾는다.
만약 객체 내에서 property가 존재한다면 탐색을 종료한다.
const car = {
wheels :4,
drive() {
console.log("drive..");
},
};
const bmw = {
color : "red",
navigator: 1,
};
const benz = {
color : "black",
};
const audi = {
color:'blue',
};
bmw.proto = car; // 이렇게 되면 car가 bmw의 프로토타입이 되는것, 다시말해, bmw는 car를 상속 받은것이다.
benz.proto = car;
audi.proto = car;
const x5 = {
color:"white",
name:"x5",
};
x5.proto=bmw;
여기서 console.log(x5.drive()) // drive..
가 나오게 되는데 이 메소드는 car객체에 있는 내용인데, 사용이 가능한 이유가 prototype chain관계에 의해서 사용이 가능하다.
const Bmw = function (color) {
this.color = color;
};
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
x5.proto=car;
z4.proto=car;
// 생성자 함수를 사용하는건 간편해서 이니 다른방법으로는
const Bmw = function (color) {
this.color=color
};
Bmw.prototype.wheels = 4;
Bmw.prototype.drive = function(){
console.log("drive..")
};
const x5 = new Bmw("red");
const z4 = new Bmw("blue");
생성자함수가 새로운 객체를 만들어 낼때, 그 객체는 생성자의 인스턴스라고 부른다. instanceof로 인해서 객체와 생성자를 확인할 수 있다.
ex) z4 instanceof Bmw << z4 Bmw로 인해서 만들어진 인스턴스 이기 때문에, true값을 반환한다.
const Bmw = function(color){
this.color = color;
};
const x5 = new Bmw("red"); // 지금 만들어진 자동차의 색상은 마음대로 변경이 가능하다. 이럴때는 클로저를 이용하면 된다.
const Bmw = function (color){
const c = color;
this.getColor = function () {
console.log(c);
}
};
const h4 = new Bmw("red");
이렇게 쓰게되면 초기에 세팅했던 컬러값을 얻을 수는 있고 바꿀수는 없다.
이처럼 우리는 함수라는 객체를 생성했을 때 그 객체에는 prototype이라는 object가 자동으로 생성된다. 그 프로토타입에는 역시 constructor라는 객체가 자동으로 생성되어 서로를 참조할 수 있게 된다.
Person.prototype.sum = function(){}
위의 코드를 통해서 prototype에 함수를 추가함으로써 여러 객체를 생성하였을 때 해당함수를 사용할 수 있게 한다.
그림에서의 객체에서
kim.sum()
lee.sum()
둘 다 사용이 가능하다.
Q. 그렇다면 이렇게 두 객체가 sum함수를 사용할 수 있는 이유는 무엇일까?
그건 바로 Person의 인스턴스를 새로 생성했을 때 해당 인스턴스의 Person의 prototype링크인 proto object를 새로 부여받기 때문이다.
따라서 kim객체에는 없는 sum함수도 사용할 수 있게 된다.
const User = function (name,age) {
this.name = name;
this.age = age;
this.showName = function (){
console.log(this.name);
};
};
const mike = new User('kevin',30);
console.log(mike);
class User2 {
constructor(name,age) {
this.name=name;
this.age = age;
}
showName() {
console.log(this.name);
}
}
const tom = new User2('lisa',29);
console.log(tom);
밑에있는 class에서는 객체 안에 showName이 존재 하지 않고, proto내에 showName이 존재한다.
첫번쨰 생성자 메소드 의 코드에서, 아래와 똑같이 prototype에 함수를 추가하기 위해선, this.showName ... 을 지우고, User.prototype.showName = function(){console.log(this.name)}; 을 추가하면 된다.
class Car {
constructor(color) {
this.color = color;
this.wheels = 4;
}
drive() {
console.log("drive..")
}
stop() {
console.log("stop!")
}
}
class Bmw extends Car {
park() {
console.log("PARK");
}
}
const z4 = new Bmw('blue');
z4.stop();
class Bmw extends Car {
park() {
console.log("PARK");
}
stop(){
super.stop() // 메소드 오버라이딩.
console.log("OFF!")
}
}
const z4 = new Bmw('blue');
z4.stop();
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;
}
park() {
console.log("PARK");
}
stop() {
super.stop()
console.log("OFF!")
}
}
const z4 = new Bmw('blue');
console.log(z4);