source : 드림코딩 js기초6
class에는 fields와 methods가 들어있는데 그 fields만 들어있는 경우 data class라고 불린다. 캡슐화, 상속, 다형성.
class는 template, 청사진이라고도 불림. class자체에는 데이터가 들어있지 않고 틀만 정해놓음.
이 class에 실제로 데이터를 넣어서 만드는 것이 object다. 그래서 클래스를 이용해서 새로운 인스턴수를 생성하면 object가 된다.
object-oriented programming
class: template
object: instance of a class
JavaScript classes
-introduced in ES6
-syntactical sugar over prototype-base inheritance
js에 class는 추가된지 얼마되지 않음. 그 전에는 클래스를 정의하지 않고 object를 만들었고 function을 이용해서 템플릿을 만들었음. class는 완전히 새롭게 추가된것이 아니라 기존의 프로토타입을 베이스로 그 위에 우리가 간편하게 쓸 수 있도록 문법만 클래스가 추가된 것이다. 문법상으로 달달한 편리함(syntactical sugar)
class Person{
//constructor
constructor(mname, age){
//fields
this.mname = name;
this.age = age;
}
//method
speak(){
console.log(${this.mname}: hello!
);
}
}
const ellie = new Person('ellie', 20);
console.log(ellie.name);
console.log(ellie.age);
ellie.speak();
setter는 사용자의 입력범위를 제한함.
getter를 정의하는 순간 this.age는 메모리에 올라가 있는 데이터를 읽어오는 것이 아니라
바로 getter를 호출하게 된다.
setter를 정의하는 순간 equal sign ()= age;) 즉, 값을 할당할 때 바로 메모리에
값을 할당하는 것이 아니라 setter를 호출한다.
그래서 getter와 setter는 메모리에 값을 할당하는 것이 아니라 계속 setter getter 무한 호출로 콜 스택이 초과됨.
따라서 getter, setter안에서 쓰이는 변수의 이름을 조금 다른 걸로 만들어줘야한다.
⭐ 결국 User class안의 fields는 firstName, lastName, _age 3개다.
field에는 _age지만 우리가 .age라고 호출할 수 있는 것, 그리고 .age에 값을 할당할 수 있는 것은 내부적으로 getter와 setter를 이용하기 때문임.
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get age(){
return this._age;
}
set age(value){
// if(value < 0){
// throw Error('age can not be negative');
// }
this._age = value < 0 ? 0 : value;
}
}
const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age);
너무 최근에 추가됨.
class Experiment {
publicField = 2; //public
#privateField = 0;// private 외부에서 접근 불가능
}
const experiment = new Experiment();
너무 최근에 추가됨.
object와 데이터에 상관없이 클래스에서 동일하게 반복적으로 사용되어지는 field와 method에 static키워드를 붙인다.
class Article{
static publisher = 'Dream coding';
constructor(articleNumber) {
this.articleNumber = articleNumber;
}
static printPublisher() {
console.log(Article.publisher);
}
}
console.log(Article.publisher);
Article.printPublisher();
a way for one class to extend another class
class Shape {
constructor(width, height, color){
this.width = width;
this.height = height;
this.color = color;
}
draw() {
console.log(`drawing ${this.color} color of`);
}
getArea(){
return width * this.height;
}
}
class Rectangle extends Shape {}
class Triangle extends Shape {
draw (){ // 오버라이딩
super.draw(); //부모의 super 호출
console.log('?');
}
getArea(){ //오버라이딩
return (this.width*this.height) / 2;
}
toString(){ //오버라이딩
return `Triangle: color: ${this.color}`;
}
}
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
const triangle = new Triangle(20, 20, 'red');
triangle.draw();
object가 해당 클래스를 이용해서 만들어진 instance인지 확인
console.log(rectangle instanceof Rectangle);
console.log(triangle instanceof Triangle);
console.log(triangle instanceof Rectangle);
console.log(triangle instanceof Shape);
console.log(triangle instanceof Object); //js의 모든 object는 Object를 상속받음.
console.log(triangle.toString());
👍 js reference MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
source : 드림코딩 js기초7
Objects
one of the JavaScript's data types.
a collection of related data and/or functionality.
Nearly all objects in JavaScript are instances of Object.
object = {key : value};
오브젝트는 key와 value의 집합채.
object는 중괄호를 이용해서 생성 또는 new 키워드 Object 클래스로 생성
첫번째 방법을 'object literal' syntax
두번째 방법을 'object constructor' syntax
const obj1 = {}; //'object literal' syntax
const obj2 = new Object();//'object constructor' syntax
function print(person){
console.log(person.mname);
console.log(person.age);
}
const ellie = {mname: 'ellie', age: 4};
//클래스가 없어도 괄호를 이용해서 오브젝트 생성
print(ellie);
with JavaScript magic(dynamically typed language)
con add properties laters
js는 런타임때 타입이 결정되므로
object 선언한 뒤에 프로퍼티를 추가하거나 삭제할 수 있다.
ellie.hasJob = true;
delete ellie.hasJob;
object안의 데이터를 접근할 때 '.'을 이용하거나 대괄호안에 스트링 형태의 데이터 이름으로 접근 가능.
후자의 방법을 Computed properties라고 함. 이때 key should be always string
전자의 방법은 코딩하는 그 순간 그 key에 해당하는 값을 받아오고 싶을때 사용.
Computed properties는 우리가 정확하게 어떤 key가 필요한지 모를 때 즉, 런타임에서 결정될 때 사용한다.
다시 말해, 실시간으로 원하는 key의 값을 받아오고 싶을 때 사용.
console.log(ellie.name);
console.log(ellie['name']);//object안의 변수 이름의 스트링 형태로 접근 가능.
ellie['hasJob'] = true; //computed properties를 이용한 프로퍼티 추가
⭐ 사용자에게 특정 key를 input받아서 value를 출력해야하는 함수라면
코딩하는 시점에는 어떤걸 출력할지 전혀 모른다.
그래서 이때는 computed properties를 써야한다.
동적으로 key에 관한 value를 받아와야할 때 유용하게 사용한다.
function printValue(obj, key){
// console.log(obj.key); -> object에 'key'라는 프로퍼티가 들어있지 않으므로 undefined 리턴
console.log(obj[key]);
}
printValue(ellie, 'name');
function에서 object 리턴할 때 key와 value가 동일하다면 생략할 수 있음.
const person1 = {mname: 'bob', age: 2};
const person2 = {mname: 'bob', age: 2};
const person3 = {mname: 'bob', age: 2};
object가 필요할때 일일이 만들게 되면 반복되는 key를 계속 작성해야하는 불편.
그래서 값만 전달해주면 object를 만드는 함수를 만듦.
즉, class(template)과 같은 역할.
const person4 = makePerson('ellie', 30);
console.log(person4);
function makePerson(name, age){
return { //object를 리턴
name, //key와 value가 동일하면 생략 가능.
age,
};
}
그래서 다른 계산을 하지 않고 순수하게 object를 생성하는 함수들은 class처럼 대문자로 시작하는 name으로 만들고 return을 하지 않고 constructor에서 했던 것처럼 this.name=name; 으로 작성함.
그리고 호출할때도 new 키워드를 사용해서 new Person()으로 사용한다.
js엔진이 알아서 object를 생성함.
const person5 = new Person('kwang', 29);
console.log(person5);
function Person(name, age){
// this = {}; -> 생략된 부분: 새로운 object 생성
this.name = name;
this.age =age;
//return this; -> 생략
}
obj안에 해당 키가 있는지 확인
console.log('name' in ellie);
for(let key in ellie){ //key들을 하나씩 받아옴
console.log(key);
}
//for (value of iterable)
//object를 쓰는 것이 아니라 배열과 같은 순차적인 구조에 해당.
const array = [1,2,3,4];
for(let value of array){
console.log(value);
}
Object.assign(dest, [obj1, obj2, obj3...])
🍀 object를 할당하게 되면 같은 obj를 가리키게 된다.
const user = {mname: 'ellie', age: '20'};
const user2 = user;
user2.mname = 'kwang';
console.log(user);
🍀 그럼 obj 내용을 복사하는 방법은? cloning
old way: 빈 obj를 만들고 수동으로 반복하면서 value를 할당.
const user3 ={};
for(let key in user){
user3[key] = user[key]; //새로운 프로퍼티 key를 만들고 value를 넣는다.
}
console.log(user3);
Object.assign(붙여넣기할 target, 복사되는 변수) 그리고 섞인 변수가 리턴.
const user4 = Object.assign({}, user);
console.log(user4);
another example
const fruit1 = {color : 'red'};
const fruit2 = {color : 'blue', size: 'big'};
const mixed = Object.assign({}, fruit1, fruit2);
console.log(mixed.color); //뒤에 나오는 변수가 있고 동일한 프로퍼티가 있다면 값을 계속 덮어씌워진다.
console.log(mixed.size);
👀 object와 자료구조의 차이점: object는 서로 연관된 특징과 행동들을 묶어 놓는 것. 그리고 비슷한 타입의 object들을 묶어놓는 것을 자료구조라고 함. 다른 언어에서는 동일한 타입의 object만 자료구조에 담을 수 있지만 js는 dynamically typed language기 때문 한 바구니 안에 여러 타입의 데이터를 담을 수 있다. 하지만 그렇게 하지 않는 것이 좋다.
source : 드림코딩 js기초8
const arr1 = new Array();
const arr2 = [1,2];
const fruits = ['🍎' , '🍌'];
console.log(fruits);
console.log(fruits.length);
console.log(fruits[0]);
console.log(fruits[fruits.length -1]);
console.clear();
for (let i = 0; i < fruits.length; i++){
console.log(fruits[i]);
}
for (let fruit of fruits){
console.log(fruit);
}
배열 안의 value들마다 내가 전달한 함수를 실행한다.
fruits.forEach(function (fruit, index) {
console.log(fruit, index);
});
anonymous function은 arrow함수 쓸 수 있다.
한 줄의 경우, 괄호와 세미콜론 필요없다.
fruits.forEach((fruit, index) => console.log(fruit, index));
fruits.push('🍓','🍑');
삭제하고 그 삭제된 원소를 리턴함.
fruits.pop();
fruits.pop();
console.log(fruits);
fruits.unshift('🍆', '🌽');
console.log(fruits);
fruits.shift();
fruits.shift();
console.log(fruits);
📌 note!! shift, unshift are slower than pop, push
맨 앞을 삽입하거나 삭제하기 위해서 그 뒤의 모든 원소를 밀어내거나 당겨와야하기 때문에 오래걸린다.
splice(시작 인덱스, 삭제할 개수): '삭제할 개수'를 지정 안하면 시작인덱스부터 끝까지 지운다.
splice(시작 인덱스, 삭제할 개수, 삽입원소1, 삽입원소2...): 또한 삭제한 그 자리에 새로운 원소 삽입 가능.
그리고 return은 삭제된 요소들이 리턴.
삭제할 개수가 0인 경우, 삽입만 할 수 있다.
fruits.push('🥑', '🍋', '🍊');
fruits.splice(1, 1);
console.log(fruits);
fruits.splice(1, 1, '🍏','🍐');
console.log(fruits);
const fruits2 = ['🍒','🌶'];
const newFruits = fruits.concat(fruits2);
console.log(fruits.indexOf('🍎'));
console.log(fruits.includes('🍌')); // false, 해당 원소가 포함되어있는지
fruits.push('🍎');
console.log(fruits.indexOf('🍎'));
console.log(fruits.lastIndexOf('🍎'));
source : 드림코딩 js기초9
// Q1. make a string out of an array
{
const fruits = ['apple', 'banana', 'orange'];
const res = fruits.join();
console.log(res);
}
// Q2. make an array out of a string
{
const fruits = '🍎, 🍌, 🍒, 🍏';
const res = fruits.split(',', 2); //2 -> 앞에서 두개만 나오도록 제한할 수 있다.
console.log(res);
}
// Q3. make this array look like this: [5, 4, 3, 2, 1]
{
const array = [1, 2, 3, 4, 5];
const res = array.reverse();
console.log(res);
console.log(array);//기존 배열도 reverse된다
}
// Q4. make new array without the first two elements
{
const array = [1, 2, 3, 4, 5];
//splice는 제거된 원소들의 배열을 리턴하고 기존 배열은 남은 원소들로 변경된다
const res = array.splice(0, 2);
console.log(res);
console.log(array);
//slice는 배열의 특정부분을 배열로써 리턴하고 기존 배열을 변하지 않는다.
//end index는 제외된다는 점을 주의하자.
//Returns a copy of a section of an array.
const array2 = [1, 2, 3, 4, 5];
const res2 = array2.slice(2, 5);
console.log(res2);
console.log(array2);
}
class Student {
constructor(name, age, enrolled, score) {
this.name = name;
this.age = age;
this.enrolled = enrolled;
this.score = score;
}
}
const students = [
new Student('A', 29, true, 45),
new Student('B', 28, false, 80),
new Student('C', 30, true, 90),
new Student('D', 40, false, 66),
new Student('E', 18, true, 88),
];
// Q5. find a student with the score 90
{
//find: Returns the value of the first element in the array where predicate is true, and undefined
//콜백함수가 true를 리턴하면 즉시 중단하고 그때의 원소를 리턴함.
const res = students.find((student) => student.score === 90);
console.log(res);
}
// Q6. make an array of enrolled students
{
//filter: Returns the elements of an array that meet the condition specified in a callback function.
//조건에 맞는 원소들을 리턴한다. 콜백함수에서 true를 리턴하면 조건에 맞는거다.
const res = students.filter((student) => student.enrolled);
console.log(res);
}
// Q7. make an array containing only the students' scores
// result should be: [45, 80, 90, 66, 88]
{
//map: 배열의 각 원소들을 콜백함수로 가공한 뒤 return하고 그 원소들(results)의 배열을 리턴함.
const res = students.map((student) => student.score);
console.log(res);
}
// Q8. check if there is a student with the score lower than 50
{
//some: 배열의 각 원소들에 대해 콜백함수에서 true를 리턴하는 원소가 있는지 탐색함.
const res = students.some((student) => student.score < 50);
console.log(res);
//every: 배열의 모든 원소들이 콜백함수에서 true를 return하는지 확인.
const res2 = !students.every((student) => student < 50 );
console.log(res2);
}
// Q9. compute students' average score
{
//reduce: 누적된(accumulated) 정보를 얻을 때 사용함.
//리턴된 값을 다음 콜백함수의 prev인자로 씀.
//초기값(init) 설정있음.
// const res = students.reduce(function(prev, curv) {
// return prev + curv.score;
// }, 0);
const res = students.reduce((prev, curr) => prev + curr.score, 0);
console.log(res / 5);
}
// Q10. make a string containing all the scores
// result should be: '45, 80, 90, 66, 88'
{
const res = students.map((student) => student.score).join();
console.log(res);
}
// Bonus! do Q10 sorted in ascending order
// result should be: '45, 66, 80, 88, 90'
{
//sort: 이 메서드는 배열을 변경하고 동일한 배열에 대한 참조를 반환합니다.
//a - b에서 음수가 나오면 b가 크다는 뜻이므로 정렬된다.
const res = students.map((student) => student.score)
.sort((a, b) => a - b)
.join();
console.log(res);
}