4. 객체와 배열, 함수의 기초

Veloger_97·2021년 4월 28일
0
post-thumbnail

4.1 객체의 기초👊


4.1.1 객체

객체는 이름과 값을 한 쌍으로 묶은 데이터를 여러 개 모은 것이다.

이름
suit"하트"
rank"A"

객체에 포함된 데이터 하나(이름과 값의 쌍) 를 가리켜 객체의 프로퍼티라고 부른다. 프로퍼티의 이름 부분 (suit, rank)는 프로퍼티 이름 또는 라고 부른다.


4.1.2 객체 리터럴로 객체 생성

// 객체 생성
var card = { suit: "하트", rank: "A" };

// 객체 안의 프로퍼티 값을 읽거나 사용 할 때
card.suit; // -> 하트
card["rank"]; // -> A

// 객체에 없는 프로퍼티를 읽을 때
card.color; // -> undefined

// 빈 객체 생성
var obj = {};
console.log(obj); // -> Object{}

프로퍼티 이름과 값은 콜론 : 으로 구분하며 중괄호({}) 안에 있는 프로퍼티들은 쉼표 , 로 구분한다. 객체 안의 프로퍼티 값을 읽거나 쓸 때는 마침표 . 또는 대괄호 [] 를 사용한다.
객체에 없는 프로퍼티를 읽으려고 시도하면 undefined를 반환하고 객체 리터럴 안에 프로퍼티를 작성하지 않으면 빈 객체가 생성된다.


4.1.3 프로퍼티 추가와 삭제

// 새로운 프로퍼티 추가
card.value = 14;
console.log(card); // -> Object {suit : "하트", rank : "A", value : 14}

// delete 연산자로 프로퍼티 삭제
delete card.rank;
console.log(card); // -> Object {suit : "하트", value : 14}

위의 코드처럼 자바스크립트의 객체는 실행 중에 프로퍼티를 자유롭게 추가하거나 삭제 가능하다.


4.1.4 in 연산자로 프로퍼티가 있는지 확인

in 연산자로 특정 프로퍼티가 객체 안에 있는지 확인가능하다. 객체 안에 포함되어 있다면 true를 반환, 포함되지 않았다면 false를 반환한다.

var card = { suit: "하트", rank: "A" };
console.log("suit" in card); // -> true
console.log("color" in card); // -> false

4.1.5 객체 리터럴 예제

var p = { x: 1.0, y: 2.5 };

var circle = {
  center: { x: 1.0, y: 2.0 },
  radius: 2.5,
};

circle.center.x; // -> 1.0

객체의 프로퍼티 값으로 객체를 대입할 수도 있다. (마침표 뒤에 프로퍼티 이름을 연결)


4.1.6 객체는 참조 타입

객체 타입의 값을 변수에 대입하면 그 변수에는 객체의 참조 (메모리에서의 위치 정보)가 저장된다. 이때 변수 상태를 가리켜 그 객체를 참조하고 있다 라고 한다. 다음 코드를 보자

// 위에서 만든 card 객체를 a 에 대입
var a = card;

// a 가 card 객체를 참조하게 되므로 읽거나 수정할 수 있다.
console.log(a.suit); // -> 하트
a.suit = "스페이드";
console.log(a.suit); // -> 스페이드
console.log(card.suit); // -> 스페이드

4.2 함수의 기초👊

8장에 자세히 나와있지만 기초를 다지기 위해 훑어보자


4.2.1 함수

일련의 처리를 하나로 모아 언제든 호출할 수 있도록 만들어 둔 것이다. 함수의 입력 값을 인수 라고 부르고 함수의 출력 값을 반환값 이라고 부른다.


4.2.2 함수 선언문으로 함수 정의하기

function square(x) {
  return x * x;
}

return 문이 실행되면 제어권이 함수를 호출한 코드로 되돌아가고, return 문에 지정된 값은 함수의 반환값이 된다.


4.2.3 함수 이름

함수 이름만 잘 붙혀도 그 함수가 어떤 일을 하는지 알 수 있고 가독성과 유지 보수성이 크게 높아진다. 함수 이름은 일반적으로 동사 또는 동사로 시작되는 어휘로 시작한다. 캐멀 표기법 또는 밑줄 표기법을 사용한다.

function saveImage(img) {...}
function load_file() {...}

4.2.4 함수 호출

함수 이름 뒤에 소괄호로 인수를 묶어 입력한다.

square(3);

함수를 호출할 때 전달하는 값(3)을 인수 (argument), 함수 정의문의 인수를 인자 (parameter) 라고 한다.


