변수 : 데이터의 개념
속성 : 성질을 나타내는 것
변수는 혼자 존재해도 가능하지만, 속성은 단독으로 존재하면 의미를 가질 수 없다.
속성(attribute, property, column, field)
- table에서 세로 방향인 것
함수 vs 메서드 : 리시버가 있느냐 없느냐 차이였다.
객체 생성 :
사용자 정의 객체 생성 : var(let, const) 객체명 = {속성이름:데이터,..}
built-in obj나 직접 생성자 만든 경우 : var 객체명 = 생성자메서드(매개변수)
객체의 요소 접근
- 객체명[속성이름] or 객체명.속성이름(이것을 권장합니다.)
- why? : 후자가 대부분의 언어에서 지원하기 때문입니다.
function - method
- 속성 안에 메서드를 작성하거나 대입하는 것이 가능
- 객체를 통한 내부 메서드 호출 : 객체.메서드(매개변수)
CRUD
upsert : 있는 속성이라면 update, 없다면 insert
delete : 지우고 싶은 객체이름.속성
코드 예시
let human=[{name:"이민호",age:26,gender:"male"}, {name:"최종원",age:26,gender:"male"}] let human2={name:"이민호",age:26,gender:"male"} // 이렇게 출력시, type을 보여준다. 속성까지 가야지 값을 보여준다. document.write(human) // 이래야 값이 나오겠지? document.write(human[0].name, human[0].age, human[0].gender) //이건 for문으로 둘다 출력하기야 for(let i=0; i<2; i+=1){ document.write(human[i].name, human[i].age, human[i].gender) document.write("<br/>") }
이렇게 python에서도 위와 같이 사용자 정의 객체를 선언한다.
이때 document.write(human)
을 출력하면 다음과 같다.
[object Object]
이는 앞에는 자료형 뒤에는 실제 변수명인데 지을게 없어서 오브젝트라 한거야.
?
나는 배열 한칸에 속성을 3개나 넣어놨는데 왜 한개치만 나오는거지?
그건 바로 human배열의 BOF(Begin of File)을 가리키고 있기에 한개만 나오는 거야. 맨 끝은 EOF(End of File) 이다. for문은 EOF를 만날때 까지이다. 결국 하나만 나온 건 BOF를 가리키기 때문에 맨 처음 하나만 나온거야.
[] : 배열 리스트, {} : 객체
배열은 index를 가지고, 객체는 이름을 가지고 찾는다.
이름을 가지고 찾는게 더 좋다. 이름을 기억하는게 더 쉽다. 번호보다.
let obj={name:"mino",disp:function(){ alert(this.name) }}
이렇게 하지 않으면 name은 출력이 안된단다. undefined로 됩니다.
this내가 속한 객체에서만 찾는다. 상위클래스는 super이다.
obj.disp(): 호출, obj.disp : 함수의 내용
동일한 모양의 인스턴스를 편리하게 생성하기 위한 방법
- Class 이다.
생성자 : new 생성자이름(매개변수) 이게 객체 생성방법
new는 프로그래머에게 굉장히 중요하다.
new는 heap영역에 만들자는 것이다.
heap영역은 가리키는게 없어지면 메모리 해제가 된다.
JS 에서 영구적인 부분에는 Function, Class, 문자열상수가 들어가진다.
영구적인부분과 Heap은 합쳐서 용량계산을 한다. 영구적인 부분은 개발자가 바로 부를 수 있다.
temporary: Stack은 실행을 위해 임시 저장 영역(Stack은 자료구조)
static : 영구적이다 지울 수 었다.
dynamic : 썼다가 지웠다 할 수 있다.(Heap 자료구조)
//생성자가 없는 경우 동일한 모양의 2개의 객체 생성 let ar=[ {name:"mino", disp:function(){document.write(this.name)}}, {name:"mino2", disp:function(){document.write(this.name)}} ] for(idx in ar){ ar[idx].disp() document.write("<br/>") } // 잘 찍히긴 하지만 함수가 중복되어 있는 형태이다. 이를 어떻게 해야 할까? //생성자를 만들어보자. - 왜 생성자야? : 함수 안에서 this를 사용했기 때문이다. //일반함수는 this를 사용할 수 없다. let person=function(name){ this.name=name; this.disp=function(){document.write(this.name)} } // 이렇게 한다면 disp를 두번 하는게 아니다. //메서드는 다시 만들지 않고 속성만 설정해서 인스턴스 생성하기에 생성자를 쓴다. //생성자를 이용해서 인스턴스를 만들 떄는 new와 함께 호출해야 한다. // 그렇게 한다면 heap 공간에 인스턴스를 생성한다. ar=[new person("mino"),new person("mino2")] for(idx in ar){ ar[idx].disp() document.write("<br/>") }
동일한 역할을 하는데 더 효율적인걸?
바로 생성
- 생성 이름 : 데이터
생성자를 이용하는 방법
- 함수를 만들 때, 내부에서 this를 이용해서 속성과 메서드를 생성
Class를 만들고 생성하는 방법(권장)
- Class : 동일한 인스턴스를 만들기 위한 모형
- 만들 때 :
let 클래스 이름 = class{ constructor(매개변수){내용}메서드 나열}
- 클래스를 이용해서 인스턴스 생성 방법
new 클래스이름(매개변수);
클래스 이름을 적지만 실제로는 constructor가 호출
- Constructor(생성자)는 default로 존재하며, 초기화가 목적임
python은 __init__이 생성자이다.
- 생성자 역할 : 1. heap에 공간 할당(allocation), 2. 내부 초기화(init)
// class를 생성하고 인스턴스 생성 let Member = class{ //관습적으로 클래스는 앞글자 대문자 //생성자 constructor(name){ this.name=name } //클래스 안에 메소드를 만들 때에는 let이나 function 생략 가능합니다. disp(){ document.write(this.name); document.write("<br/>"); } } ar=[new Member("mino"), new Member("mino2")] for(idx in ar){ ar[idx].disp() }
Class가 아니라면 내부 데이터 형태를 직접 확인해야 하는 문제가 있다.
Class가 있다면 내부 데이터가 어떤 것인지 클래스만 보고 판단 가능하다.
Class = 스키마 = 테이블 (릴레이션) : 근본적으로 다 같은 말입니다.
클래스를 설계한다면 디자인패턴, UML등을 공부하게 된다.
스키마, 테이블 설계 : 모델링 이라고 부른다.
(어떤 것을 하나로 묶는게 가장 효율적인 것일까요?)
하나의 스키마에는 배열이 존재하면 안된다.
modeling을 클래스에서 한다면 객제지향설계라고한다.
{} : 모든 데이터에는 이름이 있어야 하며, meta데이터로 데이터를 설명해주는 것이 있어야 한다.
let Person =class{ //이번에는 생성자 parameter가 2개이다. constructor(name, score){ this.name=name; this.score=score; } disp(){ console.log(this.name+":"+this.score) } // 은행의 잔액(속성)은 은행원(메서드)를 통해 변경이 가능한 것이다. // 왜냐하면 근본적으로 데이터는 syncronized가 안된다. //이를 메서드를 통해서 하는 것이다. //getter getName(){ return this.name } //setter setName(name){ this.name=name } getScore(){ return this.score } setScore(score){ //유효성 검사 : 올바른 데이터인지 확인하는 것이다. if(score<0 || score>100){ alert("적절하지 않은 점수입니다!") return // 대입하지 않고 나가버리기 } this.score=score } } let obj=new Person("mino",90); obj.setScore(150); obj.disp();
common concern & business logic
- 둘은 명확하게 구분되어야 한다. 실제 업무가 무엇인지 알아두자
- common concern : 실제 업무와는 상관 없는 작업(나중에 처리되도 된다)
- business logic : 실제 업무와 관련된 것(바로바로 처리)
A 클래스를 만들었어요. b, c 기능이 들어있는
B 클래스를 만들었어요. c, d 기능이 들어있는
똑같은거 2개 쓰는건 안좋다.
Super 클래스 C를 만들어 c 기능을 두고, A,B 클래스에 b와 d만 넣자.
그리고 작성할 때, A class extends Super{
하면 된다.
이미 만들어진 클래스를 상속받는 경우(AA')
프로그램을 만들 때 많이 쓰는 애들을 만들어줌(Framework) : A
A는 기본적인 것만 들어있는 것이다.(한 80% 제공이라 가정하자)
근데 부족하다고 100%짜리를 새로 만드는 것 보다는
A를 extends를 하는 것이다. 결국 나는 20%만 만드는 것이다.
let Super =class{ //class Super{}이것도 가능하긴 함 method(){ console.log("상위 클래스의 메서드에요") } } class Sub extends Super{ //여긴 method()가 없죠? } let obj = new Sub(); obj.method() //하지만 나오죠? //Sub에는 method가 없지만, 상속을 받아서 호출이 가능함 let Sub2= class extends Super{ } let obj2=new Sub2(); obj2.method()
무엇인가를 만들 때에는 Super를 먼저 씁니다.(안쪽)
대신 파괴 할 때에는 Super를 나중에 없애버립니다.(바깥쪽)
서브의 메모리를 해제하고 상위의 메모리를 해제해야 한다.
Super가 먼저 망가지면 안된다.
class Sub extends Super{ method(){ super.method(); console.log("상위 클래스의 메서드 재정의") } }
하위 클래스의 메서드에서 상위 클래스의 메서드를 호출할 때는 super.메서드이름()을 하면 됩니다.
오버라이딩을 한다면 하위 클래스에서는 상위 클래스의 메서드를 호출해야 한다. why?
let str="Hello"
: 문자열 상수는 static한 영역으로 들어갑니다.
-str = str + "world"
이는 굉장히 나쁘게 취급합니다.
- 등호 왼쪽은 이름이 아니기에 "Hello"로 바뀐다. static에 들어간 문자열 상수는 절대 못바꾼다.
- 그렇다면 Hello를 새로 복사해서 world를 붙이고 str에게 가리키라고 합니다. (Memory Leak)
- 그러면 기존에 있던 Hello는? : 쓸 수 없다. 정리도 안된다.
String toUpperCase("Hello")
이친구는 return을 한다.
출력하는 메서드는 원본을 변경하거나 return을 해줘야 합니다.
알아두면 좋은 메서드 indexOf()
인덱스를 찾는다면 위치를 알려주지만, 찾지 못했다면 -1 을 출력한다.
-1 : 큰 수, 내가 끝까지 갔는데 찾지 못했다.
그래서indexOf(~~) == -1
이런걸로도 쓴다. 이게 진짜 중요하다.
let company=" minoCNS " //company_up=String.toUpperCase(company) // 이게 안되네? company_up=company.toUpperCase(); console.log(company) console.log(company_up) console.log(company.indexOf("pa")) // 없으니 -1 //이번엔 모두 대문자로 변경하고 좌우 공백을 제거해야 한다. //-> 생각할 것이 좀 있어요 이거 company_trim=company.trim(); // trim을 하고 upper를 해야겠네? //-> 왜냐 upper할때 공백도 변경할것인가? company_trimUp=company_trim.toUpperCase(); //이렇게 해도 된다? company_last=company.trim().toUpperCase(); console.log(company_trimUp.indexOf("MIN")) //아래 파일 명에서 확장자를 추출해보자. let filename="mino.hwp" let file=filename.split('.') console.log(file[1])
let ar=[23,39,17,27,44] // 데이터 개수 파악 console.log(ar.length) // 데이터 순회 for(idx in ar){ console.log(ar[idx]) } // 데이터 순회하면서 작업하기 - forEach // 데이터 처리에 용이하다. // 배열을 순회하면서 데이터를 하나씩 접근하는 함수 // 첫 번째는 데이터 두번쨰는 인덱스 세번째는 배열 ar.forEach((element, idx, array)=>{ console.log(array) }) // 데이터 변환 (map) // map은 사용하는 형태는 forEach와 동일하지만 // 함수가 데이터를 리턴해야 합니다. // 리턴한 데이터를 모아서 다시 배열로 만들어서 리턴합니다. let r=ar.map((element, index, array)=>{ return element+1 }) console.log(r) // 데이터 필터링 arr=ar.filter((element, index, array)=>{ return element%2==1 }); console.log(arr)
let list=[ {name:"Kim", gender:"남"}, {name:"Lee", gender:"남"}, {name:"Park", gender:"여"} ] // gender가 남인 데이터 추출하기 let new_list=list.filter((element, index, array)=>{ return element.gender==="남"; }) console.log(new_list)
let list=[ {name:"Park", gender:"남", age:23}, {name:"Lee", gender:"남", age:19}, {name:"Kim", gender:"여", age:20} ] let ar=[23,39,167,27,44] // gender가 남인 데이터 추출하기 let new_list=list.filter((element, index, array)=>{ return element.gender==="남"; }) console.log(new_list) // 정렬은 sort 함수를 호출하면 됩니다. // 기본적으로 오름차순 정렬을 합니다. // 크기 비교가 가능한 데이터만 정렬을 수행할 수 있습니다. // sort는 호출한 배열의 데이터를 직접 조작합니다. ar.sort() //console.log(ar) //자릿수가 다르면 정렬이 잘 안되는 것을 볼 수 있다. // why? : JS에서 하는 소트 방식이 뭐길래? // 직접 크기비교를 하는 방법을 안합니다. // 첫번째 글자가 뭐네~ 이러면서 정렬을 하기에 자릿수 문제가 있다. // 정렬할 때 크기비교 함수를 대입받아서 사용자 정의 정렬을 지원 // 함수의 모양은 매개변수가 2개이고 정수를 리턴해야 합니다. // 앞의 데이터가 크다고 판단하면, 양수를 리턴하면 됩니다. 관습적으로 1 // 같으면 0 작으면 음수 -1 관습적이야. ar.sort((left,right)=>{ return left-right } )// 이 모양은 파이썬에서도 똑같아 // // 정렬을 하려면 크기비교를 할 수 있도록 해야한다. console.log(ar) list.sort() console.log(list) // 이건 될것 같아? 객체는 객체끼리 비교 x 속성이 여러개 // 그럼 그 안에 있는 속성끼리 비교해야한다. list.sort((left,right)=>{ return left.age-right.age }) console.log(list) //문자가 빼기는 안되는데 크기 비교는 할 수 있다. list.sort((left,right)=>{ if(left.name>right.name){return 1} else if(left.name==right.name){return 0} else{return -1} }) console.log(list) // 이렇게 하면 김이박 순으로 나온다. 내림차순을 하려면 부등호 방향 바꾸기 // 우리나라는 자음으로 그룹화 // -> 가보다 크고 나보다 작은거 : ㄱ으로 시작하는 단어 alert(navigator.userAgent)
데이터를 순서대로 나열하는 것
오름차순(Ascending - 기본) : 작은 것에서 큰 것 순으로 나열
내림차순(Dscending) : 큰 것에서 작은 것 순으로 나열
다양한 알고리즘을 이용해서 정렬을 수행할 수 있는데,Quick Sort나 Merge Sort 정도는 알고 있으면 면접에 도움이 됩니다.
<div id="display"></div> <input type="text" id="name"/> <button id ="btn">버튼</button> <script> document.getElementById("btn").addEventListener("click",(e)=>{ document.getElementById("display").innerHTML= document.getElementById("name").value; }) </script>
밥짓기와 빨래를 한다고 하자.
동기 : 밥을 다 지을때까지 빨래를 안함
비동기 : 밥을 짓고 남은 시간에 빨래를 하러감
이때, 알람이 없다면 비동기가 어려울 것이다.
참고 : electron 에서 실행파일 만들 때
package.json 수정할 때 mac winodws 맞춰서 설정해주기(주변에 적혀있으니 참고)