var, let, const
키워드를 사용var
키워드를 사용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행자바스크립트 코드를 해석하고 실행하는 자바스크립트 엔진이 수행할 동작을 규정한 일종의 명령어
자바스크립트에서 제공하는 원시 타입의 값
console.log(score); //undefined
var score; //변수 선언문
변수 선언이 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문에 참조에러가 발생하는게 아닌
undefined
가 출력
즉, 자바스크립트 엔진은 변수 선언이 소스코드 어디에 있든 상관없이 다른 코드보다 먼저 실행. 따라서 변수 선언이 어디에 위치하는지 상관없이 어디서든지 변수 참조 가능
var, let, const, function,* class
키워드를 사용해서 선언하는 모든 식별자(변수, 함수, 클래스 등)는 호이스팅 된다.console.log(score); // undefined
var score; // ① 변수 선언
score = 80; // ② 값의 할당
console.log(score); // 80
변수에 값을 할당할 때는 이전 값
undefined
가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 80을 새롭게 저장하는 것이 아닌 새로운 메모리 공간을 확보하고 그곳에 할당 값 80을 저장한다
constant
를 사용해 선언한 변수는 재할당이 금지
하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙
// 카멜 케이스 (camelCase)
var firstName;
// 스네이크 케이스 (snake_case)
var first_name;
// 파스칼 케이스 (PascalCase)
var FirstName;
// 헝가리언 케이스 (typeHungarianCase)
var strFirstName; // type + identifier
var $elem = document.getElementById('myId'); // DOM 노드
var observable$ = fromEvent(document, 'click'); // RxJS 옵저버블
리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법
// 리터럴 표현식
10
'Hello'
// 식별자 표현식(선언이 이미 존재한다고 가정)
sum
person.name
arr[1]
// 연산자 표현식
10 + 20
sum = 10
sum !== 10
// 함수/메서드 호출 표현식(선언이 이미 존재한다고 가정)
square()
person.getName()
1+2 = 3
// 변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다.
var x;
// 1, 2, 1 + 2, x = 1 + 2는 모두 표현식이다.
// x = 1 + 2는 표현식이면서 완전한 문이기도 하다.
x = 1 + 2;
// 표현식이 아닌 문은 값처럼 사용할 수 없다.
var foo = var x; // SyntaxError: Unexpected token var
undefined
를 출력하는 것이 완료값이다.// 모두 숫자 타입이다.
var integer = 10; // 정수
var double = 10.12; // 실수
var negative = -20; // 음의 정수
var binary = 0b01000001; // 2진수
var octal = 0o101; // 8진수
var hex = 0x41; // 16진수
// 표기법만 다를 뿐 모두 같은 값이다.
console.log(binary); // 65
console.log(octal); // 65
console.log(hex); // 65
console.log(binary === octal); // true
console.log(octal === hex); // true
Infinity
: 양의 무한대-Infinity
: 음의 무한대NaN
: 산술 연산 불가// 숫자 타입의 세 가지 특별한 값
console.log(10 / 0); // Infinity
console.log(10 / -0); // -Infinity
console.log(1 * 'String'); // NaN
NaN
≠ nan
' ', " ", 백틱
으로 텍스트를 감싼다// 문자열 타입
var string;
string = '문자열'; // 작은따옴표
string = "문자열"; // 큰따옴표
string = `문자열`; // 백틱 (ES6)
string = '작은따옴표로 감싼 문자열 내의 "큰따옴표"는 문자열로 인식된다.';
string = "큰따옴표로 감싼 문자열 내의 '작은따옴표'는 문자열로 인식된다.";
var template = `Template literal`;
console.log(template); // Template literal
var str = 'Hello
world.';
// SyntaxError: Invalid or unexpected token
\
)로 시작하는 이스케이프 시퀀스를 사용+
를 사용해 연결+
연산자는 피연산자중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작var first = 'Ung-mo';
var last = 'Lee';
// ES5: 문자열 연결
console.log('My name is ' + first + ' ' + last + '.'); // My name is Ung-mo Lee.
var first = 'Ung-mo';
var last = 'Lee';
// ES6: 표현식 삽입
console.log(`My name is ${first} ${last}.`); // My name is Ung-mo Lee.
${ }
으로 표현식을 감싼다불리언 타입의 값은 논리적참, 거짓을 나타내는 true
와 false
뿐이다.
undefined
값은 undefined
가 유일undefined
는 의도적으로 할당한 값이 아닌 자바스크립트 엔진이 변수를 초기화 할 때 사용하는 값null
타입의 값은 null
이 유일null
은 변수에 값이 엇다는 것으 의도적으로 명시 할때 사용null
을 반환자바스크립트를 이루고 있는 거의 모든 것이 객체다
var foo;
console.log(typeof foo); // undefined
foo = 3;
console.log(typeof foo); // number
foo = 'Hello';
console.log(typeof foo); // string
foo = true;
console.log(typeof foo); // boolean
foo = null;
console.log(typeof foo); // object
foo = Symbol(); // 심벌
console.log(typeof foo); // symbol
foo = {}; // 객체
console.log(typeof foo); // object
foo = []; // 배열
console.log(typeof foo); // object
foo = function () {}; // 함수
console.log(typeof foo); // function
산술연산이 불가능한 경우 NaN
을 반환
부수 효과(side effect)
값을 반환하는 메서드나 함수가 외부 상태를 변경하는 경우
++/--
) 연산자는 피연산자의 값을 변경하는 부수 효과가 있다var x = 5, result;
// 선할당 후증가(postfix increment operator)
result = x++;
console.log(result, x); // 5 6
// 선증가 후할당(prefix increment operator)
result = ++x;
console.log(result, x); // 7 7
// 선할당 후감소(postfix decrement operator)
result = x--;
console.log(result, x); // 7 6
// 선감소 후할당 (prefix decrement operator)
result = --x;
console.log(result, x); // 5 5
+
단항 연산자는 피연산자에 어떠한 효과도 없다+
연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작
그 외에는 산술 연산자로 동작
// true는 1로 타입 변환된다.
1 + true; // -> 2
// false는 0으로 타입 변환된다.
1 + false; // -> 1
좌항과 우항의 피연산자를 비교한 다음 결과를 불리언 값으로 반환
// 타입은 다르지만 암묵적 타입 변환을 통해 타입을 일치시키면 동등하다.
5 == '5'; // -> true
// 암묵적 타입 변환을 하지 않고 값을 비교한다.
// 즉, 값과 타입이 모두 같은 경우만 true를 반환한다.
5 === '5'; // -> false
// NaN은 자신과 일치하지 않는 유일한 값이다.
NaN === NaN; // -> false
// 양의 0과 음의 0의 비교. 일치 비교/동등 비교 모두 결과는 true이다.
0 === -0; // -> true
0 == -0; // -> true
피연산자의 크기를 비교하여 불리언 값을 반환
조건식의 평가 결과에 따라 반환할 값을 결정
왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환
typeof
연산자는 7가지 문자열 "string", "number", "boolean", "undefined", "symbol", "object", "function"중 하나를 반환typeof '' // -> "string"
typeof 1 // -> "number"
typeof NaN // -> "number"
typeof true // -> "boolean"
typeof undefined // -> "undefined"
typeof Symbol() // -> "symbol"
typeof null // -> "object"
typeof [] // -> "object"
typeof {} // -> "object"
typeof new Date() // -> "object"
typeof /test/gi // -> "object"
typeof function () {} // -> "function"
typeof 연산자가 반환하는 문자열은 7개의 데이터 타입과 정확히 일치하지는 않는다
-5 ** 2;
// SyntaxError: Unary operator used immediately before exponentiation expression.
// Parenthesis must be used to disambiguate operator precedence
(-5) ** 2; // -> 25
지수 연산자는 이항 연산자 중 우선순위가 가장 높음
연산자가 실행되는 순서
연산자의 어느쪽 부터 평가를 수행할 것인지를 나타내는 순서
// 블록문
{
var foo = 10;
}
주어진 조건식의 평가 결과에 따라 코드 블록의 실행을 결정
주어진 조건식의 평가 결과, 논리적 참 또는 거짓에 따라 실행할 코드 블록을 결정
case
문으로 실행 흐름을 옮긴다case
문은 상황을 의미하는 표현식을 지정하고 콜론으로 마친다// 무한루프
for (;;) { ... }
주어진 조건식의 평가 결과가 참이면 코드 블록을 계속해서 반복 실행
for
문은 반복 횟수가 명확할 때 사용while
문은 반복 횟수가 불명확할 때 사용코드블럭을 먼저 실행하고 조건식을 평가
switch문, 레이블 문, 반복문
외에 사용시 문법 에러 발생// foo라는 레이블 식별자가 붙은 레이블 문
foo: console.log('foo');
break
문처럼 반복문을 탈출하지는 않는다문자열 연결 연산자의 피연산자 중에서 문자열 타입이 아닌 피연산자를 문자열 타입으로 변환한다
1 + '2' // -> "12"
// 숫자 타입
0 + '' // -> "0"
-0 + '' // -> "0"
1 + '' // -> "1"
-1 + '' // -> "-1"
NaN + '' // -> "NaN"
Infinity + '' // -> "Infinity"
-Infinity + '' // -> "-Infinity"
// 불리언 타입
true + '' // -> "true"
false + '' // -> "false"
// null 타입
null + '' // -> "null"
// undefined 타입
undefined + '' // -> "undefined"
// 심벌 타입
(Symbol()) + '' // -> TypeError: Cannot convert a Symbol value to a string
// 객체 타입
({}) + '' // -> "[object Object]"
Math + '' // -> "[object Math]"
[] + '' // -> ""
[10, 20] + '' // -> "10,20"
(function(){}) + '' // -> "function(){}"
Array + '' // -> "function Array() { [native code] }"
NaN
이 된다// 문자열 타입
+'' // -> 0
+'0' // -> 0
+'1' // -> 1
+'string' // -> NaN
// 불리언 타입
+true // -> 1
+false // -> 0
// null 타입
+null // -> 0
// undefined 타입
+undefined // -> NaN
// 심벌 타입
+Symbol() // -> TypeError: Cannot convert a Symbol value to a number
// 객체 타입
+{} // -> NaN
+[] // -> 0
+[10, 20] // -> NaN
+(function(){}) // -> NaN
불리언 타입이 아닌 값을 Truthy 값(참으로 평가되는 값) 또는 Falsy 값(거짓으로 평가되는 값)으로 구분
false
로 평가되는 Falsy값false, undefined, null, 0, -0, NaN, 빈 문자열
true
로 평가되는 Truthy 값이다// 1. String 생성자 함수를 new 연산자 없이 호출하는 방법
// 숫자 타입 => 문자열 타입
String(1); // -> "1"
String(NaN); // -> "NaN"
String(Infinity); // -> "Infinity"
// 불리언 타입 => 문자열 타입
String(true); // -> "true"
String(false); // -> "false"
// 2. Object.prototype.toString 메서드를 사용하는 방법
// 숫자 타입 => 문자열 타입
(1).toString(); // -> "1"
(NaN).toString(); // -> "NaN"
(Infinity).toString(); // -> "Infinity"
// 불리언 타입 => 문자열 타입
(true).toString(); // -> "true"
(false).toString(); // -> "false"
// 3. 문자열 연결 연산자를 이용하는 방법
// 숫자 타입 => 문자열 타입
1 + ''; // -> "1"
NaN + ''; // -> "NaN"
Infinity + ''; // -> "Infinity"
// 불리언 타입 => 문자열 타입
true + ''; // -> "true"
false + ''; // -> "false"
// 1. Number 생성자 함수를 new 연산자 없이 호출하는 방법
// 문자열 타입 => 숫자 타입
Number('0'); // -> 0
Number('-1'); // -> -1
Number('10.53'); // -> 10.53
// 불리언 타입 => 숫자 타입
Number(true); // -> 1
Number(false); // -> 0
// 2. parseInt, parseFloat 함수를 사용하는 방법(문자열만 변환 가능)
// 문자열 타입 => 숫자 타입
parseInt('0'); // -> 0
parseInt('-1'); // -> -1
parseFloat('10.53'); // -> 10.53
// 3. + 단항 산술 연산자를 이용하는 방법
// 문자열 타입 => 숫자 타입
+'0'; // -> 0
+'-1'; // -> -1
+'10.53'; // -> 10.53
// 불리언 타입 => 숫자 타입
+true; // -> 1
+false; // -> 0
// 4. * 산술 연산자를 이용하는 방법
// 문자열 타입 => 숫자 타입
'0' * 1; // -> 0
'-1' * 1; // -> -1
'10.53' * 1; // -> 10.53
// 불리언 타입 => 숫자 타입
true * 1; // -> 1
false * 1; // -> 0
// 1. Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
// 문자열 타입 => 불리언 타입
Boolean('x'); // -> true
Boolean(''); // -> false
Boolean('false'); // -> true
// 숫자 타입 => 불리언 타입
Boolean(0); // -> false
Boolean(1); // -> true
Boolean(NaN); // -> false
Boolean(Infinity); // -> true
// null 타입 => 불리언 타입
Boolean(null); // -> false
// undefined 타입 => 불리언 타입
Boolean(undefined); // -> false
// 객체 타입 => 불리언 타입
Boolean({}); // -> true
Boolean([]); // -> true
// 2. ! 부정 논리 연산자를 두번 사용하는 방법
// 문자열 타입 => 불리언 타입
!!'x'; // -> true
!!''; // -> false
!!'false'; // -> true
// 숫자 타입 => 불리언 타입
!!0; // -> false
!!1; // -> true
!!NaN; // -> false
!!Infinity; // -> true
// null 타입 => 불리언 타입
!!null; // -> false
// undefined 타입 => 불리언 타입
!!undefined; // -> false
// 객체 타입 => 불리언 타입
!!{}; // -> true
!![]; // -> true
&&
) 연산자와 논리합(||
) 연산자는 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환하는것을 단축평가라 한다var done = true;
var message = '';
// 주어진 조건이 true일 때
if (done) message = '완료';
// if 문은 단축 평가로 대체 가능하다.
// done이 true라면 message에 '완료'를 할당
message = done && '완료';
console.log(message); // 완료
-------------------------------------------------------------
var done = false;
var message = '';
// 주어진 조건이 false일 때
if (!done) message = '미완료';
// if 문은 단축 평가로 대체 가능하다.
// done이 false라면 message에 '미완료'를 할당
message = done || '미완료';
console.log(message); // 미완료
?.
는 좌항의 피연산자가 null
또는 undefined
인 경우 undefined
를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조null
또는 undefined
가 아닌지 확인하고 프로퍼티를 참조할 때 유용??
는 좌항의 피연산자가 null
또는 undefined
인 경우 우항의 피연산자를 반환, 그렇지 않으면 좌항의 피연산자를 반환var person = {
name: 'Lee',
sayHello: function () {
console.log(`Hello! My name is ${this.name}.`);
}
};
console.log(typeof person); // object
console.log(person); // {name: "Lee", sayHello: ƒ}
var person = {
// 프로퍼티 키는 name, 프로퍼티 값은 'Lee'
name: 'Lee',
// 프로퍼티 키는 age, 프로퍼티 값은 20
age: 20
};
var person = {
firstName: 'Ung-mo', // 식별자 네이밍 규칙을 준수하는 프로퍼티 키
'last-name': 'Lee' // 식별자 네이밍 규칙을 준수하지 않는 프로퍼티 키
};
console.log(person); // {firstName: "Ung-mo", last-name: "Lee"}
문자열 표현식을 사용해 프로퍼티 키를 동적으로 생성할 시 대괄호로 묶어야 한다
프로퍼티 값이 함수일 경우 메서드라 한다
var circle = {
radius: 5, // ← 프로퍼티
// 원의 지름
getDiameter: function () { // ← 메서드
return 2 * this.radius; // this는 circle을 가리킨다.
}
};
console.log(circle.getDiameter()); // 10
.
)를 사용하는 마침표 표기법[...]
)를 사용하는 대괄호 표기법var person = {
name: 'Lee'
};
// person 객체에 name 프로퍼티가 존재하므로 name 프로퍼티의 값이 갱신된다.
person.name = 'Kim';
console.log(person); // {name: "Kim"}
var person = {
name: 'Lee'
};
// person 객체에는 age 프로퍼티가 존재하지 않는다.
// 따라서 person 객체에 age 프로퍼티가 동적으로 생성되고 값이 할당된다.
person.age = 20;
console.log(person); // {name: "Lee", age: 20}
delete
연산자는 객체의 프로퍼티를 삭제하며 delete
연산자의 피연산자는 프로퍼티 값에 접근할 수 있는 표현식이어야 한다var person = {
name: 'Lee'
};
// 프로퍼티 동적 생성
person.age = 20;
// person 객체에 age 프로퍼티가 존재한다.
// 따라서 delete 연산자로 age 프로퍼티를 삭제할 수 있다.
delete person.age;
// person 객체에 address 프로퍼티가 존재하지 않는다.
// 따라서 delete 연산자로 address 프로퍼티를 삭제할 수 없다. 이때 에러가 발생하지 않는다.
delete person.address;
console.log(person); // {name: "Lee"}
function
키워드를 생략한 축약 표현 사용 가능
// ES5
var obj = {
name: 'Lee',
sayHi: function() {
console.log('Hi! ' + this.name);
}
};
obj.sayHi(); // Hi! Lee
-------------------------------------------------------------------------------
// ES6
const obj = {
name: 'Lee',
// 메서드 축약 표현
sayHi() {
console.log('Hi! ' + this.name);
}
};
obj.sayHi(); // Hi! Lee
원시 값을 할당한 변수에 새로운 원시 값을 재할당시 새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장후, 변수는 새롭게 재할당한 원시 값을 가리킨다.
원시 값은 변경 불가능한 값이어서 직접 변경 불가능하다. 변수 값 변경하기 위해 원시값을 재할당 하면 새로운 메모리 공간을 확보하고 재할당한 값을 저장 후, 변수가 참조하던 메모리 공간의 주소를 변경한다. 값의 이러한 특성을 불변성이라고 한다
불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 변수 값을 변경할 수 있는 방법은 없다
var str = 'Hello';
str = 'world';
str
은 'Hello'
가 저장된 메모리 공간의 첫 번째 메모리 셀 주소를 가리킴'world'
를 메모리에 생성하고 식별자 str
은 이것을 가리킴'Hello'
는 사라지는게 아닌 'Hello'
와 'world'
는 모두 메모리에 존재변수에 원시 값을 갖는 변수를 할당하면 할당받는 변수에는 할당되는 변수의 원시 값이 복사되어 전달
var score = 80;
// copy 변수에는 score 변수의 값 80이 복사되어 할당된다.
var copy = score;
console.log(score, copy); // 80 80
console.log(score === copy); // true
값의 의한 전달은 정확히 말하자면 값을 전달하는것이 아닌 메모리 주소를 전달하는 것이다. 단, 전달된 메모리 주소를 통해 메모리 공간에 접근하면 값을 참조 가능
따라서 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭 불가능
var person = {
name: 'Lee'
};
// 프로퍼티 값 갱신
person.name = 'Kim';
// 프로퍼티 동적 생성
person.address = 'Seoul';
console.log(person); // {name: "Kim", address: "Seoul"}
부작용: 여러개의 식별자가 하나의 객체를 공유할 수 있다
객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달
var person = {
name: 'Lee'
};
// 참조값을 복사(얕은 복사). copy와 person은 동일한 참조값을 갖는다.
var copy = person;
// copy와 person은 동일한 객체를 참조한다.
console.log(copy === person); // true
// copy를 통해 객체를 변경한다.
copy.name = 'Kim';
// person을 통해 객체를 변경한다.
person.address = 'Seoul';
// copy와 person은 동일한 객체를 가리킨다.
// 따라서 어느 한쪽에서 객체를 변경하면 서로 영향을 주고 받는다.
console.log(person); // {name: "Kim", address: "Seoul"}
console.log(copy); // {name: "Kim", address: "Seoul"}
일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것
함수 선언문은 함수 이름을 생략 불가능
함수 선언문은 표현식이 아닌 문이므로 변수에 할당 불가능
// 기명 함수 리터럴을 단독으로 사용하면 함수 선언문으로 해석된다.
// 함수 선언문에서는 함수 이름을 생략할 수 없다.
function foo() { console.log('foo'); }
foo(); // foo
// 함수 리터럴을 피연산자로 사용하면 함수 선언문이 아니라 함수 리터럴 표현식으로 해석된다.
// 함수 리터럴에서는 함수 이름을 생략할 수 있다.
(function bar() { console.log('bar'); });
bar(); // ReferenceError: bar is not defined
함수 리터럴의 함수 이름은 생략가능, 이러한 함수를 익명 함수라고 한다
// 함수 참조
console.dir(add); // ƒ 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;
}
// 함수 표현식
var sub = function (x, y) {
return x - y;
};
함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문에 타입 에러가 난다. 따라서 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출
=>
를 사용// 화살표 함수
const add = (x, y) => x + y;
console.log(add(2, 5)); // 7
화살표 함수는 생성자 함수로 사용 불가능. 기존 함수와 this 바인딩 방식이 다르고 ,prototype 프로퍼티가 없으며 arguments객체를 생성하지 않음
함수를 실행하기 위해 필요한 값을 함수 외부에서 내부로 전달할 때 매개변수를 통해 인수를 전달
undefined
function add(x, y) {
return x + y;
}
console.log(add(2)); // NaN
function add(x, y) {
return x + y;
}
console.log(add(2, 5, 10)); // 7
함수는 return
키워드와 반환값으로 이뤄진 반환문을 사용해 실행 결과를 함수 외부로 반환 할 수 있다
반환문의 역할
1. 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다
2. 반환문은 return
키워드 뒤에 오는 표현식을 평가해 반환
return
뒤에 반환값으로 사용할 표현식을 명시적으로 지정하지 않으면 undefined
가 반환function foo () {
return;
}
console.log(foo()); // undefined
function foo () {
// 반환문을 생략하면 암묵적으로 undefined가 반환된다.
}
console.log(foo()); // undefined
// 매개변수 primitive는 원시 값을 전달받고, 매개변수 obj는 객체를 전달받는다.
function changeVal(primitive, obj) {
primitive += 100;
obj.name = 'Kim';
}
// 외부 상태
var num = 100;
var person = { name: 'Lee' };
console.log(num); // 100
console.log(person); // {name: "Lee"}
// 원시 값은 값 자체가 복사되어 전달되고 객체는 참조 값이 복사되어 전달된다.
changeVal(num, person);
// 원시 값은 원본이 훼손되지 않는다.
console.log(num); // 100
// 객체는 원본이 훼손된다.
console.log(person); // {name: "Kim"}
(...)
로 감싸야 한다// 즉시 실행 함수도 일반 함수처럼 값을 반환할 수 있다.
var res = (function () {
var a = 3;
var b = 5;
return a * b;
}());
console.log(res); // 15
// 즉시 실행 함수에도 일반 함수처럼 인수를 전달할 수 있다.
res = (function (a, b) {
return a * b;
}(3, 5));
console.log(res); // 15
함수 내부에 정의된 함수
function outer() {
var x = 1;
// 중첩 함수
function inner() {
var y = 2;
// 외부 함수의 변수를 참조할 수 있다.
console.log(x + y); // 3
}
inner();
}
outer();
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
var count = 0; // 현재 카운트를 나타내는 상태
// 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환한다.
function increase(n) {
return ++n;
}
// 순수 함수가 반환한 결과값을 변수에 재할당해서 상태를 변경
count = increase(count);
console.log(count); // 1
count = increase(count);
console.log(count); // 2
var count = 0; // 현재 카운트를 나타내는 상태: increase 함수에 의해 변화한다.
// 비순수 함수
function increase() {
return ++count; // 외부 상태에 의존하며 외부 상태를 변경한다.
}
// 비순수 함수는 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려워진다.
increase();
console.log(count); // 1
increase();
console.log(count); // 2