[JS] 벨로퍼트와 함께하는 모던 자바스크립트 정리

yeopto·2022년 8월 15일
0

JavaScript

목록 보기
1/2
post-thumbnail

객체


객체 안에 함수 넣기

  • 함수가 객체안에 들어가게 되면 this 는 자신이 속해있는 객체를 가르키게 된다.
  • function 으로 선언한 함수는 this 가 제대로 자신이 속한 객체를 가르키게 되는데, 화살표 함수는 그렇지 않기 때문.

Getter 함수와 Setter 함수

  • Getter 함수와 Setter 함수를 사용하게 되면 특정 값을 바꾸려고 하거나, 특정 값을 조회하려고 할 때 우리가 원하는 코드를 실행 시킬 수 있다.
  • 왜 쓸까? → 이건 공부하다보면 나중에 왜 필요한지 알게 될듯?
  • 일단은 Getter는 조회 Setter는 수정 → 만약 객체 프로퍼티로 get a(), set a() a() 가 두개가 있음 → number.a = 7 이 경우는 바꾸는거니깐 set a()를 호출하겠지?. console.log(number.a) 는 a라는 함수를 실행했을 때 반환되는 값이 나오게됨. 그럼 조회하는 거니까 get() 을 호출하겠지?

반복문


  • for…of - 배열 반복문
  • for…in - 객체 반복문

배열 내장함수


map

배열 안의 각 원소를 변환 할 때 사용, 이 과정에서 새로운 배열이 만들어짐.

findIndex

배열 안에 있는 값이 객체거나, 배열이라면 indexOf 로 찾을 수 없음. findIndex 함수에 검사하고자 하는 조건을 반환하는 함수를 넣어서 찾을 수 있음.

find

찾아낸 값이 몇번째인지 인덱스를 알아내는 것이 아니라, 찾아낸 값 자체를 반환.

filter

배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열을 만듬.

concat

여러개의 배열을 합쳐줌.

reduce

두개의 파라미터를 전달. 첫번째 파라미터는 accumulator와 current를 파라미터로 가져와서 결과를 반환하는 콜백함수, 두번쨰 파라미터는 reduce 함수에서 사용 할 초깃값임. accumulator는 누적 값

const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current) => {
  console.log({ accumulator, current });
  return accumulator + current;
}, 0);

console.log(sum);

/* 결과 */
/* 
{ accumulator: 0, current: 1 }
{ accumulator: 1, current: 2 }
{ accumulator: 3, current: 3 }
{ accumulator: 6, current: 4 }
{ accumulator: 10, current: 5 }
15
*/

프로토타입과 클래스


객체 생성자

객체 생성자는 함수를 통해서 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현 할 수 있게 해준다.

function Animal(type, name, sound) { // 객체 생성자는 Animal 함수 그 자체
  this.type = type;
  this.name = name;
  this.sound = sound;
  this.say = function() {
    console.log(this.sound);
  };
}

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

프로토타입

프로토타입은 다음과 같이 객체 생성자 함수 아래에 .prototype.[원하는키] =코드를 입력하여 설정 할 수 있다.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
  console.log(this.sound);
};
Animal.prototype.sharedValue = 1;

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say(); // 멍멍
cat.say(); // 야옹

console.log(dog.sharedValue); // 1
console.log(cat.sharedValue); // 1

객체 생성자 상속받기

예를 들어서 우리가 Cat 과 Dog 라는 새로운 객체 생성자를 만든다고 가정. 그리고, 해당 객체 생성자들에서 Animal 의 기능을 재사용한다고 가정.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
  console.log(this.sound);
};
Animal.prototype.sharedValue = 1;

function Dog(name, sound) {
  Animal.call(this, '개', name, sound); // 상속받는다. 첫번째 인자에 this와야함.
}
Dog.prototype = Animal.prototype; // 프로토타입을 공유해야 하기 때문에 상속받은 객체 생성자(DOG)를 만들고 나서
																	// 프로토타입 값을 Animal.prototype으로 설정

function Cat(name, sound) {
  Animal.call(this, '고양이', name, sound);
}
Cat.prototype = Animal.prototype;

const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');

dog.say();
cat.say();

클래스

객체 생성자로 구현했던 코드를 조금 더 명확하고, 깔끔하게 구현 할 수 있게 해줌(ES6에 추가됨). 추가적으로, 상속도 훨씬 쉽게 해줌.

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
  say() { // 클래스 내부의 함수를 메서드라 함. 이렇게 메서드를 만들면 자동으로 prototype으로 등록이 됨.
    console.log(this.sound);
  }
}

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

클래스 상속

상속을 할 때는 extends 키워드를 사용하며, constructor에서 사용하는 super()함수가 상속받은 클래스의 생성자를 가르킴

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
	say() {
		console.log(this.sound);		
	}
}

class Dog extends Animal {
  constructor(name, sound) {
    super('개', name, sound);
  }
}

class Cat extends Animal {
  constructor(name, sound) {
    super('고양이', name, sound);
  }
}

const dog = new Dog('멍멍이', '멍멍');
const dog2 = new Dog('왈왈이', '왈왈');
const cat = new Cat('야옹이', '야옹');
const cat2 = new Cat('냐옹이', '냐옹');

