목차
- 객체
1-1. 객체 선언 및 호출
1-2. key 식별자 ① 객체명.속성명, ② 객체명['속성명'], ③ 객체명[변수명]
1-3. 상수 객체 속성 변경
1-4. 객체 속성 추가 및 제거 - 함수 활용 객체 생성
- in 키워드 true/false
- for in 반복문
- 객체의 메소드 속성
- 생성자 함수
- 객체 배열
7-1. push() 객체 배열 추가
7-2. find/findIndex 배열 내 객체 검색, 첫 true에 대해서만 반환
7-3. filter true 요소 전체 반환
1. 객체
다른 자료형은 오직 하나의 데이터만 담을 수 있는 원시형(primitive type)인 반면, 객체의 경우는 다양한 데이터를 취급한다는 특징이 있다.
1-1. 객체 선언 및 호출
- 객체는 프로퍼티(property, key-value 한 쌍)를 저장하며, 키 값 통해 속성을 식별한다.
- 이때 키는 문자열로서 모든 자료형을 속성값으로 받을 수 있다.
<body>
<script>
function test() {
// 객체 생성자 호출
let objA = new Object();
// 객체 리터럴 선언 -- 값이 정해져 있을 때
let objB = {};
let product = {
//키-값 쌍으로 구성된 프로퍼티
pName : 'Dry Mango',
origin : 'Philippines',
price : 10000,
ingredient : ['mango', 'sugar']
};
console.log("===== product =====");
console.log(product);
console.log('객체명.속성명으로 접근');
console.log('product.pName : ' + product.pName);
console.log('product.origin : ' + product.origin);
console.log('product.price : ' + product.price);
console.log('product.ingredient : ' + product.ingredient);
console.log('product.ingredient[0] : ' + product.ingredient[0]);
console.log('product.ingredient[1] : ' + product.ingredient[1]);
console.log("객체명['속성명']으로 접근");
console.log("product['pName'] : " + product['pName']);
console.log("product['origin'] : " + product['origin']);
console.log("product['price'] : " + product['price']);
console.log("product['ingredient'] : " + product['ingredient']);
console.log("product['ingredient'][0] : " + product['ingredient'][0]);
console.log("product['ingredient'][1] : " + product['ingredient'][1]);
}
test();
</script>
</body>
- 객체 생성 방법에는 다음 두 가지가 있다: ① 객체 생성자 new Object(); 통해 호출하거나, ② 값이 정해져 있는 경우는 중괄호 {}로 작성하여 선언한다.
- 호출 시에는 ① 객체명.속성명, 또는 ② 객체명['속성명']으로 접근하여 데이터를 불러올 수 있다.
1-2. key 식별자 ① 객체명.속성명, ② 객체명['속성명'], ③ 객체명[변수명]
- 객체의 키(key)는 모든 문자열을 사용할 수 있다.
- 단, 식별자로서 [쓰일 수 없는 단어]나 [변수]를 키로서 사용하고자 할 때는 대괄호 []로 감싸주어야 객체 요소에 접근이 가능하다.
<body>
<script>
function test() {
let objTest = {
'hello world' : 'Hello World!!', //key에 띄어쓰기 들어 있는 경우
'!@#$%$#^()' : 1234567890, //key에 특수문자
test : true
//key : false -- objTest.key가 찾고 있는 것
};
// 변수에 담긴 key 값
let key = "test";
console.log("===== objTest =====");
console.log(objTest);
console.log("객체명.속성명 접근 불가")
//console.log(objTest.'hello world');
//console.log(objTest.'!@#$%$#^()');
console.log(objTest.key); //undefined... key라는 key값이 있냐고 묻는 것이라서 없다고 나옴
console.log("객체명['속성명']으로 접근 가능")
console.log(objTest['hello world']);
console.log(objTest['!@#$%$#^()']);
console.log(objTest[key]); //변수를 key로 사용하는 경우 무조건 대괄호
}
test();
</script>
</body>
- ① 키 값에 띄어쓰기가 들어있는 경우
객체명.속성명 방법으로는 접근이 불가하다. 위처럼 코드 작성만 하더라도 오류 메시지를 띄운다: Identifier expected
따라서 ['hello world']처럼 대괄호 안에 작성해 객체명['속성명']으로 객체에 접근하여야 한다.
- ② 키 값에 특수문자가 포함된 경우이다. 이처럼 다양한 특수문자를 객체명으로 받을 수는 있지만,
객체명.속성명으로의 접근은 오류에 해당돼 불가하다: Identifier expected
특수문자가 쓰인 키로서 쓰인 경우도 객체명['속성명'] 식으로 접근되어야 한다.
- ③ 객체명.속성명과 객체명['속성명']은 의미상의 차이를 보이기도 한다.
객체명.key라고 작성한 경우는 key라는 이름의 key 값이 있는지를 묻는 것이 돼 key : ...가 정의되지 않은 이상 false라는 값을 반환한다.
반대로 객체명[key]는 let key = "test";에서 정의한 변수 key를 토대로 test : true라는 한 쌍의 프로퍼티를 만들었고, 이에 대해 물어 true라는 value를 리턴한다. 따라서 변수를 key로 사용하는 경우는 무조건 대괄호 []를 써서 객체명[변수명]처럼 쓰여야 한다.
1-3. 상수 객체 속성 변경
❗ 상수 배열/객체 속성은 변경 가능하나, 상수 배열/객체재할당은 불가하다.
<body>
<script>
function test() {
const student = {name: '이자스', age: 20};
console.log(student);
// 할당돼 있는 객체 안의 속성값들, 즉 해당 객체에서 속성값 변경은 가능하다
student.age = 30; //가능
console.log(student);
// 이미 존재하는 상수 객체에 재할당은 불가하다
student = {name: '이자스', age: 40}; //상수값 재할당은 불가
}
test();
</script>
</body>
- 할당돼 있는 상수 객체 안의 속성값들, 즉 해당 객체에서의 속성값 변경은 가능하다: student.age = 30;
- 단, 이미 존재하는 상수 객체에 재할당은 불가한 것이다.
1-4. 객체 속성 추가 및 제거
❗ 객체 생성 직후 속성을 추가 또는 제거하는 것을 두고 동적으로 속성을 추가한다 또는 제거한다라고 표현한다.
<body>
<script>
function test() {
// 빈 객체 선언
let student = {};
console.log(student);
// 객체 속성 추가
student.name = "김자스";
student.hobby = '게임';
student.strength = '프로그래밍';
student.dream = '개발자';
console.log(student);
// 객체 속성 제거
delete(student.hobby);
console.log(student);
}
test();
</script>
</body>
- 빈 객체를 선언한 뒤, 객체명.속성명을 명시해 추가할 수 있다.
- delete(객체명.속성명); 형태로 객체 속성을 제거한다.
2. 함수 활용 객체 생성
-- key : value 설정
function makeStudent(name, score) {
let student = {
name : name,
score : score
};
return student;
}
- 함수 내의 변수 통해 key : value를 설정한 예시이다.
- 사실 굳이
변수에 담는 과정이 필요하지는 않으므로 이를 생략하고 아래처럼 간결히 만들 수 있다.
<body>
<script>
function makeStudent(name, score) {
return {
// 단축 프로퍼티
name, // name : name
score // score : score
};
}
console.log(makeStudent('박자스', 100));
</script>
</body>
- return 구문만으로 해결되는 것이다: return { name, score };
- 또, key와 value가 같은 경우이므로 단축 프로퍼티로 대신할 수 있다.
3. in 키워드 true/false
속성명 in 변수명(객체명)
<body>
<script>
function test() {
let student = {
name : '구자스',
kor : 100,
eng : 80,
math : 90,
test : undefined
};
console.log('student 객체에 name 속성이 있는지 확인 : ' + ('name' in student)); //true
console.log('student 객체에 kor 속성이 있는지 확인 : ' + ('kor' in student));
console.log('student 객체에 eng 속성이 있는지 확인 : ' + ('eng' in student));
console.log('student 객체에 math 속성이 있는지 확인 : ' + ('math' in student));
console.log('student 객체에 sum 속성이 있는지 확인 : ' + ('sum' in student)); //false
console.log('student 객체에 test 속성이 있는지 확인 : ' + ('test' in student)); //true
}
test();
</script>
</body>
- in 키워드 통해 객체 내부에 해당 속성이 들어있는지 확인한다.
- 비록 undefined가 주어졌지만 test 속성에 대해서도 true를 반환함을 알 수 있다.
console.log('student.name : ' + student.name); //value 값 나옴
console.log('student.sum : ' + student.sum); //undefined -- 속성이 없어서
console.log('student.test : ' + student.test); //undefined -- 속성이 있지만 값이 없어서
- 이처럼 값이 undefined인 속성의 경우 in 키워드로 확인하는 것이 정확하다.
- undefined로 정의된 데는 ① 정말 해당 속성이 존재하지 않거나, ② 속성은 있지만 값이 없는 경우로 사유를 나눠볼 수 있다.
객체명.속성명으로 value를 찾아오는 예시를 살펴보자. student.sum은 존재하지 않는 속성이므로 undefined를 반환하고, student.test는 값이 없어 undefined를 리턴하고 있다. 이때 in 키워드를 사용해 해당 속성들의 존재 유무를 판단하거든sum 속성에 대해서는 false, test 속성은 true가 정상적으로 확인된다. 이러한 연유에서 객체 내부에 속성의 존재 유무를 판단하기 위해서는 in 키워드를 사용함이 바람직하다고 하는 것이다.
4. for in 반복문
for(let key in 객체명) {}
<body>
<script>
function test() {
let game = {
title : 'DIABLO 3',
price : 35000,
language : '한국어지원',
supportOS : 'windows 32/64',
service : true
};
console.log(game);
console.log("===== 반복문 동작 =====");
for(let key in game) { // key값 in 객체명
console.log(key + " : " + game[key]);
}
}
test();
</script>
</body>
- 객체 속성을 살필 때는 단순 for문은 사용이 불가하고, 대신에 for in문을 써야 한다.
5. 객체의 메소드 속성
<body>
<script>
function test() {
let name = "뽀삐";
let dog = { name : "박카스" };
// 함수 표현식으로 함수를 만들고 객체 속성 dog.eat에 할당
// => 메소드로 등록한다
dog.eat = function(food) {
console.log(name + "가 " + food + "를 먹고 있네요."); //뽀삐
//객체 내에서 자신의 속성을 호출할 때는 반드시 this를 사용
console.log(this.name + "가 " + food + "를 먹고 있네요."); //박카스
};
// 메소드 호출
dog.eat("고구마");
// 선언된 함수 메소드로 등록 -- dog.walk는 key, 뒤에 walk는 function 이름
dog.walk = walk;
// 메소드 호출
dog.walk("테헤란로");
let human = {
name : '김김김',
//eat : function() {}
//메소드 단축 구문
eat(food) {
console.log(this.name + "이 " + food + "를 먹고 있어요.");
// this를 사용하지 않고 외부 변수를 참조해서 객체에 접근
// 가능하기는 하지만 변수명이 변경되는 상황 등이 있을 수 있으므로
// 사용을 지양하고, 항상 this로 참조하도록 한다.
//console.log(human.name + "이 " + food + "를 먹고 있어요.");
}
};
human.eat("짬뽕");
//외부 변수 참조 시 발생할 수 있는 문제
let person = human;
human = null;
person.eat('닭가슴살 샐러드'); //human.name은 더이상 유효하지 않아 오류
}
//선언된 함수
function walk (place) {
console.log(this.name + "가 " + place + "를 산책하고 있어요.");
}
test();
</script>
</body>
- 객체 속성에 저장된 함수를 메소드(method)라고 하며, 객체명.메소드()와 같은 형식으로 사용된다.
- 메소드는 this로 객체를 참조한다.
❗ this.속성명 대신 변수명.속성명으로의 접근도 가능은 하다. 하지만 변수명이 변경되는 등 상황에 대응할 수 없게 되므로 변수명 사용을 지양하고, this 통해 참조하도록 한다.
6. 생성자 함수
앞서 서술한 <2. 함수 활용 객체 생성>과는 차이가 있으며, 생성자 통해서는 많은 객체 생성 시 유리하다.
<body>
<script>
function Student(name, java, oracle, html, css, javascript) {
// 속성 정의
this.name = name;
this.java = java;
this.oracle = oracle;
this.html = html;
this.css = css;
this.javascript = javascript;
// 메소드 정의
// 성적 합계 리턴 메소드
this.getSum = () => this.java + this.oracle + this.html + this.css + this.javascript;
// 성적 평균 리턴 메소드
this.getAvg = () => this.getSum() / 5;
}
</script>
</body>
- 하나의 function을 getSum 메소드로 만든 것처럼 함수 안에서 속성 및 메소드에 대한 정의가 치러진다.
- 이처럼 정의된 생성자 함수를 new 연산자와 함께 호출하거든 ① this = {}; 빈 객체가 만들어지고, ② return this; this가 암시적으로 반환된다.
7. 객체 배열
7-1. push() 객체 배열 추가
<body>
<script>
function test() {
// 생성자 함수 호출하여 객체 생성
let student1 = new Student("홍길동", 100, 90, 80, 70, 60);
console.log(student1);
console.log("student1 점수 합계 : " + student1.getSum());
console.log("student1 점수 평균 : " + student1.getAvg());
let student2 = new Student(prompt("이름 입력"),
Number(prompt('java 점수 입력')),
Number(prompt('oracle 점수 입력')),
Number(prompt('html 점수 입력')),
Number(prompt('css 점수 입력')),
Number(prompt('javascript 점수 입력')));
console.log(student2);
console.log("student2 점수 합계 : " + student2.getSum());
console.log("student2 점수 평균 : " + student2.getAvg());
// 배열 선언 -- 모든 자료형을 취급하기에 객체 또한 담을 수 있다
let students = [];
// 배열에 객체 담기
students.push(student1, student2);
// 객체 배열 출력
console.log(students);
}
test();
</script>
</body>
- 생성자 함수 호출하여 객체를 생성한다. 이때 ① 소괄호 () 안에 인자로서 전달하는 방향도 있고, ② prompt 통해 입력을 받도록 지시하는 방법 역시 가능하다.
- 또, 이들 결과를 배열로서 담을 수도 있다. 배열의 경우는 모든 자료형을 취급하기에 객체 또한 저장 가능하다.
- push() 메소드 통해 뒤에서부터 차례로 추가되도록 한다.
7-2. find/findIndex 배열 내 객체 검색, 첫 true에 대해서만 반환
let 변수 = 배열.find/findIndex(function(item, index, array) {});
- 객체 배열 대상으로 특정 조건에 부합하는 객체를 조회한다.
- true가 반환되면 반복이 멈추고, 해당 요소를 반환하거나(find). 해당 요소의 인덱스를 반환(findIndex)한다.
7-3. filter true 요소 전체 반환
- 조건을 충족시키는 요소가 여러 개일 때 활용한다.
- 즉
첫 true에 대해서만 반환하는 find/findIndex를 대신할 수 있는 메소드이다. - find/findIndex와 문법은 유사하지만, 조건에 맞는 요소 전체를 담은 배열을 반환한다는 차이가 있다.
<body>
<script>
function test() {
//객체 3개를 배열 안에 담음
let students = [new Student("수지", 100, 90, 95, 85, 80),
new Student("제니", 70, 80, 90, 75, 60),
new Student("유아", 80, 65, 55, 90, 90)];
// 제니라는 이름을 가진 학생 찾기
let jennie = students.find(item => item.name == '제니');
console.log(jennie); //true인 값을 찾아오는 것임
// 우리라는 이름을 가진 학생 찾기 -- 존재하지 않는 이름
let woori = students.find(item => item.name == '우리');
console.log(woori); //undefined
// java 점수가 90점 이상인 학생의 인덱스 찾기
let java = students.findIndex(item => item.java >= 90);
console.log(java);
// oracle 점수가 60점 미만인 학생의 인덱스 찾기
let oracle = students.findIndex(item => item.oracle < 60);
console.log(oracle); //-1... 해당값을 찾지 못함 60점 미만 학생 없음.
// 평균 점수가 70점대인 학생 인덱스 찾기
// let avg70 = students.findIndex(item => item.getAvg() >= 70 && item.getAvg() < 80);
// filter 사용해서 수정
let avg70 = students.filter(item => item.getAvg() >= 70 && item.getAvg() < 80);
console.log(avg70); //2
}
test();
</script>
</body>
- 속성이 존재하는 학생에 대해 find 실시하면 true인 데 대해 배열 정보를 반환한다.
- 존재하지 않는 학생을 find로 가리키거든 undefined를 리턴해주고 있다.
- findIndex 역시 존재하는 데 대해서는 해당 인덱스(index)를 결과값으로 돌려주고, 존재하지 않으면 -1 이라는 음수를 나타낸다.
- 한편 평균 점수가 70점대인 학생의 인덱스를 찾고자 findIndex로 가리키거든 예상 결과는 2명임에도 첫 번째 인덱스(index)인 [1]만을 가리킨다. 이는 findIndex 특성상의 한계이다.
- 이를 filter로 고쳐쓰면 조건에 해당하는 전체 학생 목록을 배열 형태로 확인할 수 있다.
'Frontend > JavaScript' 카테고리의 다른 글
[JavaScript] DOM | 요소 노드 | 텍스트 노드 | 문서 객체 (1) | 2022.02.20 |
---|---|
[JavaScript] 숫자 | 문자 | 날짜 | 객체 메소드 (0) | 2022.02.20 |
[JavaScript] 배열 | for of | forEach | map | Array 객체 메소드 (0) | 2022.02.18 |
[JavaScript] 함수 선언문 | 함수 표현식 | 콜백 함수 | 화살표 함수 (0) | 2022.02.17 |
[자바스크립트/수업 과제 practice] 기본 문법 실습 (0) | 2022.02.16 |