사용자 정의 데이터 타입
• 회원정보, 영화정보, 주문정보와 같은 복합 데이터는 낱개의 변수를 사용하여 다루는 것보다 별도의 타입을 정의하여 한 단위로 묶어서 다루는 것이 편하다.
‐ 복합데이터 : 여러 개의 항목으로 구성된 데이터
‐ 회원정보(번호, 이름, 이메일, 전화, 주소 등)
영화정보(영화명, 설명, 제작사, 주연배우, 개봉일 등)
• 자바에서 제공하지 않는 데이터 타입을 정의할 때 사용하는 문법이 클래스이다.
규모가 작을 때는 안 묶어도 되는데 규모가 커지면 묶는다.
C → 구조체(structure)
C++ → 클래스
점점 규모가 커지니까 많은 코드를 다루기 편하게
데이터를 묶어서 다루는 문법이 등장
MyList App 실행하기
com.eomcs.mylist.Contact 클래스 정의
클래스는 2가지 용도로 쓴다.
① 데이터 타입 정의 (user-defined Data Type)
user → 개발자
② 메서드 분류
메서드를 묶는다.
클래스 문법이 뭐냐?
→ 데이터 타입을 정의하거나 메서드 분류하는 용도로 사용하는 문법입니다.
메모리 설계도
class 데이터타입명 {
변수 선언
...
}
class Contact {
String name;
String email;
String tel;
String company;
}
⇒ 메모리 설계도
new 명령을 실행하면 클래스에 정의된 대로 변수가 준비된다.
new 데이터타입명();
데이터타입명 = 클래스명
클래스 설계도에 따라 변수(메모리) 준비 ⇒ Heap 영역에 준비됨
클래스 설계도에 따라 준비한 메모리 ⇒ '인스턴스(instance)=객체(object)'라고 한다.
주소를 받을 변수
데이터타입명 주소를 받을 변수 = new 데이터타입명();
Contact c = new Contact();
Contact 인스턴스의 주소를 저장하는 변수 = 레퍼런스(reference)
인스턴스의 주소를 저장
com.eomcs.mylist.Contact.java
package com.eomcs.mylist;
public class Contact {
String name;
String email;
String tel;
String company;
}
com.eomcs.mylist.ContactController 클래스 변경
‐ 배열 변수 변경
레퍼런스 : 인스턴스의 주소를 저장하는 변수
C에서는 포인터(pointer)라고 한다.
Contact 설계도에 따라 준비한 메모리 ⇒ Contact의 인스턴스 ⇒ Contact의 객체
① 배열 사용 전
② 배열 사용 후
레퍼런스는 주소를 담는 거!
레퍼런스 배열 → 레퍼런스 변수를 한 번에 만든 거
자바에는 인스턴스 배열을 만드는 문법이 없다.
클래스 정의한 거 안에 있는 인스턴스는 Heap에 만들어진다.
클래스를 정의만 해놓고 사용을 하지 않으면 메모리에 올라가지 않는 거?
⇒ Method Area에 올라간다!
인스턴스와 인스턴스는 연속된 메모리가 아니다. 보장하지 않는다.
new 라는 명령어로 만드는 모든 변수는 Heap 영역에 올라간다.
레퍼런스 배열을 만들었다고 인스턴스가 존재하는 게 아니다.
이 선언은 레퍼런스 배열만 만든 상태
Contact[] contacts = new Contact[5];
레퍼런스 배열을 만든다.
Contact[] arr = new Contact[size];
@RequestMapping("/contact/list")
public Object list() {
Contact[] arr = new Contact[size]; // 배열에 저장된 값만 복사할 새 배열을 만든다.
for (int i = 0; i < size; i++) {
arr[i] = contacts[i]; // 전에 배열에서 값이 들어 있는 항목만 복사한다.
}
return arr; // 복사한 항목들을 담고 있는 새 배열을 리턴한다.
};
com.eomcs.mylist.ContactController 클래스 변경
‐ list() 변경 ⇒ 웹 브라우저로 응답 결과 확인
public Object add(Contact contact)
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.printf("%s,%s,%s,%s\n", contact,name, contact.email, contact.tel, contact.company);
/*
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = createCSV(name, email, tel, company);
*/
return size;
}
http://localhost:8080/contact/add?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=abc
null 나옴
com.eomcs.mylist.Contact.java 가서
오른쪽 마우스 클릭 - Source - Generate Getters and Setters... 클릭
Select All 클릭 - Generate 클릭
Select All → 모든 변수에 대해서 다 게터 세터를 만들겠다
실무에서는 롬복이라고 불리는 api가 있음
롬복을 쓰면 게터 세터 만들 필요가 없는데 아직 그걸 사용할 때가 아님
package com.eomcs.mylist;
public class Contact {
String name;
String email;
String tel;
String company;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println("%s,%s,%s,%s", contact.name, contact.email, contact.tel, contact.company);
/*
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = createCSV(name, email, tel, company);
*/
return size;
}
이게 스프링 부트의 최소 조건..
Generate toString()
Generate 클릭
toString()
이 안에 있는 변수를 한 줄의 문자열로 만들어서 리턴해주는 메소드
설계도에 따라서 만든 인스턴스 변수의 값을 한 줄의 문자열로 만들어서 리턴해주는 메소드
toString()
을 사용하면 메모리 안에 어떤 이름, 어떤 이메일 등이 들어있는지 꺼내 보기가 편함
package com.eomcs.mylist;
public class Contact {
String name;
String email;
String tel;
String company;
@Override
public String toString() {
return "Contact [name=" + name + ", email=" + email + ", tel=" + tel + ", company=" + company
+ "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
System.out.println(contact.toString());
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println(contact.toString());
/*
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = createCSV(name, email, tel, company);
*/
return size;
}
toString()
메서드가 한 줄의 문자열로 만들어준 걸 리턴
PCR 검사 받고 오라고 하면 굳이 말 안 해도 어떻게 해야 되는지 알고 있음
얘가 그래요
println한테 contact.toString() 메서드 호출해서 contact이 가리키는 메모리에 들어 있는 각각의 변수 값을 꺼내서 문자열을 리턴 받아서 println에 넘기는데
굳이 얘기 안 해도 됨. toString() 지우기.
굳이 얘기 안 해도 println은 객체 주소를 넘겨주면 알아서 toString() 메소드를 호출해서 그 메소드가 리턴한 값을 화면에 뿌린다. 그러므로 굳이 직접 toString() 할 필요가 없다.
내부적으로 toString() 호출
System.out.println(contact.toString());
→ System.out.println(contact);
인스턴스 안에 있는 값을 출력하고 싶으면 그냥 println 하고 인스턴스의 주소를 주면 됨
다른 작업 필요 없이 주소만 주면 됨
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println(contact);
/*
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = createCSV(name, email, tel, company);
*/
return size;
}
잘 나옴
인스턴스 안에 있는 값을 출력하고 싶으면 그냥 println 하고 인스턴스의 주소를 주면 됨
다른 작업 필요 없이 주소만 주면 됨
Spring Boot와 클래스 파라미터
① add?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=abc
웹 브라우저에서 스프링 부트에게 요청을 보내는데
add?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=abc
이렇게 값을 넘긴다
② 인스턴스 생성 → 요청 파라미터 값 저장
그러면 스프링 부트가 ContactController에 대해서 여기 있는 메소드 중에서 add 라는 메소드를 호출한다
이때 add 라는 메소드를 호출할 때 이렇게 함
new Contact() 인스턴스를 생성한다
파라미터가 Contact이기 때문
이름과 일치하는 거 찾아서 값을 저장함
변수가 아니라 세터 메소드를 찾아서 저장
③ add() 호출
바로 이 부분
Spring Boot는 페이지 컨트롤러의 요청핸들러를 호출하기 전에
add()에 선언된 클래스 인스턴스를 만든다.
요청 파라미터의 값을 그 인스턴스의 각 변수에 저장한다.
요청 파라미터 이름과 인스턴스의 세터 메서드명이 같아야 한다.
요청 파라미터 이름이 name이라면 인스턴스의 세터 메서드명은 setName()이어야 한다.
변수 이름과 일치하는 게 아니라 세터 메서드 이름과 일치해야 되는 거
게터 세터 지우고 다시 해보기
package com.eomcs.mylist;
public class Contact {
String name;
String email;
String tel;
String company;
@Override
public String toString() {
return "Contact [name=" + name + ", email=" + email + ", tel=" + tel + ", company=" + company
+ "]";
}
}
null로 나옴
변수명은 상관 없는 거
?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=비트캠프
Object add(String name, String email, String tel, String company) {...}
?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=비트캠프
Object add(Contact contact) {...}
Contact 인스턴스 만든 후에 값 저장한 후에 파라미터에 집어 넣는다
?name=aaa&email=aaa@test.com&tel=010-0000-0000&company=비트캠프
파라미터 세터 메서드
name ⟶ setName()
email ⟶ setEmail()
tel ⟶ setTel()
company ⟶ setCompany()
basicAddr ⟶ setBasicAddr()
firstName ⟶ setFirstName()
변수명은 쿼리 스트링의 파라미터와 상관없다!
세터 메서드는 쿼리 스트링의 파라미터와 관련있다.
세터 메서드 이름이 같아야 스프링 부트가 자동으로 꽂아주는 거
3교시 시작
전체 명령 코드는 Method Area 영역에 들어간다
그 중에서 설계 도면을 보고 여기 나와 있는 명령어대로 Heap 영역에 메모리를 만든다.
레퍼런스 변수 ← 인스턴스 주소를 받는다
레퍼런스 변수는 메서드를 호출한 쪽에서 넘겨줌
메서드를 누가 호출한다? 스프링 부트가 호출한다.
스프링 부트가 Contact 클래스의 인스턴스를 만들고 그 인스턴스 주소를 넘겨준다.
웹 브라우저가 스프링 부트에게 add 해달라고 요청한다. 쿼리 스트링으로 값을 넘긴다.
스프링 부트는 ContactController에 add 라는 메서드를 호출하려고 하는데 add 메서드가 요구하는 게 Contact 인스턴스의 주소다. 스프링 부트가 Contact 인스턴스를 만든다. 만든 후에 세터를 통해서 클라이언트가 보낸 값들을 인스턴스의 각 변수에 담는다. 담은 다음에 그 인스턴스의 주소를 넘겨준다.
println에 인스턴스 주소를 주면 내부적으로 toString()을 호출해서 인스턴스 값을 꺼낸 다음에 출력한다.
레퍼런스 배열을 늘리는 거
Contact 배열이라고 하지 Contact 레퍼런스 배열이라고 안 함
package com.eomcs.mylist;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
// 이 클래스가 클라이언트 요청 처리 담당자임을 표시한다.
// 이 표시(애노테이션)가 붙어있어야만 스프링 부트가 인식한다.
public class ContactController {
Contact[] contacts = new Contact[5];
int size = 0;
@RequestMapping("/contact/list")
public Object list() {
Contact[] arr = new Contact[size]; // 배열에 저장된 값만 복사할 새 배열을 만든다.
for (int i = 0; i < size; i++) {
arr[i] = contacts[i]; // 전에 배열에서 값이 들어 있는 항목만 복사한다.
}
return arr; // 복사한 항목들을 담고 있는 새 배열을 리턴한다.
};
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println(contact);
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
/*
contacts[size++] = createCSV(name, email, tel, company);
*/
return size;
}
/*
@RequestMapping("/contact/get")
public Object get(String email) {
int index = indexOf(email);
if (index == -1) {
return "";
}
return contacts[index];
}
@RequestMapping("/contact/update")
public Object update(String name, String email, String tel, String company) {
int index = indexOf(email);
if (index == -1) {
return 0;
}
contacts[index] = createCSV(name, email, tel, company);
return 1;
}
@RequestMapping("/contact/delete")
public Object delete(String email) {
int index = indexOf(email);
if (index == -1) {
return 0;
}
remove(index); // 메서드 이름으로 코드의 의미를 짐작할 수 있다. 이것이 메서드로 분리하는 이유이다.
return 1;
}
// 기능:
// - 입력 받은 파라미터 값을 가지고 CSV 형식으로 문자열을 만들어 준다.
String createCSV(String name, String email, String tel, String company) {
return name + "," + email + "," + tel + "," + company;
}
// 기능:
// - 이메일로 연락처 정보를 찾는다.
// - 찾은 연락처의 배열 인덱스를 리턴한다.
//
int indexOf(String email) {
for (int i = 0; i < size; i++) {
if (contacts[i].split(",")[1].equals(email)) {
return i;
}
}
return -1;
}
// 기능:
// - 배열에서 지정한 항목을 삭제한다.
//
String remove(int index) {
String old = contacts[index];
for (int i = index + 1; i < size; i++) {
contacts[i-1] = contacts[i]; // 한 칸씩 앞으로 당긴다
}
size--;
return old;
}
*/
// 기능:
// - 배열의 크기를 늘린다.
// - 기존 배열의 값을 복사해온다.
//
Contact[] grow() {
Contact[] arr = new Contact[newLength()];
copy(contacts, arr);
return arr;
}
// 기능:
// - 주어진 배열에 대해 50% 증가시킨 새 배열의 길이를 알려준다.
int newLength() {
return contacts.length + (contacts.length >> 1);
}
// 기능:
// - 배열을 복사한다.
//
void copy(Contact[] source, Contact[] target) {
// 개발자가 잘못 사용할 것을 대비하여 다음 코드를 추가한다.
// 즉 target 배열이 source 배열보다 작을 경우 target 배열 크기만큼만 복사한다.
int length = source.length;
if (target.length < source.length) {
length = target.length;
}
for (int i = 0; i < length; i++) {
target[i] = source[i];
}
}
}
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println(contact);
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = contact;
return size;
}
CreateCSV()
필요 없어져서 삭제
스프링 부트가 인스턴스를 만들고 인스턴스 주소를 넘긴다
// 기능:
// - 이메일로 연락처 정보를 찾는다.
// - 찾은 연락처의 배열 인덱스를 리턴한다.
//
int indexOf(String email) {
for (int i = 0; i < size; i++) {
Contact contact = contacts[i];
if (contact.email.equals(email)) {
return i;
}
}
return -1;
}
① 인스턴스 변수에 값 저장
인스턴스 주소를 알고 있는 레퍼런스.인스턴스 변수
c.name
c.email
② 인스턴스 변경
c = new Contact();
기존의 200번지에서 300번지로 바뀜
c.name = "임꺽정";
기존 인스턴스의 주소를 알고 있는 레퍼런스가 한 개도 없으면 "Garbage"가 된다.
레퍼런스는 언제든지 다른 인스턴스의 주소를 가질 수 있다.
@RequestMapping("/contact/get")
public Object get(String email) {
int index = indexOf(email);
if (index == -1) {
return "";
}
return contacts[index];
}
int indexOf(String email) {
for (int i = 0; i < size; i++) {
Contact contact = contacts[i];
if (contact.email.equals(email)) {
return i;
}
}
return -1;
}
자바 객체를 JSON 문자열로 바꾼 거
백엔드 개발자는 UI 없어도 이렇게 테스트할 수 있어야 함
@RequestMapping("/contact/update")
public Object update(Contact contact) {
int index = indexOf(contact.email);
if (index == -1) {
return 0;
}
contacts[index] = contact;
return 1;
}
낱개로 데이터를 다루는 게 아니라 클래스를 사용해서 변수들을 묶어서 한 단위로 다룬다.
http://localhost:8080/contact/update?name=a2xx&email=a2@test.com&tel=010-0000-0000xx&company=비트캠프xx
리스트에 없는 거라서 0 나옴
// 기능:
// - 배열에서 지정한 항목을 삭제한다.
//
Contact remove(int index) {
Contact old = contacts[index];
for (int i = index + 1; i < size; i++) {
contacts[i-1] = contacts[i]; // 한 칸씩 앞으로 당긴다
}
size--;
return old;
}
리턴한 거 꼭 써야 됩니까?
쓸 사람은 쓰라고 리턴하라고
이미 지운 거 또 지우라고 해보면 0 나옴
package com.eomcs.mylist;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
// 이 클래스가 클라이언트 요청 처리 담당자임을 표시한다.
// 이 표시(애노테이션)가 붙어있어야만 스프링 부트가 인식한다.
public class ContactController {
Contact[] contacts = new Contact[5];
int size = 0;
@RequestMapping("/contact/list")
public Object list() {
Contact[] arr = new Contact[size]; // 배열에 저장된 값만 복사할 새 배열을 만든다.
for (int i = 0; i < size; i++) {
arr[i] = contacts[i]; // 전에 배열에서 값이 들어 있는 항목만 복사한다.
}
return arr; // 복사한 항목들을 담고 있는 새 배열을 리턴한다.
};
@RequestMapping("/contact/add")
public Object add(Contact contact) {
System.out.println(contact);
if (size == contacts.length) { // 배열이 꽉 찼다면,
contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
}
contacts[size++] = contact;
return size;
}
@RequestMapping("/contact/get")
public Object get(String email) {
int index = indexOf(email);
if (index == -1) {
return "";
}
return contacts[index];
}
@RequestMapping("/contact/update")
public Object update(Contact contact) {
int index = indexOf(contact.email);
if (index == -1) {
return 0;
}
contacts[index] = contact;
return 1;
}
@RequestMapping("/contact/delete")
public Object delete(String email) {
int index = indexOf(email);
if (index == -1) {
return 0;
}
remove(index); // 메서드 이름으로 코드의 의미를 짐작할 수 있다. 이것이 메서드로 분리하는 이유이다.
return 1;
}
// 기능:
// - 이메일로 연락처 정보를 찾는다.
// - 찾은 연락처의 배열 인덱스를 리턴한다.
//
int indexOf(String email) {
for (int i = 0; i < size; i++) {
Contact contact = contacts[i];
if (contact.email.equals(email)) {
return i;
}
}
return -1;
}
// 기능:
// - 배열에서 지정한 항목을 삭제한다.
//
Contact remove(int index) {
Contact old = contacts[index];
for (int i = index + 1; i < size; i++) {
contacts[i-1] = contacts[i]; // 한 칸씩 앞으로 당긴다
}
size--;
return old;
}
// 기능:
// - 배열의 크기를 늘린다.
// - 기존 배열의 값을 복사해온다.
//
Contact[] grow() {
Contact[] arr = new Contact[newLength()];
copy(contacts, arr);
return arr;
}
// 기능:
// - 주어진 배열에 대해 50% 증가시킨 새 배열의 길이를 알려준다.
int newLength() {
return contacts.length + (contacts.length >> 1);
}
// 기능:
// - 배열을 복사한다.
//
void copy(Contact[] source, Contact[] target) {
// 개발자가 잘못 사용할 것을 대비하여 다음 코드를 추가한다.
// 즉 target 배열이 source 배열보다 작을 경우 target 배열 크기만큼만 복사한다.
int length = source.length;
if (target.length < source.length) {
length = target.length;
}
for (int i = 0; i < length; i++) {
target[i] = source[i];
}
}
}
‐ /contact/index.html 변경
‐ /contact/view.html 변경
개발자들에게 자바스크립트 객체로 이쁘게 보여준 거
이 문자열을 가지고 자바스크립트 객체를 만든다
JSON에서 모든 문자열은 반드시 더블 쿼테이션
fetch("/contact/list")
.then(function(response) {
return response.json();
})
.then(function(contacts) {
console.log(contacts);
for (var contact of contacts) {
var tr = document.createElement("tr");
tr.innerHTML = `<td><a href="view.html?email=${contact.email}">${contact.name}</a></td>
<td>${contact.email}</td>
<td>${contact.tel}</td>
<td>${contact.company}</td>`;
tbody.appendChild(tr);
}
});
view.html
// 3) 서버에서 데이터 가져오기
fetch(`/contact/get?email=${email}`)
.then(function(response) {
return response.json();
})
.then(function(contact) {
var values = contact.split(",");
response 객체에서
response.json() 파싱해서 자바스크립트 객체로 만들어서 객체 주소를 넘김
response.json() 이거 실행하는 데 시간이 걸림
등록해두고 진짜 응답오면 얘가 호출이 될 것이고
지금은 호출될 함수를 등록하는 거
이 함수가 실행이 완료된 후에 얘를 실행해줘
then
웹 브라우저에서 함수 호출
// 3) 서버에서 데이터 가져오기
fetch(`/contact/get?email=${email}`)
.then(function(response) {
return response.json();
})
.then(function(contact) {
// 4) 연락처 상세 정보를 화면에 출력한다.
xName.value = contact.name;
xEmail.value = contact.email;
xTel.value = contact.tel;
xCompany.value = contact.company;
})
1단계 - 서버에서 받은 JSON 형식의 문자열을 자바스크립트 객체로 전환하여 다룬다.
‐ /contact/index.html 변경
‐ /contact/view.html 변경
http://localhost:8080/javascript/ex04/exam01.html
최소 Object 라는
toString ← 자바에 있는 toString과 똑같다
생성자를 호출하지 않았기 때문에 아무것도 없다
이 방법은 자바스크립트 라이브러리
라이브러리: 다른 개발자가 쓰라고 만드는 거
나 뿐만 아니라 다른 개발자가 사용할 유용한
보통 3번 방법과 4번 방법을 쓸 거임
가장 많이 쓰는 게 4번 방법
단축 코드
자바스크립트 객체를 만드는 데 설계도가 따로 없다
빈 객체가 아니라 기본 객체
51-자바스크립트 / 19 페이지
객체를 초기화 시키는 함수를 "생성자(constructor)"라 부른다.
객체를 초기화 시킨다는 의미는?
객체가 주어진 역할을 하는 데 필요한 변수나 함수를 준비하는 것
프로토타입 : 객체를 초기화시킨 생성자를 가리킨다.
prototype: 원형 객체
Object()처럼 빈 객체를 초기화시키는 함수를 "생성자 함수(constructor)"라 부른다.
var obj = new Object();
① 빈 객체 생성 ← new
② Object() 호출 → 기본 변수, 함수 추가
obj도 레퍼런스
console.log(obj.toString());
[object Object] ← 객체인데 Object가 초기화 시킨 객체예요
console.log(obj.valueOf());
값 출력
console.log(obj.hasOwnProperty("toString")); // false
hasOwnProperty()
는 기본 객체를 생성한 이후에 개발자가 추가한 프로퍼티인지 검사한다.
프로퍼티명이 변수명
퉁쳐서 프로퍼티라고 한다.
hasOwnProperty
console.log(obj.hasOwnProperty("title")); // true
console.log(obj.hasOwnProperty("content")); // true
console.log(obj.hasOwnProperty("viewCount")); // true
console.log(obj.hasOwnProperty("plus1")); // true
console.log(obj.hasOwnProperty("plus2")); // true
console.log(obj.hasOwnProperty("plus3")); // true
나중에 추가한 건 true
함수명은 그 자체가 함수 객체의 주소를 갖고 있는 변수이다.
익명 함수를 바로 넣을 수도 있고
화살표 함수를 바로 넣어도 됨
obj.plus1(100, 200);
obj["plus2"](100, 200);
obj['plus3'](100, 200);
global 객체
함수 객체도 객체
프로퍼티의 값으로 다른 객체의 주소를 저장할 수 있다.
객체를 포함할 순 없음
실제로는 품고 있는 게 아니라 그 주소를 갖고 있는 거
obj.other.v4();
객체 선(연결) 그래프를 따라가는 경로를 표기한 문법
Object Graph Navigation Language => OGNL 표기법
객체에 접근하기 위한 언어
따라 들어가는 거
객체와 객체를 따라가는 거
graph 선형 그래프
값을 꺼내고 세팅할 때 표기법
객체가 다른 객체를 담는다는 것은 객체의 주소를 갖고 있는 거
참조변수 this
같은 방에 들어있으면 this 라고 해줘야 됨
자바에서는 println()에 객체 주소를 주면
println()에서 내부적으로 해당 객체의 toString() 호출한다.
그리고 그 리턴 값을 출력한다.
그러나 자바스크립트의 console.log()는
자바와 달리 toString()의 리턴 값을 출력하지 않는다.
자기가 소속된 객체를 가리키는 게 this
toString()은 이미 객체에 들어 있는 함수이다.
다음은 기존 함수를 덮어 쓴다.
{}은 기본 객체를 생성하는 단축 문법이다.
자바스크립트에서 프로퍼티는 변수도 프로퍼티라고 부르고
자바에서 프로퍼티는 게터 세터 이것들을 프로퍼티라고 한다.
프로퍼티 이름은 다음 3가지 형태로 작성 가능
문자열은 ""
, ''
사용 가능
자바스크립트 객체 생성 코드를 참고해서 만든 데이터 표현 형식
JavaScript Object Notation => JSON
프로퍼티 이름은 반드시 문자열로 표현해야 한다.
반드시 더블 쿼테이션
문자열은 반드시 더블 쿼테이션""
을 사용해야 한다.
JSON은 데이터 표현 형식
앞에 function 쓰면 에러!!
sum() {
return this.kor + this.eng + this.math;
},
this는 obj랑 주소가 같다
arrow function에서 this는 소속된 객체가 아니라 window 객체를 가리킨다.
exam10-2.html
레퍼런스 배열
반복문을 돌릴 수 있어서 좋다
// 배열을 이용하여 여러 개의 객체를 다루기
var scores = []; //new Array();
window : 최상위 글로벌 객체
자바스크립트도 객체에 배열을 만들 방법이 없음
레퍼런스 배열이고
객체는 new Object() 아니면 {}
이걸로 만드는 방법 밖에 없음
exam10-3.html
아직 부족한 점!
=> 특정 과목의 점수가 바뀌면 다시 합계와 평균을 계산해야 한다.
sum은 더 이상 변수가 아니라 함수
obj.sum = kor + eng + math;
obj.sum = function() {
return this.kor + this.eng + this.math;
};
함수로 바꿨기 때문에 출력할 때도
함수 객체 주소를 저장하는 거
함수 추가한다고 짤막하게 표현
exam10-5.html
객체를 리턴하는 거 = 객체 주소를 리턴하는 거
객체 넘겨
객체 받아
new 뒤에 오는 함수는 생성자로서의 역할을 한다
앞에 아무것도 없으면 Object()로 초기화시킨 객체
앞에 이름이 있으면 아 이 객체는 이 함수로 초기화시킨 객체구나
이 함수가 생성자 함수 용도인지
자기가 만든 거니까
다른 개발자는 이 메소드 이름만 보더라도 얘가 생성자로서 역할을 하는지
생성자 함수는 자바의 클래스처럼 대문자로 시작한다!
new를 썼을 때만 this.Object();
이게 제일 먼저 실행된다.
https://velog.io/@banana/2021-12-15목-6주차-4일
이때 this 변수에는 new 명령으로 만든 객체의 주소가 들어 있다.
new creatScore();
① 빈 객체 생성 ← new
② creatScore()
호출
this.Object()
호출 → 기본 프로퍼티 추가
creatScore()
의 프로퍼티 추가 (있으면)
this.Object();
가 없어도 자동으로 수행된다.
instanceof
를 사용하면 그 객체를 초기화시킨 생성자를 확인할 수 있다.
createScore()
내부에서 Object()
생성자를 호출한다.
ex04 - exam01 부터 exam10-7 까지 복습하기
ohola !