4.2.5 인수

함수는 인수를 여러 개를 쉼표 , 로 구분하여 받을 수 있다.

// 인수 여러 개 받기
function dist(p,q) {
    var dx = q.x - p.x;
    var dy = q.y - p.y;
}

var p1 = {x:1, y:1},
var p2 = {x:4, y:5},
var d = dist(p1,p2);

// 인수가 없을 때
var bark = function() {console.log("Wow");};
bark(); // -> "Wow"

4.2.6 함수 선언문의 끌어올림

자바스크립트의 함수 선언문은 프로그램의 어떤 위치에도 작성할 수 있다. 함수를 실행한 후 함수를 정의해도 문제 없이 동작한다.

console.log(square(5)); // -> 25
function square(x) {
  return x * x;
}

4.2.7 값으로서의 함수

자바스크립트에서는 함수가 객체이다. 즉 변수에 함수를 할당하고 그 변수 이름으로 함수를 실행할 수 있다.

var sq = square;
console.log(square(5)); // -> 25

4.2.8 참조에 의한 호출과 값에 의한 호출

function add1(x) {
  return (x = x + 1);
}
var a = 3;
var b = add1(a);
console.log("a = " + a + ", b = " + b); // -> a = 3, b = 4

// 인수가 객체일 때
function add1(p) {
  p.x = p.x + 1;
  p.y = p.y + 1;
  return p;
}
var a = { x: 3, y: 4 };
var b = add1(a);
console.log(a, b); // -> Object {x = 4, y = 5} Object {x = 4, y = 5}

add1은 전달받은 인수에 1을 더하여 반환하는 함수이다. 이 함수가 호출될 떄 변수 a의 복사본이 인자 x에 할당된다. 즉, 인수에 원시 값을 넘기면 그 값 자체가 인자에 전달된다. 이를 가리켜 값의 전달 이라고 부른다. 이때 변수 a 와 x 는 다른 영역의 메모리에 위치한 별개의 변수이기 때문에 x 값을 바꾸더라도 a 값은 바뀌지 않는다.


인수 여러 개를 우아하게 전달하는 방법

함수에 넘겨야 하는 인수 개수가 많아지면 다음과 같은 문제가 발생한다.

  • 인수의 순서를 착각하기 쉽다.
  • 함수가 받는 인수 개수를 바꾸면 함수의 호출 방법이 바뀌므로 프로그램 전체를 수정해야 한다.

객체의 프로퍼티에 인수를 담아서 넘기면 이러한 문제를 해결 할 수 있다.

// 인자가 많은 함수
function setBallProperties(x,y,vx,vy,radius) {...}
...
setBallProperties(0,0,10,15,5);

// 객체의 프로퍼티에 인수를 담아서 해결
var parameters = {
    x : 0,
    y : 0,
    vx : 10,
    vy : 15,
    radius : 5
}
function setBallProperties(parameters) {...}
...
setBallProperties(parameters);

4.2.9 변수의 유효 범위


전역 유효 범위와 지역 유효 범위

변수에 접근할 수 있는 범위를 그 변수의 유효 범위 라고 한다. 자바스크립트 변수는 변수의 유효 범위에 따라 전역 변수지역 변수로 나뉜다.


전역 변수는 함수 바깥에서 선언된 변수이고 유효 범위가 전체 프로그램이다. 반대로 지역 변수는 함수 안에서 선언된 변수이고 유효 범위는 함수 내부이다.


변수의 충돌

변수에 유효 범위가 있는 이유는 프로그램의 다른 부분에서 이름이 같은 변수끼리 충돌하지 않도록 하기 위해서다. 다른 함수 내부에서 각각의 지역 변수로 선언된 변수는 함수 내에서만 유효하므로 충돌하지 않는다. 하지만 전역 변수는 이름이 같으면 충돌하기 때문에 주의해야 한다.


함수 안에서의 변수 선언과 변수 끌어올림

함수 중간 부분에서 변수를 선언하더라도 변수는 함수 첫 머리에서 선언된 것처럼 함수 안의 다른 문장보다 먼저 선언된다

function f() {
  console.log(a); // -> undefined
  var a = "local";
  console.log(a); // -> local
  return a;
}

함수 안에서의 변수 선언 생략

변수를 선언하지 않은 상태에서 값을 대입하면 전역 변수로 선언된다.

function f() {
  a = "local";
  console.log(a); // -> local
  return a;
}
console.log(a); // -> local

4.2.10 블록 유효 범위 : let 과 const

