일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 파이썬프로그래밍기초
- 방송대
- 코드잇
- 99클럽
- TiL
- 코딩테스트준비
- 꿀단집
- CSS
- Python
- 엘리스sw트랙
- HTML
- 중간이들
- 항해99
- 데이터베이스시스템
- Git
- 프로그래머스
- 유노코딩
- MySQL
- node.js
- redis
- JavaScript
- 방송대컴퓨터과학과
- presignedurl
- 파이썬
- 코딩테스트
- nestjs
- 개발자취업
- Cookie
- SQL
- aws
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] 모던 자바스크립트 ① 모던 자바스크립트 이해, 동작원리, 함수 다루기 본문
1. 모던 자바스크립트 이해하기
모던 자바스크립트에 대한 이해
• ECMAScript : 자바스크립트 표준 명세서 (JavaScript Specification)
· 'Standard ECMA-262'라는 이름으로 관리되고 있음.
· ES1 : 1997년에 등장
· ES6 : 2015년에 등장 (정식 명칭 : ES2015)
· 웹브라우저가 당장 새로운 버전의 문법을 지원하지 않음. → 최신 버전을 바로 적용하는 것이 힘듦.
· 보편적으로 사용되는 브라우저들이 지원하는 범위 내에서 ECMA스크립트를 준수하는 것이 일반적임.
• Modern JavaScript : 현시점에 사용하기 적합한 범위 내에서 최신 버전의 표준을 준수하는 자바스크립트
2. 자바스크립트의 동작 원리
데이터 타입의 특징과 종류
자바스크립트의 데이터타입 특징
• Python : 데이터 타입이 다른 변수끼리는 연산 불가능 (ex. 2 + "3")
• C, Java : 변수에도 데이터 타입을 지정, 타입이 정해진 변수에 다른 타입은 지정 불가
• Javascript :
- 데이터타입이 다른 경우도 연산 가능
ex. 2 + "3" = "23" (숫자 + 문자열 = 문자열)
숫자 2를 문자열 2로 인식해서 문자열끼리의 연산으로 계산함.
// + 연산자 : 문자열 연결을 수행
// 나머지 산술 연산자 : 숫자 간에만 작동
a = 2 + "3"
console.log(a) // 23
console.log(typeof(a)) // string
b = 2 * "3"
console.log(b) // 6
console.log(typeof(b)) // number
c = 2 / "3"
console.log(c) // 0.6666666666666666
console.log(typeof(c)) // number
d = 2 - "3"
console.log(d) // -1
console.log(typeof(d)) // number
- 변수에 따로 타입을 정해주지 않기 때문에 언제든지 다양한 타입의 값으로 재할당이 가능함.
let x = 0;
x = 'Codeit';
x = false;
x = null;
x = undefined;
x = {};
자바스크립트에서는 데이터 타입에 대한 이해가 중요함.
내가 작성한 코드가 어떤 타입의 데이터인지 알고 있어야 예상치 못한 결과로 오류 나는 상황을 피할 수 있음.
자바스크립트 데이터타입 종류
• 기본형 (Primitive Type) : Number, String, Boolean, Symbol, BigInt, Null, Undefined
- Symbol : (ES2015) 유일한 값을 만들 때
- BigInt : (ES2020) 엄청 큰 숫자를 다룰 때
• 참조형 (Reference Type) : Object
Symbol과 BigInt
Symbol
코드 내 유일한 값을 가진 변수 이름을 만들 때 사용
const user = Symbol();
const user = Symbol('this is a user');
const symbolA = Symbol('apple');
const symbolA = Symbol('banana');
// SyntaxError: Identifier 'symbolA' has already been declared
해당 symbol 값을 담은 변수는 다른 어떤 값과 비교해도 true가 될 수 없음.
user === 'user' // false
user === 0; // false
user === null; // false
user === undefined; // false
symbol의 설명이 같아도 두 값을 비교하면 false가 나옴.
const symbolA = Symbol('apple');
const symbolB = Symbol('apple');
BigInt
매우 큰 연산을 다루거나 정확한 연산이 필요한 상황의 큰 정수를 표현
자바스크립트의 숫자형(number type) 값에는 9000조 정도의 정수 표현의 한계가 존재
→ 이 숫자 범위를 초과하는 정숫값 사용시에는 연산에 미세한 오류가 발생
이유 : 배정밀도 부동소수점 형식 숫자체계를 사용하기 때문 (IEEE 754)
표현방식
일반 정수 마지막에 'n'을 붙이기 또는 'BigInt' 함수 사용
console.log(9007199254740993n); // 9007199254740993n
console.log(BigInt(9007199254740993)); // 9007199254740993
특징
소수 표현에는 사용할 수 없어서 소수점 아랫부분이 절삭됨.
8.3n; // SyntaxError
6n / 4n; // 1n
BigInt 타입끼리만 연산 가능함.
다른 타입끼리 연산하려면 명시적 형변환이 필요함.
8n * 3; // TypeError
4n * 5n; // 20n
Number(5n) * 2; // 10
typeof 연산자
사용하는 값이 어떤 데이터타입을 나타내는지 알려주는 연산
typeof(NaN); // 괄호로 감싸기
typeof NaN; // 한칸 띄우기
* NaN
- 연산 과정에서 잘못된 입력을 받았음을 나타내는 기호
- 특히 부동소수점 연산에서 사용
typeof 'Codeit'; // string
typeof Symbol(); // symbol
typeof {}; // object
typeof []; // object
typeof true; // boolean
typeof(false); // boolean
typeof(123); // number
typeof(NaN); // number
typeof(456n); // bigint
typeof(undefined); // undefined
typeof(null)); // object
자바스크립트의 처음 구현단계에서 값은 타입 태그와 값으로 표시되었음.
객체의 타입 태그가 0이라서 null은 Null pointer(대부분의 플랫폼에서 0x00)로 표시되면서, 타입 태그로 0을 가졌음.
이후 typeof null === 'null'으로 수정이 제안되었으나 버그 우려로 거절됨.
// 함수의 데이터타입 : function
// 자바스크립트의 함수는 객체로 취급하나 데이터타입은 function임.
function greekyogurt() {
console.log('i love it');
}
console.log(typeof greekyogurt); // function
Falsy값과 Truthy값
자바스크립트의 조건문에서는 boolean이 아닌 다른 타입의 값들도 boolean으로 평가됨.
Falsy값
- false로 평가되는 값
- false, null, undefined, NaN, 0, ''(빈 문자열)
Truthy값
- True로 평가되는 값
- 나머지 값들
- [](빈배열), {}(빈 객체)
console.log(Boolean(-123)) // true
console.log(Boolean([])) // true
console.log(Boolean('')) // false
console.log(Boolean({})) // true
const fruits = ['apple', 'banana', 'orange', 'peach'];
for (let i = 3; i; i = i - 1) {
console.log(fruits[i]);
}
/*
i = 3 --> peach
i = 2 --> orange
i = 1 --> banana
i = 0 --> falsy값으로 평가되어서 반복문 종료됨.
*/
AND와 OR 연산 방식
상황에 따라서 어떤 값들을 선택하는 방식으로 동작함.
console.log('Codeit' && 'JavaScript'); // JavaScript
// 왼쪽 문자열이 truthy해서 오른쪽 값 반환
AND 와 OR 연산자 사이에서는 AND 연산자의 우선순위가 더 높음.
console.log(true || false && false); // true
console.log((true || false) && false); // false
console.log('Codeit' || NaN && false); // Codeit
console.log(('Codeit' || NaN) && false); // false
AND 연산자 (&&)
왼쪽값이 truthy하면 오른쪽 값을 리턴함.
왼쪽값이 falsy하면 왼쪽값을 리턴함.
console.log(true && true); // true (오른쪽)
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false (왼쪽)
OR 연산자 (||)
왼쪽값이 truthy하면 왼쪽 값을 리턴함.
왼쪽값이 falsy하면 오른쪽 값을 리턴함.
console.log(true || true); // true (왼쪽)
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false (오른쪽)
이런 방식을 조건식처럼 활용할 수 있음.
function print(eat) {
const message = eat || 'apple';
console.log(message);
}
print();
print('JavaScript');
// print()함수에 파라미터를 빈 값으로 두어서 print()함수 안 eat 변수에는 빈 값이 들어감.
// (falsy값 || truthy값) 이므로 truthy값인 'apple'이 리턴됨.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Operator_precedence
연산자 우선순위 - JavaScript | MDN
연산자 우선순위는 연산자를 실행하는 순서를 결정합니다. 우선순위가 높은 연산자가 먼저 실행됩니다.
developer.mozilla.org
null 병합 연산자??
null 병합 연산자(Nullish coalescing operator)
· 왼쪽 피연산자가 null 또는 undefined일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환하는 논리 연산자
· falsy값인지 여부는 고려하지 않음.
// 예시 1
const alternative1 = '' ?? 'Programming'; // ''(빈문자열)
const alternative2 = 0 ?? 'is'; // 0
const alternative3 = false ?? 'fun'; // false (boolean)
console.log(alternative1, alternative2, alternative3);
// 0 false
// 예시 2
const alternative4 = undefined ?? 'Programming';
const alternative5 = null ?? 'is';
const alternative6 = undefined ?? 'fun'; // false (boolean)
console.log(alternative4, alternative5, alternative6);
// Programming is fun
왼쪽이 null 또는 undefined가 아님이 판명되면 오른쪽 표현식은 평가되지 않음. (출처 : mdn)
function A() {
console.log("A was called");
return undefined;
}
function B() {
console.log("B was called");
return false;
}
function C() {
console.log("C was called");
return "foo";
}
console.log(A() ?? C());
// logs "A was called" then "C was called" and then "foo"
// as A() returned undefined so both expressions are evaluated
console.log(B() ?? C());
// logs "B was called" then "false"
// as B() returned false (and not null or undefined), the right
// hand side expression was not evaluated
변수와 스코프
var 키워드의 문제점 : 호이스팅(선언 전 사용 가능), 중복 선언 가능, 스코프는 함수 단위로 결정됨
ES2015에서는 Var 키워드가 가진 문제를 해결하기 위해 let, const를 사용함.
let (재할당 O), const (재할당 X)
호이스팅(hoisting)
· 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 이동시키는 과정
· 선언 부분만 끌어 올려짐.
→ 선언과 동시에 값을 할당해도, 할당된 값 자체는 그 이후에 접근 가능함.
console.log(title) // 변수 선언 전에 사용 가능 (undefined)
var title = 'apple'; // 변수 선언
console.log(title) // apple
console.log(title)
let title;
중복 선언 가능
var title = 'apple';
console.log(title);
var title = 'banana';
console.log(title);
실수로 이미 선언한 변수에 재할당하면 이전 변수는 사라짐.
let title = 'apple';
console.log(title);
let title = 'banana';
console.log(title);
함수 스코프 (function scope) - var
변수가 선언된 함수 내에서만 유효한 스코프
function example() {
if (true) {
var x = 10;
console.log(x); // 10
}
console.log(x); // 10
}
example();
console.log(x); // ReferenceError: x is not defined
function example() {
for (var i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
console.log("반복문 외부에서 i:", i); // 3 - 반복문 외부에서도 접근 가능
}
example();
블록 스코프 (block scope) - let, const
변수가 선언된 블록(일반적으로 중괄호 {}로 둘러싸인 부분) 내에서만 유효한 스코프
function example() {
if (true) {
let y = 20;
console.log(y);
}
console.log(y); // ReferenceError: y is not defined
}
example();
console.log(y); // ReferenceError: y is not defined
function example() {
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
console.log("반복문 외부에서 i:", i); // ReferenceError: i is not defined
}
example();
var과 let, const의 차이점
var 변수 | let과 const 변수 |
변수 이름 중복선언 가능 | 변수 이름 중복선언 불가 (SyntaxError 발생) |
변수 선언 전에 사용 가능(호이스팅) | 변수 선언 전에 사용 불가 (ReferenceError 발생) |
함수 스코프 | 블록 스코프 |
3. 함수 다루기
함수를 만드는 방법
· 함수를 만드는 방법 두 가지 : 함수 선언 , 함수 표현식
· 함수 선언과 함수 표현식의 가장 큰 차이 : 호이스팅, 스코프
· 보편적으로는 표현식보다는 선언을 우선으로 사용함.
함수 선언 (Function Declaration)
· function 키워드를 통해서 함수를 선언하는 일반적인 방식
· 호이스팅으로 인해서 함수를 선언하기 이전에 함수를 호출해도 정상적으로 동작
· 함수 스코프를 가짐.
funcion 함수이름(파라미터) {
동작
return 리턴값
}
function apple() {
function banana() {
console.log('banana')
}
console.log('apple'); // 실행 O
banana(); // 실행 O
}
apple(); // apple banana
banana(); // ReferenceError: banana is not defined
// 함수 선언은 함수 호이스팅이 가능함.
printCodeit(); // Codeit
function printCodeit() {
console.log('Codeit')
}
함수 표현식 (Function Expression)
· 함수 선언을 변수에 할당하거나 다른 함수의 아규먼트로 활용하면서 마치 함수 선언을 값처럼 활용해서 함수를 만드는 방식
· 반드시 변수가 선언된 이후에 함수를 호출해야 정상적으로 동작
· 변수에 할당하는 경우에는 할당된 변수의 특성에 따라 스코프가 결정 (var: 함수, let이나 const: 블록)
const printCodeit = function () {
console.log('Codeit');
};
const myBtn = document.querySelector)'#myBtn');
myBtn.addEventListener('click', function () {
console.log('button is clicked');
});
// 함수 선언 (함수 스코프)
{
function sayHi() {
console.log('Hi!');
}
}
sayHi(); // Hi!
// 함수 표현식 - let 키워드로 선언 (블록 스코프)
{
let sayHi = function () {
console.log('Hi!');
};
}
sayHi(); // ReferenceError: sayHi is not defined
// 함수 표현식 - var 키워드로 선언 (함수 스코프)
{
var sayHi = function () {
console.log('Hi!');
};
}
sayHi(); // Hi!
이름이 있는 함수 표현식
Named Function Expression (기명 함수 표현식)
· 함수 표현식으로 할당된 함수에 이름을 붙일 수 있음.
· 이름이 없는 함수를 변수에 할당할 때는 변수의 name 프로퍼티는 변수 이름 그 자체를 문자열로 가지게 됨.
하지만 함수에 이름을 붙여주게 되면, name 속성은 함수 이름을 문자열로 가짐.
· 함수에 이름을 명시적으로 지정할 수 있어 디버깅과 코드 가독성 측면에서 유용함.
· 함수 내부에서 자신을 참조 가능, 외부에서는 이름으로 참조 불가능함.
var myFunction = function namedFunction() {
console.log("This is a named function expression.");
};
myFunction(); // 함수 호출
// 함수 이름을 통한 참조
console.log(namedFunction); // undefined
console.log(myFunction); // 함수의 정의가 출력됨
외부에서 변수 myFunction을 통해 함수에 접근 가능, namedFunction으로 접근 불가능
자기 자신을 재귀적으로 호출하는 예시
var factorical = function caculateF(n) {
if (n <= 1) {
return 1;
} else {
// 함수 내부에서 자신을 참조
return n * calculateF(n);
}
};
// 함수 호출
console.log(factorial(5)); // 5! = 120
let countdown = function(n) {
console.log(n);
if (n === 0) {
console.log('End!');
} else {
countdown(n - 1);
}
};
let myFunction = countdown;
countdown = null;
myFunction(5); // TypeError
let countdown = function printCountdown(n) {
console.log(n);
if (n === 0) {
console.log('End!');
} else {
printCountdown(n - 1);
}
};
let myFunction = countdown;
countdown = null;
myFunction(5); // 정상적으로 동작
함수 이름을 사용해서 재귀적으로 호출하는 경우 외부에서 함수를 할당한 변수의 이름을 바꾸더라도 영향을 받지 않음.
함수 이름은 함수를 정의할 때 고정된 값이기 때문에 외부에서 함수를 호출하거나 함수에 대한 참조를 변경해도 영향을 받지 않음.
즉시 실행 함수 (IIFE)
즉시 실행함수 (IIFE, Immediately Invoked Function Expression)
· 함수 선언과 동시에 즉시 실행되는 함수
· 함수 선언부분을 소괄호로 감싸고, 바로 뒤에 실행하는 소괄호 붙이기
· 활용 : 프로그램 초기화 기능, 재사용이 필요없는 일회성 동작
(function (x, y) {
console.log(x + y);
})(3, 5);
즉시 실행 함수는 함수에 이름을 지어주더라도 외부에서 재사용할 수 없다.
내부에서는 재귀적으로 사용할 수 있음.
(function sayHi() {
console.log('Hi!');
})();
sayHi(); // ReferenceError
(function countdown(n) {
console.log(n);
if (n === 0) {
console.log('End!');
} else {
countdown(n - 1);
}
})(5);
/*
5
4
3
2
1
0
End!
*/
값으로서 함수
자바스크립트에서 함수는 변수나 다른 데이터 구조 안에 자유롭게 할당
함수 표현식, 객체의 프로퍼티로 함수 선언해서 메소드 생성, 배열의 요소로 생성 가능함.
객체 내 함수 (Object method)
const myObject = {
brand: 'Codeit',
bornYear: 2017,
isVeryNice: true,
sayHi: function(name) {
console.log(`Hi! ${name}`);
}
};
myObject.sayHi('JavaScript');
// 출력: Hi! JavaScript
객체 myObject 안에 sayHi 메서드를 정의하고, 이를 호출하여 인사 메시지를 출력함.
배열 내 함수 (Function in an array)
const myArray = [
'codeit',
2017,
true,
function(name) {
console.log(`Hi! ${name}`);
}
];
myArray[3]('Codeit');
// 출력: Hi! Codeit
배열 myArray 안에 함수가 있고, 해당 함수를 배열 인덱스를 통해 호출하면서 'Codeit'을 인자로 넘김.
이벤트 리스너에 함수 전달 (Passing a function to an event listener)
const myBtn = document.querySelector('#myBtn');
myBtn.addEventListener('click', function() {
console.log('button is clicked');
});
myBtn 요소를 찾고, 클릭 이벤트가 발생하면 'button is clicked' 메시지를 출력하는 함수를 등록함.
고차 함수 (Higher Order Function)
함수를 반환하거나 매개변수로 함수를 받는 함수
// 함수가 다른 함수를 반환하는 경우에는 반환된 함수를 호출하기 위해 추가적인 괄호가 필요
function getPrintHi() {
return function() {
console.log('Hi!?');
};
}
// 괄호 1개
getPrintHi(); // 아무것도 출력되지 않음
// 괄호 2개
getPrintHi()(); // Hi!?
// 함수를 다른 변수에 할당하여 호출
const greeting = getPrintHi();
console.log(greeting); // [Function (anonymous)]
greeting(); // Hi!?
일급 함수 (First-class Function)
자바스크립트에서 함수는 일급 함수임.
이는 함수를 변수에 할당하거나, 다른 함수의 매개변수로 전달하거나, 함수에서 반환할 수 있다는 것을 의미함.
위의 예시들에서 보여준 것처럼 함수를 값으로 다룰 수 있음.
콜백 함수 (callback function)
다른 함수의 매개변수로 전달되는 함수
// 간단한 배열
const numbers = [1, 2, 3, 4, 5];
// 배열을 순회하면서 각 요소에 대해 콜백 함수를 호출하는 함수
function forEach(arr, callback) {
for (let i = 0; i < arr.length; i++) {
// 각 요소에 대해 콜백 함수 호출
callback(arr[i]);
}
}
// 순회할 때 실행될 콜백 함수
function squareNumber(num) {
console.log(num * num);
}
// forEach 함수를 사용하여 배열을 순회하면서 squareNumber 콜백 함수 호출
forEach(numbers, squareNumber);
Parameter
function greeting(name) {
console.log(`Hi! My name is ${name}!`);
}
greeting('JavaScript');
greeting('Codeit');
greeting('World');
파라미터(Parameter)
외부로부터 값을 전달받기 위해 함수를 선언할 때 작성하는 것, 함수 안에 작성
ex. name은 greeting 함수의 파라미터(parameter)
아규먼트(Argument)
함수를 호출할 때 파라미터로 전달하는 값
ex, 'JavaScript', 'Codeit', 'World' 등
function greeting(name) {
console.log(`Hi! My name is ${name}!`);
}
greeting();
// Hi! My name is undefined!
아규먼트가 파라미터로 전달될 때는 파라미터의 기본값과는 전혀 관계없이 함수를 호출할 때 작성한 순서 그대로 전달됨.
아규먼트 생략할 가능성이 있어서 기본값이 필요한 파라미터는 가급적 오른편에 작성하는 것이 권장됨.
function greeting(name = 'Codeit', interest) {
console.log(`Hi! My name is ${name}!`);
console.log(`I like ${interest}!`);
}
greeting('JavaScript');
// Hi! My name is JavaScript!
// I like undefined!
function greeting(name = 'Codeit', interest = 'JavaScript') {
console.log(`Hi! My name is ${name}!`);
console.log(`I like ${interest}!`);
}
greeting(undefined, 'Python');
// Hi! My name is Codeit!
// I like Python!
function calculate (x, y = x + 2) {
console.log(`x : ${x}`);
console.log(`y : ${y}`);
}
calculate(3) // x : 3, y : 5
calculate(3, 4) // x : 3, y : 4
calculate(undefined, 4) // x : undefined, y : 4
calculate(4, undefined) // x : 4, y : 6 (기본값이 설정돼 있으면 기본값)
calculate(null, 4) // x : null, y : 4
calculate(4, null) // x : 4, y : null (기본값이 설정돼 있어도 null)
Arguments
함수 내에서 사용할 수 있는 특별한 객체
함수에 전달된 모든 인자를 포함함.
이 객체는 유사한 배열의 형태를 가지며, 배열처럼 인덱스로 접근 가능함.
(arguments.length와 arguments[0]과 같이 사용 가능)
이미 예약된 이름이므로, 함수 내부에서 'arguments'라는 변수나 함수를 만들지 않는 것이 좋음.
function printArguments(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
console.log('------');
}
printArguments('apple', 'banana', 'orange'); // apple, banana, orange
printArguments('apple'); // apple, undefined, undefined
printArguments('apple', 'banana'); // apple, banana, undefined
printArguments('apple', 'banana', 'orange', 'peach'); // apple, banana, orange
function exampleFunction() {
// arguments 객체의 길이를 출력
console.log("Arguments Length:", arguments.length);
// arguments 객체를 for of 반복문을 통해 순회하여 각 인자를 출력
for (const arg of arguments) {
console.log("Current Argument:", arg);
}
}
// 함수 호출 시에 다양한 인자를 전달
exampleFunction('첫 번째', '두 번째', '세 번째');
/*
출력 결과:
Arguments Length: 3
Current Argument: 첫 번째
Current Argument: 두 번째
Current Argument: 세 번째
*/
Rest Parameter
arguments 객체의 아쉬운 부분
· arguments 객체가 유사배열이라서 배열의 메소드 사용 불가
· 항상 함수를 호출할 때 전달한 arguments 전체를 다루기 때문에 마지막 2개 혹은 3개만 다루려면 인덱싱을 통해 세분화하는 과정이 필요함
→ ES2015 이후 Rest Parameter 가 등장함.
rest parameter
· 인자들을 배열로 묶어주는 문법으로 가변적인 매개변수를 다를 수 있음.
· 일반 파라미터 앞에 마침표 3개 붙인 것
· rest parameter은 배열이므로, 배열의 메소드를 자유롭게 사용할 수 있음.
function printArguments(...args) {
for (const arg of ars) {
console.log(arg);
}
console.log('-----');
};
printArguments('apple', 'banana', 'orange');
printArguments('apple');
printArguments('apple', 'banana');
printArguments('apple', 'banana', 'orange', 'peach');
function printArguments(...args) {
console.log(args.splice(0, 2));
console.log(arguments.splice(0, 2));
console.log('------------');
};
printArguments('apple', 'banana', 'orange');
printArguments('apple');
printArguments('apple', 'banana');
printArguments('apple', 'banana', 'orange', 'peach');
// arguments.splice is not a function
에러가 발생하는 이유는 'arguments'가 배열이 아닌 배열과 유사한 객체이기 때문임.
'splice' 매서드는 배열 메서드이며, 'arguments' 객체에 직접 사용할 수 없음.
여기서 주의할 점 : (...args)는 실제로 배열을 만드는 것이 아니라 인자들을 배열로 묶어주는 문법이라는 것임.
'arguments'를 배열로 변환하려면 전개 연산자나 'Array.from()' 매서드를 사용할 수 있음.
function printArguments(...args) {
// arguments를 배열로 변환하기 위해 전개 연산자 사용
const argsArray = [...args];
console.log(argsArray.splice(0, 2));
// 또는 arguments를 배열로 변환하기 위해 Array.from() 메서드 사용
const argumentsArray = Array.from(arguments);
console.log(argumentsArray.splice(0, 2));
}
printArguments('apple', 'banana', 'orange');
rest 파라미터와 일반 파라미터를 함께 사용할 수 있음
function ignoreFirst (first, ...args) {
// 출력할 배열 정의
let exceptFirst = [];
// 파라미터에 들어간 원소들을 배열의 원소로 집어 넣음
for (const thing of args) {
exceptFirst.push(thing);
}
console.log(exceptFirst);
}
ignoreFirst('곰팡이', '강아지', '고양이');
일반 파라미터와 함께 사용할 때 rest parameter은 가장 나중에 작성되어야 함.
명확하게 구분되어야 하는 것은 일반 파라미터를 사용, 유연하게 다룰 수 있는 부분은 rest parameter로 나누기
Arrow Function
· 기존의 함수선언 방식을 보다 간결하게 만들어주는 표현식. (ES2015에 등장)
· 이름이 없는 익명함수임.
·이름을 가진 변수에 할당, 다른 함수의 argument로 변수를 선언
·function 키워드를 지우고 '() =>'를 작성
const getTwice = (number) => {
return number * 2;
};
console.log(getTwice(6)); // 12
// 위 코드에서 파라미터의 괄호 생략
const getTwice = number => {
return number * 2;
};
console.log(getTwice(6)); // 12
파라미터가 2개 이상이거나 없을 경우 소괄호 반드시 작성
// 파라미터가 2개 이상이거나 없을 경우 소괄호 반드시 작성
const sum = (a, b) => a + b;
console.log(sum(3, 7)) // 10
const sum = (a, b) => (a + b);
console.log(sum(3, 7)) // 10
리턴값이 객체인 경우
const getName = () => {
return { name: "길동", };
};
console.log(getName()); // { name: '길동' }
const getName = () => { name: "길동", };
console.log(getName());
// SyntaxError: Unexpected token '}'
// 리턴값이 객체인 경우
// 함수의 동작 부분을 구분하는 중괄호로 인식함
const getName = () => { name: "길동", };
console.log(getName());
const getName = () => ({ name: "길동", });
console.log(getName());
화살표를 쓰고 그 다음에 바로 중괄호를 쓰면 함수의 동작 부분을 구분하는 것으로 인식해서 오류가 남.
중괄호 부분을 '소괄호()'로 감싸면 됨.
arrow function에서는 arguments 객체가 없다.
function normalFunc() {
console.log(arguments);
};
const arrowFunc = () => {
console.log(arguments);
};
normalFunc(1, 2, 3); // [Arguments] { '0': 1, '1': 2, '2': 3 }
arrowFunc(1, 2, 3); // error
rest parameter을 사용하여 인자를 받을 수 있음.
const arrowFunc = (...args) => {
console.log(args);
};
arrowFunc(1, 2, 3); // [ 1, 2, 3 ]
this
· 함수를 호출한 객체를 가리키는 키워드임
·코드를 작성할 때 값이 미리 결정 (X)
·함수가 호출될 때 어떤 객체가 함수를 호출했는지에 따라 값이 변함. (O)
브라우저 안에서 자바스크립트가 동작하면 윈도우 객체가 출력됨.
전역객체인 window객체가 this의 기본값임.
this는 일반적으로 사용되지 않고 함수 내부에서 주로 사용됨.
특히 객체 메소드를 만들 때 중요한 역할을 함.
const myObject = {
'name' : '길동',
'age' : 43,
'introduce_myself' : function () {
return `내 이름은 ${this.name}이고, 내 나이는 ${this.age}이다.`;
// this : 현재 메소드를 호출한 객체 = myObject라는 객체임
}
}
console.log(myObject.introduce_myself())
일반함수와 화살표 함수의 차이점은 this를 다루는 방식임.
· 일반함수 : 호출한 대상에 따라 상대적으로 변함
· 화살표함수 : arrow function이 선언되기 직전의 그때 유효한 this값과 똑같이 동작함.
객체 메소드를 만들 때는 화살표함수보다 일반 함수가 권장됨.
this에 메소드를 호출한 객체를 가리키고 싶다면 arrow function 보다는 일반 함수를 활용하면 좋음.
// 일반 함수를 사용하여 객체를 생성하는 예제
function NormalFunction() {
// 객체 생성 시 value 속성을 1로 설정
this.value = 1;
// 1초 후에 실행되는 콜백 함수
setTimeout(function () {
// 여기서의 this는 전역 객체를 가리킴
// 따라서 this.value++는 전역 객체의 value 속성을 증가시키려 함
// 그러나 전역 객체에 value 속성이 없으므로 NaN(Not a Number)이 출력됨
this.value++;
console.log("Normal Function:", this.value);
}, 1000);
}
// 화살표 함수를 사용하여 객체를 생성하는 예제
function ArrowFunction() {
// 객체 생성 시 value 속성을 1로 설정
this.value = 1;
// 1초 후에 실행되는 콜백 함수
setTimeout(() => {
// 여기서의 this는 ArrowFunction 함수 내에서의 this를 따라감
// ArrowFunction 객체를 가리키므로 this.value++는 ArrowFunction 객체의 value 속성을 증가시킴
// 따라서 1에서 시작하여 1초 후에 2가 출력됨
this.value++;
console.log("Arrow Function:", this.value);
}, 1000);
}
// 객체를 생성하여 NormalFunction 함수 실행
const obj = new NormalFunction(); // Normal Function: NaN (전역 객체에 value가 없음)
// 객체를 생성하여 ArrowFunction 함수 실행
const obj2 = new ArrowFunction(); // Arrow Function: 2
'코드잇 Codeit > Front-End' 카테고리의 다른 글
[코드잇] CSS 핵심개념 ① - 기본개념, 자주 쓰는 CSS 속성, 박스모델 (0) | 2023.12.17 |
---|---|
[코드잇] 모던 자바스크립트 ② 자바스크립트 문법과 표현, 내부 기능, 모듈 (0) | 2023.12.17 |
코드잇 웹 퍼블리싱 - ① 웹 퍼블리싱 시작하기 (0) | 2023.05.05 |
코드잇 javaScript 기초 - 프로그래밍과 데이터 in JavaScript ④ 과제로 복습하기 (0) | 2023.05.05 |
코드잇 javaScript 기초 - 프로그래밍과 데이터 in JavaScript ③ 자료형 심화 (0) | 2023.05.04 |