dog.say();
dog2.say();
cat.say();
cat2.say();

spread와 rest


spread

객체 혹은 배열을 펼칠 수 있는 문법(ES6) → 기존의 것을 건들이지 않고, 새로운 객체를 만드는 것.

const slime = {
  name: '슬라임'
};

const cuteSlime = {
  ...slime, // 기존 것 
  attribute: 'cute'
};

const purpleCuteSlime = {
  ...cuteSlime,
  color: 'purple'
};

console.log(slime);
console.log(cuteSlime);
console.log(purpleCuteSlime);
  • 배열에서도 가능
const animals = ['개', '고양이', '참새'];
const anotherAnimals = [...animals, '비둘기'];
console.log(animals); // '개', '고양이', '참새'
console.log(anotherAnimals); // '개', '고양이', '참새', '비둘기'
  • 배열에서 spread 연산자를 여러번 사용 할 수도 있다.
const numbers = [1, 2, 3, 4, 5];

const spreadNumbers = [...numbers, 1000, ...numbers];
console.log(spreadNumbers); // [1, 2, 3, 4, 5, 1000, 1, 2, 3, 4, 5]

rest

spread랑 생김새는 비슷한데, 역할이 매우 다름. rest는 객체, 배열, 그리고 함수 파라미터에서 사용가능.

  • rest 는 객체와 배열에서 사용 할 때는 이렇게 비구조화 할당 문법과 함께 사용.
const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...rest } = purpleCuteSlime;
console.log(color); // purple
console.log(rest); // Object {name: "슬라임", attribute: "cute"} -> color 값을 제외한 값이 들어있음.
  • attribute까지 없앤 새로운 객체를 만들고 싶다면?
const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...cuteSlime } = purpleCuteSlime;
console.log(color); // purple
console.log(cuteSlime); // Object {name: "슬라임", attribute: "cute"}

const { attribute, ...slime } = cuteSlime;
console.log(attribute); // cute
console.log(slime); //Object {name: "슬라임"}
  • 함수 인자와 spread
function sum(...rest) { // 파라미터 -> rest
  return rest.reduce((acc, current) => acc + current, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];
const result = sum(...numbers); // 인자 -> spread
console.log(result);

Scope


Scope 란, 우리가 변수 혹은 함수를 선언하게 될 때 해당 변수 또는 함수가 유효한 범위를 의미.

  1. Global(전역) Scope → 코드의 모든 범위에서 사용 가능
  2. Function(함수) Scope → 함수 안에서만 사용이 가능.
  3. Block(블록) Scope → if, for, switch, 등 특정 블록 내부에서만 사용이 가능.

var vs const,let

const 로 선언한 값은 Block Scope 로 선언이 됩니다. 따라서, if 문 같은 블록 내에서 새로운 변수/상수를 선언하게 된다면, 해당 블록 내부에서만 사용이 가능하며, 블록 밖의 범위에서 똑같은 이름을 가진 값이 있다고 해도 영향을 주지 않음. let도 마찬가지

하지만 var 는 Function Scope 로 선언이 되므로, if 문 블록 내부에서 선언한 value 값이 블록 밖의 value에도 영향을 미침.

Hoisting

호이스팅이란, 자바스크립트에서 아직 선언되지 않은 함수/변수를 “끌어올려서" 사용 할 수 있는 자바스크립트의 작동 방식을 의미. 함수 안에 있는 선언들을 모두 끌어 올려서 해당 함수 유효 스코프의 최상단에 선언하는 것을 말함.

letconstvar 처럼 호이스팅이 일어난다.(방식이 다름) var (자바스크립트 엔진이 호이스팅이 일어나면 변수선언과 초기화를 동시에 함 그래서 참조가 가능)와 다르게 letconst 는 호이스팅이 일어나서 변수 선언을 하고 초기화 되기전까지 TDZ라는 곳에 머물러 초기화가 될 때까지 잠시 ‘죽어있는 상태’ 이기 때문에 초기화 전에 참조가 불가능 함. 즉, 스코프에 진입할 때 변수가 선언만되고 TDZ(Temporal Dead Zone → 일시적 사각지대)가 생성되어, TDZ에 있기 때문에 코드 실행이 변수가 실제 있는 위치에 도달하기 전에는 액세스할 수 없다는 것.

hoisting은 자바스크립트 엔진이 갖고 있는 성질이며, 호이스팅을 일부러 할 필요는 없지만, 방지하는 것이 좋다. → 호이스팅이 발생하는 코드는 이해하기 어렵기 때문에 유지보수도 힘들어지고 의도치 않는 결과물이 나타나기 쉬움. 호이스팅 방지를 위해 const, let 위주로 사용하고(호이스팅 되도 에러가 뜨니까), 함수는 꼭 선언 후에 호출을 하도록 주의하는게 좋다.

개발을 본격적으로 하게 될 때에는 ESlint 라는것을 사용하여 hoisting이 발생하는 코드는 에디터상에서 쉽게 발견할 수 있음.


참고 - 벨로퍼트와 함께하는 모던 자바스크립트(https://learnjs.vlpt.us)

profile
https://yeopto.github.io로 이동했습니다.

0개의 댓글