letconst는 ECMAScript6 부터 추가된 변수 선언자로 모두가 '블록 유효 범위'를 갖는 변수를 선언한다.


let

// 변수 선언
let x;
// 변수 동시 선언
let a, b, c;
// 선언과 동시에 초깃값 설정
let x = 5,
  y = 7;

varlet의 가장 큰 차이점은 let으로 선언한 변수의 유효 범위가 블록 안이라는 점이다. 이러한 차이점 때문에 var보다 let을 많이 쓴다.

let x = "outer x";
{
  let x = "inner x";
  let y = "inner y";
  console.log(x); // -> inner x
  console.log(y); // -> inner y
}
console.log(x); // -> outer x
console.log(y); // -> ReferenceError : y is not defined

const

const문은 블록 유효 범위를 가지면서 한번만 할당할 수 있는 변수(상수)를 선언한다. let문으로 선언한 변수처럼 동작하지만 반드시 초기값을 설정해야 한다는 차이점이 있다.

const x = 2;
x = 5; // -> Uncaught TypeError (const문은 값을 바꿀 수 없는 상수이다)

const origin = { x: 1, y: 2 };
origin.x = 3;
console.log(origin); // -> Object {x : 3, y : 2} (상수 값이 객체나 배열이면 값을 바꿀 수 있다.)

4.2.11 함수 리터럴로 함수 정의하기

console.log(square(3)); // -> 호이스팅 X TypeError 등장
var square = function (x) {
  return x * x;
};

// 익명함수에도 이름을 붙일 수 있다.
var square = function sq(x) {
  return x * x;
};

위 코드에서는 function(x) {...} 부분이 함수 리터럴이다. 함수 리터럴은 이름이 없는 함수이므로 익명 함수 또는 무명 함수라고 부른다. 함수 리터럴을 사용할 때는 끝에 반드시 세미콜론을 붙여야 한다. 함수 선언문으로 정의한 함수는 호이스팅이 적용되지만 함수 리터럴로 정의한 함수는 호이스팅이 적용되지 않는다.


4.2.12 객체의 메서드

객체의 프로퍼티 중에서 함수 객체의 참조를 값으로 담고 있는 프로퍼티를 가리켜 메서드라고 부른다.

var circle = {
  center: { x: 1.0, y: 2.0 }, // 원의 중점을 표현하는 객체
  radius: 2.5, // 원의 반지름
  area: function () {
    // 원의 넓이를 구하는 메서드
    return Math.PI * this.radius * this.radius;
  },
};

// 원을 평행으로 이동시키는 translate 메서드 추가
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; //h -> Object {x=2, y=4}

위 코드에 return에 나오는 this는 그 함수를 메서드로 가지고 있는 객체 (위 코드에선 circle)를 가리킨다. 즉, this.radiuscircle.radius 이다. 메서드 또한 프로퍼티의 일종이므로 나중에 추가할 수 있다.


4.2.13 함수의 장점

  • 재사용할 수 있다.
  • 만든 프로그램을 이해하기 쉽다.
  • 프로그램 수정이 간단해진다.

4.3 객체의 기초👊


4.3.1 생성자로 객체 생성하기

자바스크립트에선 C++과 Java와 달리 class가 없다. 대신 생성자라고 하는 함수로 객체를 생성할 수 있다.

function Card(suit, rank) {
  this.suit = suit;
  this.rank = rank;
}

// 생성자로 객체를 생성할 때는 "new" 연산자를 사용
var card = new Card("하트", "A");

console.log(card); // -> Card {suit: "하트", rank: "A"}

위의 코드를 실행하면 suit 프로퍼티에는 "하트", rank 프로퍼티에는 "A"라는 값이 저장된 객체가 생성되고, 마지막으로 그 객체의 참조가 변수 card에 할당된다.


생성자

위의 예처럼 new 연산자로 객체를 생성할 것이라 기대하고 만든 함수를 생성자라고 한다. 생성자의 이름은 첫글자를 대문자로 쓰는 파스칼 표기법을 사용한다. 그리고 생성자와 new 연산자로 생성한 객체를 그 생성자의 인스턴스라고 부른다.


생성자의 역할

생성자는 객체를 생성하고 초기화하는 역할을 한다. 생성자를 사용하면 이름은 같지만 프로퍼티 값이 다른 객체(인스턴스) 여러 개를 간단히 생성 할 수 있다.

var card1 = new Card("하트", "A");
var card2 = new Card("클럽", "K");
var card3 = new Card("스페이드", "2");

