4장 객체와 배열, 함수의 기초
- 자바스크립트는 원시 타입을 제외한 나머지는 참조타입(객체 Object)이다.
- 배열, 객체, 함수가 대표적이다.
- Object의 데이터 자체는 별도의 메모리 공간(heap)에 저장되며, 변수에 할당 시 데이터에 대한 주소(힙 Heap 메모리의 주소값)가 저장되기 때문에 자바스크립트 엔진이 변수가 가지고 있는 메모리 주소를 이용해서 변수의 값에 접근하게 된다.
- 객체는 객체 리터럴과 생성자로 생성할 수 있다.
4.1 객체의 기초 ①객체 리터럴
- 객체는 데이터 여러 개를 하나로 모은 복합 데이터이다.
- 객체에 포함된 데이터 하나(key, value 쌍)를 가리켜 객체의 프로퍼티라고 부른다.
- 프로퍼티의 이름 부분을 프로퍼티 이름 또는 키라고 부른다.
let card = {
suit: "하트",
rank: "A"
}
- {...} 부분이 바로 객체 리터럴이다.
- 프로퍼티 이름으로는 모든 식별자와 문자열 리터럴(빈 문자열도 가능)을 사용할 수 있다.
// 프로퍼티 이름 즉,식별자만 사용 가능
card.suit; // 하트
// 프로퍼티 이름 또는 문자열을 반환하는 표현식 사용
card["rank"]; // A
- 객체에 없는 프로퍼티를 읽으려고 시도하면 undefined를 반환한다.
- 객체 리터럴 안에 어떠한 프로퍼티도 작성하지 않으면 빈 객체가 생성된다.
card.value = 14;
console.log(card); // Object {suit: "하트", rank: "A", value: 14}
- 없는 프로퍼티 이름에 값을 대입하면 새로운 프로퍼티가 추가된다.
delete card.rank;
console.log(card); // Object {suit: "하트", value: 14}
- delete 연산자를 사용하면 프로퍼티를 삭제할 수 있다.
let card = {suit: "하트", rank: "A"};
console.log("suit" in card); // true
console.log("color" in card); // false
// card는 Object 객체를 상속받았기 때문
console.log("toString" in card); // true
- in 연산자를 사용하면 객체에 특정 프로퍼티가 있는지 확인할 수 있다.
- in 연산자가 조사하는 대상이 그 객체가 가진 프로퍼티와 그 객체가 상속받은 모든 프로퍼티라는 점을 주의한다.
- 프로퍼티에 저장된 값의 타입이 함수면 그 프로퍼티를 메서드라고 부른다.
console.log(a.suit); // 하트
a.suit = "스페이드";
console.log(a.suit); // 스페이드
console.log(card.suit); // 스페이드
- 객체 타입의 값을 변수에 대입하면 그 변수에는 객체의 참조가 저장된다.
4.2 함수의 기초
- 함수 이름은 일반적으로 동사 또는 동사로 시작되는 어휘로 만든다. 캐멀표기법 또는 밑줄 표기법을 사용한다.
- 함수를 호출할 때 전달하는 값을 인수(argument), 함수 정의할 때 외부로부터 받아들이는 임의의 값을 인자(parameter)라고 한다.
- 인수를 받지 않는 함수도 정의할 수 있다.
함수의 실행 흐름
- 호출한 코드에 있는 인수가 함수 정의문의 인자에 대입된다.
- 함수 정의문의 중괄호 안에 작성된 프로그램이 순차적으로 실행된다.
- return 문이 실행되면 호출한 코드로 돌아간다. return 문의 값은 함수의 반환값이 된다.
- return 문이 실행되지 않은 상태로 마지막 문장이 실행되면, 호출한 코드로 돌아간 후에 undefined가 함수의 반환값이 된다.
console.log(square(5));
function square(x) {
return x * x;
}
- 함수 선언문을 프로그램의 첫머리로 끌어올린다.
참조에 의한 호출과 값에 의한 호출
- 함수는 원시 값을 인수로 넘겼을 때와 객체를 인수로 넘겼을 때 다르게 동작한다.
/* 인수가 원시타입일 때 */
function add1(x) {
return x = x + 1;
}
let a = 3;
let b = add1(a);
console.log(`a = ${a}, b = ${b}`); // a = 3, b = 4
이 함수가 호출될 때 변수 a의 복사본이 인수 x에 할당된다. 이를 가리켜 값의 전달이라고 한다.
이 때 변수 a와 변수 x는 다른 영역의 메모리에 위치한 별개의 변수이다. 따라서 x의 값을 바꾸더라도 a값은 바뀌지 않는다.
/* 인수가 객체타입일 때 */
function add1(p) {
p.x = p.x + 1;
p.y = p.y + 1;
return p;
}
let a = {
x: 3,
y: 4
}
let b = add1(a);
console.log(a, b); // a = Object {x=4, y=5}, b = Object {x=4, y=5}
변수 a에 객체{x:3, y:4}의 참조가 저장되어 있으며, 이 참조 값을 인자 p에 대입한다.
이 때 인자 p와 변수 a는 똑같은 객체를 참조하고 있다. 따라서 함수 안에서 p.x와 p.y를 수정하는 행위는 a.x와 a.y를 수정하는 행위와 같다.
이처럼 함수의 인수로 객체를 넘기면 함수 안에서 원래의 객체를 바꿀 수 있다.
/* 인수 여러 개를 우아하게 전달하는 방법(elegant way) */
function test({a,b,c,d}) {
// code
}
let options = {
a: "a",
b: "b",
c: "c",
d: "d"
}
test(options);
! 함수 안에서 객체의 프로퍼티를 수정하면 호출한 코드에 있는 인수 객체의 프로퍼티가 함께 바뀌므로 주의해야 한다.
객체를 인수로 넘기면 함수에는 객체의 참조가 전달되기 때문이다.
변수의 유효범위
var a = "global";
var b = "global2"
function f() {
console.log(c); // undefined
var a = "local";
b = "global3";
var c = "local2"
console.log(a); // local
console.log(b); // global3
console.log(c); // local2
return a;
return b;
return c;
}
f();
console.log(a); // global
console.log(b); // global3
console.log(c); // ReferenceError: c is not defined
- 전역 변수 : 함수 바깥에서 선언된 변수로 유효 범위가 전체 프로그램이다.
- 지역 변수 : 함수 안에서 선언된 변수와 함수 인자로 유효 범위는 변수가 선언된 함수 내부이다.
- 함수 내에서 변수를 선언하지 않은 상태에서 값을 대입하면 전역 변수로 선언된다.
- 변수에 유효 범위가 있는 이유는 프로그램의 다른 부분에서 선언된 이름이 같은 변수와 충돌하지 않도록 하기 위해서이다.
let과 const
let x = "outer X";
function f() {
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = "inner X";
let y = "inner Y";
console.log(x); // inner X
console.log(y); // inner Y
return x;
return y;
}
f();
console.log(x); // outer X
console.log(y); // ReferenceError: y is not defined
- ECMAScript 6부터 추가된 변수 선언자이다.
- let은 변수를 선언하고 const는 한 번만 할당할 수 있는 상수를 선언한다.
- let : 블록 유효 범위를 갖는 지역 변수를 선언한다. let으로 선언한 변수의 유효 범위는 블록 안이다.
- let 문 으로 똑같은 이름을 가진 변수를 선언하면 문법 오류가 발생한다.
const origin = {x: 1, y: 2};
origin.x = 3;
console.log(origin); // Object {x: 3, y: 2}
- const 문은 블록 유효 범위를 가지면서 한 번만 할당할 수 있는 변수(상수)를 선언한다.
- const 문으로 선언한 변수에 다시 대입을 시도하면 타입 오류가 발생한다.
- 상수 값은 수정할 수 없지만, 상수 값이 객체이거나 배열일 경우에는 프로퍼티 또는 프로퍼티 값을 수정할 수 있다.
console.log(square(3)); // TypeError: square is not a function
let square = function(x) { return x * x };
- 함수는 함수 리터럴로 정의할 수 있다.
- 함수 리터럴은 이름이 없는 함수이므로 익명 함수 또는 무명 함수라고 부른다.
- 함수 리터럴을 사용할 때에는 끝에 반드시 세미콜론을 붙여야 한다.
- 함수 리터럴로 정의한 함수는 끌어올리지 않는다.
let circle = {
center: {
x: 1.0,
y: 2.0
},
radius: 2.5,
area: function(){
return Math.PI * this.radius * this.radius;
}
}
circle.area(); // 19.634954084936208
circle.translate = function(a, b) {
this.center.x = this.center.x + a;
this.center.y = this.center.y + b;
}
circle.translate(1, 2);
circle.center; // Object {x: 2, y: 4}
- 객체의 프로퍼티 중에서 함수 객체의 참조를 값으로 담고 있는 프로퍼티를 가리켜 메서드라고 부른다.
- this는 그 함수를 메서드로 가지고 있는 객체를 가리킨다.
- 메서드 또한 프로퍼티의 일종이므로 나중에 추가할 수 있다.
- 메서드는 일반적으로 메서드가 속한 객체의 내부 데이터(프로퍼티 값) 상태를 바꾸는 용도로 사용한다.
- 객체를 기본 부품으로 삼아 프로그램을 만들어가는 기법 => 객체 지향 프로그래밍
함수를 활용하면 얻을 수 있는 장점
- 재사용할 수 있다.
- 만든 프로그램을 이해하기 쉽다.
- 프로그램 수정이 간단해진다.
4.3 객체의 기초 ② 생성자
4.4 객체의 기초 ③ 내장 객체
4.5 배열의 기초
728x90
반응형
'ETC > 스터디' 카테고리의 다른 글
[알고리즘] ChatGPT 와 함께하는 알고리즘 풀기1 (1) | 2024.01.22 |
---|---|
[자바스크립트] 원시값과 참조값 이해하기 (0) | 2023.12.06 |
[자바스크립트] 공부2 (0) | 2018.05.21 |
[자바스크립트] 공부1 (0) | 2018.05.17 |
[스터디] 자바스크립트 스터디_20170904 (0) | 2018.05.15 |