6.20일 ch10 ~ ch12
자바스크립트는 객체(Object) 기반의 프로그래밍 언어이며 자바스크립를 구성하는 '모든 것'이 객체다.
원시 타입은 단 하나의 값만 나탄지만 객체 타입은 다양한 값(원시 값 또는 다른 객체)을 하나의 단위로 구성한 복합적인 자료구조이이다. 또한 원시 타입의 값, 즉 원시 값은 변경 불가능한 값immutable value
이지만 객체 타입의 값, 즉 객체는 변경 가능mutable value
한 값이다.
객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 키(key)와 값(value)으로 구성된다.
메서드method
라고 부른다.프로퍼티
- 객체의 상태를 나타내는 값(data)
메서드
- 프로퍼트(상태 데이터)를 참조하고 조작할 수 있는 동작(behavior)
클래스 기반 객체지향 언어는 클래스를 사전에 정의하고 필요한 시점에 new 연산자와 함께 생성자를 호출하여 인스턴스를 생성하는 방식으로 객체를 생성한다.
인스턴스instance
- 클래스에 의해 생성되어 메모리에 저장된 실체, 객체는 클래스와 인스턴스를 포함한 개념,클래스는 인스턴스를 생성하기 위한 템플릿의 역할
자바스크립트는 프로토타입 기반 객체지향 언어로서 클래스 기반 객체지향 언어와는 달리 다양한 객체 생성 방법 지원
-> 가장 일반적이고 간단한 방법은 객체 리터럴을 사용
리터럴literal
- 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용하여 값을 생성하는 표기법, 객체 리터럴은 객체를 생성하기 위한 표기법
var person = {
name: 'harbour',
sayHello: function() {
console.log(`Hello! My name is ${this.name}.`);
}
};
console.log(typeof person); // object
console.log(person); // {name:'harbour', sayHello: f}
//만약 중괄호 내에 프로퍼티를 정의하지 않으면 빈 객체가 생성된다.
var empty = {} // 빈 객체
console.log(typeof empty); //object
⚠️ 객체 리터럴의 중괄호는 코드 블록을 의미하지 않는다. (코드 블록은 닫을 때 세미콜론을 붙이지 않는다)
객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다.
프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌 값
프로퍼티 값 : 자바스크립트에서 사용할 수 있는 모든 값
마침표 표기법
대괄호 표기법: 반드시 따옴표로 감싼 문자열이여야 함
객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환한다.
let person = {
name: 'harbour'
}
console.log(person.name); //마침표 표기법
console.log(person['name']); // 대괄호 표기법
console.log(person[name]); // referenceError: name is not defined
console.log(person.age); // undefined
let person = {
name: 'harbour'
};
//person 객체에 name 프로퍼티가 존재하므로 name 프로퍼티의 값이 갱신된다
person.name = 'zzinao';
cosole.log(person); // {name: 'zzinao'}
let person = {
name: "harbour"
};
person.age = 20;
console.log(person); // {name: "harbour", age: 20}
delte연산자로 ㅍ로퍼티를 삭제할 수 있다
프로퍼티 축약 표현
키와 값이 같으면 프로퍼티 키를 생략할 수 있다.
계산된 프로퍼티 이름
원시 값은 변경 불가능하다 라는 말은 원시 값 자체를 변경할 수 없다는 것, 변수 값을 변경할 수 없다는 것이 아니다. -> 변수는 언제든지 재할당을 통해 변수 값을 변경(엄밀히 말하자면 교체)할 수는 있지만 상수는 단 한 번만 할당이 허용되므로 변수 값을 변경할 수 없다.
원시 타입별로 메모리 공간의 크기가 미리 정해져있다.
let score = 80;
let copy = score;
console.log(score, copy); // 80 80
console.log(score === copy); //true
변수에 원시 값을 갖는 변수를 할당하면 할당받는 변수에는 할당되는 변수의 원시 값이 복사되어 전달된다.
->값에 의한 전달
이때 score 변수와 copy 변수는 숫자 값 80을 갖는다는 점에서 동일하다. 하지만 둘의 값은 다른 메모리 공간에 저장된 별개의 값이다.
-> 사실은 값을 전달하는 것이 아니라 메모리 주소를 전달, 전달된 메모리 주소를 통해 메모리 공간에 접근하면 값을 참조할 수 있다.
프로그래밍 언어의 함수는 일련의 과정을 문으로 구현하고 코드블록으로 감싸서 하나의 실행 단위로 정의한 것
함수는 필요할 때 여러 번 호출할 수 있다. -> 코드의 재사용이라는 측면에서 매우 유용
함수는 객체지만 일반 객체와는 다름, 일반 객체는 호출할 수 없지만 함수는 호출할 수 있다.그리고 고유한 프로퍼티를 갖는다.
//1. 함수 선언문
function add(x,y){
return x+y;
}
//2. 함수 표현식
let add = function(x,y){
return x+y;
};
//3. function 생성자 함수
let add new Function('x', 'y', 'return x+y');
//4. 화살표 함수(ES6)
let add = (x,y) => x+y;
함수 선언문
함수 선언문은 함수 이름을 생략할 수 없다. 표현식이 아닌 문,
함수 표현식
함수는 일급객체이므로 함수 리터럴로생성한 함수 객체를 변수에 할당할 수 있다 -> 함수 표현식
함수 리터럴의 함수 이름은 생략할 수 있다.(일반적)
//함수 참조
console.dir(add) // f add(x,y)
console.dir(sub); // undefined
//함수 호출
console.log(add(2, 5)); //7
console.log(sub(2, 5)); // TypeError: sub is not a function
//함수 선언문
function add(x, y){
return x+y;
}
//함수 표현식
let sub = function (x, y) {
return x-y;
};
함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다. 그러나 함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출할 수 없다. -> 정의한 함수의 생성 시점이 다르기 때문
var 키워드를 사용한 변수 선언문과 함수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다는 점에서 동일, 하지만 var 키워드로 선언된 변수는 undefined로 초기화되고, 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화된다.
함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문, 따라서 함수 표현식은 변수 선언문과 변수 할당문을 한 번에 기술한 축약 표현과 동일하게 동작,
변수 선언은 런타임 이전에 실행되어 undefined로 초기화되지만 변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
-> 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
function 생성자 함수
일반적이지 않으며 바람직하지 않은 방식
function 생성자 함수로 생성한 함수는 클로저를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작한다.
화살표 함수
화살표 함수는 생성자 함수로 사용할 수 없으며 기존 함수와 this바인딩 방식이 다르고 prototype프로퍼티가 없으며 arguments객체를 생성하지 않는다.
함수는 함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출한다. 함수 호출 연산자 내에는 0개 이상의 인수를 쉼표로 구분해서 나열한다. 함수를 호출하면 현재의 실행 흐름을 중단하고 호출된 함수로 실행 흐름을 옮긴다.
함수를 실행하기 위해 필요한 값을 함수 외부에서 함수 내부로 전달할 필요가 있는경우, 매개변수를 통해 인수를 전달한다.인수는 값으로 평가될 수 있는 표현식어야한다.
매개변수는 함수 몸체 내부에서만 참조할 수 있고 함수 몸체 외부에서는 참조할 수 없다.
function add(x,y){
console.log(x,y); //2 5
return x + y;
}
add(2,5);
console.log(x, y) // ReferenceError: x is not defined
function nan(x,y){
return x + y;
}
console.log(add(2)); // NaN
function addd(x, y){
console.log(arguments); // Arfuments(3) [2,5,10 callee:....]
return x + y;
};
console.log(add(2, 5, 10); // 7
함수의 정의와 동시에 즉시 호출되는 함수, 단 한 번만 호출되며 다시 호출할 수 없다.
반드시 그룹 연산자(...)로 감싸야한다.
함수 이름이 없는 익명 함수를 사용하는 것이 일반적이며 이름이 있을 경우 다시 호출할 수는 없다.
(function(){
let a = 3;
let b = 5;
return a * b;
}());
함수가 자기 자신을 호출하는 것을 재귀함수라고 한다.
재귀 함수는 반복되는 처리를 위해 사용한다.
//팩토리얼(계승)은 1부터 자신까지의 모든 양의 정수의 곱
// n! = 1 * 2 * ....* (n-1) * n
function factorial(n){
//탈출 조건: n이 1 이하일 때 재귀 호출을 멈춘다.
if(n <= 1) return 1;
//재귀 호출
return n * factorial(n-1);
}
console.log(factorial(5)); // 5! = 5*4*3*2*1 = 120
재귀함수는 자신을 무한 재귀호출한다. 따라서 재귀함수 내에는 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다.
대부분의 재귀 함수는 for문이나 while문으로 구현 가능하다
함수 내부에 정의된 함수를 중첩 함수, 또는 내부 함수라고 한다. 그리고 중첩 함수를 포함하는 함수는 외부 함수라고 부른다. 중첩 함수는 외부 함수 내부에서만 호출할 수 있다. 일반적으로 중첩 함수는 자신을 포함하는 외부 함수를 돕는 헬퍼 함수의 역할을 한다.
function outer() {
let x = 1;
//중첩 함수
function inner() {
let y = 2;
console.log(x+y); //3 외부 함수의 변수를 참조할 수 있다.
}
inner();
}
outer();
function repeat(n, f){
for(let i = 0; i< n; i++){
f(i);
}
}
let logAll = function(i) {
console.log(i);
};
repeat(5, logAll) // 0 1 2 3 4
repeat함수는 경우에 따라 변경되는 일을 함수 f로 추상화했고 이를 외부에서 전달받는다. 자바스크립트의 함수는 일급 객체이므로 함수의 매개변수를 통해 함수를 전달할 수 있다. repeat 함수는 더 이상 내부로직에 강력히 의존하지 않고 외부에서 로직의 일부분을 함수로 전달받아 수행하므로 더욱 유연한 구조를 갖게 되었다.
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수라고 한다.
매개 변수를 통해 외부에서 콜백 함수를 전달받은 함수를 고차함수라고 한다.
중첩 함수가 외부 함수를 돕는 헬퍼 함수의 역할을 하는 것처럼 콜백함수도 고차함수에 전달되어 헬퍼 함수의 역할을 한다. 단 중첩함수는 고정되어 있어서 교체하기 곤란하지만 콜백함수는 함수 외부에서 고차 함수 내부로 주입하기 때문에 자유롭게 교체할 수 있다.
-> 고차 함수는 콜백함수를 자신의 일부분으로 합성한다
고차 함수는 매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출한다.
콜백함수는 고차 함수에 호출 되며 이때 고차함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다.
콜백 함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리(이벤트 처리, ajax 통신, 타이머 함수 등)에 활용되는 중요한 패턴이다.
함수형 프로그래밍에서는 어떤 외부 상태에 의존하지도 않고 변경하지도 않는 부수 효과가 없는 함수를 순수 함수라고 하고, 외부 상태에 의존하거나 외부 상태를 변경하는 즉 부수 효과가 있는 함수를 비순수 함수라고 한다.