4.3.2 메서드를 가진 객체를 생성하는 생성자

생성자에서 this.프로퍼티 이름에 함수의 참조를 대입하면 메서드를 정의할 수 있다.

function Circle(center, radius) {
  this.center = center;
  this.radius = radius;
  this.area = function () {
    return Math.PI * this.radius * this.radius;
  };
}
var p = { x: 0, y: 0 };
var c = new Circle(p, 2.0);
console.log("넓이 = " + c.area()); // -> 넓이 12.566370614359172

4.4 객체의 기초👊


4.4.1 내장 생성자

사용자가 정의하는 생성자 외에도 자바스크립트에 내장되어있는 내장 생성자가 있다. 자주 쓰이는 내장 생성자를 알아보자

생성자 이름생성되는 객체
String문자열 객체
Number숫자 객체
Array배열
Date날짜와 시간
Function함수 객체
Mapkey/value맵을 생성
......

4.4.2 기타 내장 객체

객체도 마찬가지로 자바스크립트에 내장되어있는 내장 객체가 있다.

내장 객체설명
전역 객체프로그램 어디에서나 사용할 수 있는 객체
JsonJSON을 처리하는 기능 제공
Math수학적인 함수와 상수 제공
Reflect프로그램 흐름을 가로채는 기능

4.4.5 전역 객체

위의 표에서 소개한 전역 객체는 자바스크립트에서 매우 중요한 객체이다. 전역 객체의 프로퍼티는 프로그램의 어느 위치에서나 사용할 수 있다.

분류프로퍼티
전역 프로퍼티undefined, NaN, Infinity
생성자Object(), String(), Number() 등
전역 함수parseInt(), parseFloat(), isNaN() 등
내장 객체Math, JSON, Reflect

4.5 배열의 기초👊


4.5.1 배열 리터럴로 생성하기

배열 리터럴은 쉼표로 구분한 값을 대괄호[]로 묶어서 표현한다.

var evens = [2, 4, 6, 8];

// 배열 리터럴 안에 어떠한 요소도 작성하지 않으면 빈 배열이 생성
var empty = [];
console.log(empty); // -> []

// 배열 리터럴 요소의 값을 생략하면 생성되지 않는다
var a = [2, , 4];
console.log(a); // -> [2, undefined, 4]

// 변수와 마찬가지로 모든 타입의 값이 올 수 있다
var various = [3.14, "pi", true, { x: 1, y: 2 }, [2, 4, 6, 8]];

4.5.2 length 프로퍼티

배열 요소의 최대 인덱스 값 +1이 담겨 있다. 즉, 배열 길이를 구할 수 있다.

var evens = [2, 4, 6, 8];
evens.length; // -> 4

// 배열의 길이를 줄일 수 있다.
var a = [1, 2, 3, 4, 5];
a.length = 2;
console.log(a); // -> [1,2];

4.5.3 Array 생성자로 생성하기

배열을 Array 생성자로 생성할 수 있다.

var evens = new Array(2, 4, 6, 8);
var empty = new Array();
var a = new Array(2, 4);
var v = new Array(3.14, "pi", true);

// Array 생성자의 인수가 한개고 그 값이 양의 정수면 길이를 뜻한다.
var x = new Array(3);
console.log(x.length); // -> 3;

// 음수이면 오류 발생
var x = new Array(-3); // -> 에러

4.5.5 배열은 객체

Array 객체는 배열의 인덱스를 문자열로 변환해서 그것을 프로퍼티로 이용한다. 즉, 배열에 대괄호 연산자를 사용하는 것은 객체에 대괄호 연산자를 사용하는 것과 마찬가지이고, 배여르이 요소 번호로 숫자 값 대신 문자열을 사용할 수 있다.

var a = ["A", "B", "C", "D"];
console.log(a["2"]); // -> C

// 없는 배열 요소를 읽으면 undefined 반환
a[4]; // undefined

4.5.6 배열 요소의 추가와 삭제

없는 배열 요소에 값을 대입하면 새로운 요소가 추가된다.

var a = ["A", "B", "C"];
a[3] = "D";
console.log(a); // ->  ["A", "B", "C", "D"]

// push() 메서드러 추가
var a = ["A", "B", "C"];
a.push("D");
console.log(a); // ->  ["A", "B", "C", "D"]

// delete() 메서드로 삭제
delete a[1];
console.log(a); // -> ["A", undefined, "C", "D"]
profile
프론트엔드 개발자가 되고 싶어요 🙆‍♂️

0개의 댓글

관련 채용 정보