javascript 문법 - 함수
함수
// 함수(Function)
// 함수 선언문(Declaration)
// function hello() {}
// 함수 표현식(Expression)
// const hello = function () {}
// 호이스팅(Hoisting), 유효범위 안에서 함수 선언부가 가장 위에 있도록 javascript가 동작되는 것, 함수 선언에서만 발생하고 함수 표현에서는 발생하지 않는다.
hello();
// function hello() {
// console.log('Hello!');
// }
const hello = function () {
console.log('Hello!');
}
main.js:10 Uncaught ReferenceError: Cannot access 'hello' before initialization
at Object.adjPd (main.js:10:1)
at newRequire (index.63aff760.js:71:24)
at index.63aff760.js:122:5
at index.63aff760.js:145:3
할당 연산자를 통해서 함수를 할당하게되면 기명함수라도 호이스팅되지 않아서 에러가 발생한다.
const world = function hello() {
console.log('Hello!');
}
world();
// 반환 및 종료
function hello() {
// 기본 값 undefined, return 이후 코드는 동작하지 않음,
// return 키워드가 없어도 undefined
}
console.log(hello()); // hello만 넣으면 함수 통째, hello() 넣으면 함수의 return값이 나온다
function plus(num) {
if (typeof num !== 'number') {
console.log('숫자를 입력해주세요!');
return 0;
}
return num + 1;
}
return을 적절히 사용해서 함수를 잘 종료하자
// 매개변수 패던(Parameter pattern)
//// 기본값(Default value)
function sum(a, b = 1) {
return a + b;
}
console.log(sum(1, 2));
console.log(sum(7));
매개변수에 기본값을 할당해서 매개변수에 값이 안들어왔을 때, 기본값을 넣어주게 할 수 있다.
//// 구조 분해 할당(Destructuring assignment)
// 객체 구조 분해 할당
const user = {
name: 'HEROPY',
age: 85,
email: 'theseco@gmail.com',
}
function getName({ name }) {
return name;
}
function getEmail({ email = '이메일이 없습니다.' }) {
return email;
}
console.log(getName(user));
console.log(getEmail(user));
// 배열 구조 분해 할당
const fruits = ['Apple', 'Banana', 'Cherry'];
const numbers = [1, 2, 3, 4, 5, 6, 7];
function getSecondItem([, b]) {
return b;
}
console.log(getSecondItem(fruits));
console.log(getSecondItem(numbers));
//// 나머지 매개변수(Rest parameter)
function sum(...rest) {
console.log(rest);
console.log(arguments); // arguments는 array-like 유사배열, 언제든지 함수 내에서 사용할 수 있다. 유사배열이라서 argumets는 reduce 메소드를 쓸 수 없다.
return rest.reduce(function (acc, cur) {
return acc + cur;
}, 0);
}
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // 55
// 화살표 함수(Arrow function)
// function sum() {};
// const sum = function () {};
// const sum = () => {};
// function sum(a, b) {
// return a + b;
// }
const sum = (a, b) => a + b;
console.log(sum(1, 2)); // 3
console.log(sum(10, 20)); // 30
const a = () => {};
// 화살표 함수의 기본 구조, 항상 어떤 변수에다가 할당해서 만들어야 한다.
const b = x => {};
// 매개변수가 1개일 때는 소괄호를 생략할 수 있다.
const c = (x, y) => {};
// 매개변수가 2개 이상일 때는 소괄호를 생략할 수 없다.
const d = x => { return x * x };
const e = x => x * x;
// return 키워드가 맨 앞에 오는 경우에는 중괄호와 return 키워드를 생략할 수 있디ㅏ.
const f = x => {
console.log(x * x);
return x * x;
}
// 특정한 로직이 나오게 되면 중괄호를 생략할 수 없다.
const g = () => { return { a: 1 }};
// 반환하는 데이터가 객체 데이터라면 중괄호와 return 키워드를 넣어서 사용해야한다.
const h = () => ({ a: 1 });
// 아니면 소괄호로 객체를 묶어주면 생략할 수 있다.
const i = () => { return [1, 2, 3]};
const j = () => [1, 2, 3];
// 배열데이터는 괄호 모양이 다르기 때문에 중괄호를 생략할 수 있다.
화살표 함수를 사용하게되면 this 키워드가 다르게 해석된다.
이후에 내용이 있을 예정
// 즉시실행함수(IIFE, Immediately-Invoked Function Expression)
const a = 7;
const double = () => {
console.log(a * 2);
}
double();
(() => {
console.log(a * 2);
})();
// 화살표 함수 경우
(() => {console.log(a * 2);})(); // (F)(), 화살표 함수는 이렇게만 사용할 수 있다.
// 일반함수 경우
(function () {console.log(a * 2);})(); // (F)()
(function () {console.log(a * 2);}()); // (F())
!function () {console.log(a * 2);}(); // !F()
+function () {console.log(a * 2);}(); // +F()
((a, b) => {
console.log(a);
console.log(b);
})(1, 2);
((a, b) => {
console.log(a.innerWidth);
console.log(b.body);
})(window, document);
// 콜백(Callback)
const a = callback => {
callback();
console.log('A');
}
const b = () => {
console.log('B');
}
a(b);
const sum = (a, b, c) => {
setTimeout(c(a + b), 1000);
};
sum(1, 2, value => {
console.log(value);
});
sum(3, 7, value => {
console.log(value);
});
// https://www.gstatic.com/webp/gallery/4.jpg
// const loadImage = (url, cb) => {
// const imgEl = document.createElement('img');
// imgEl.src = url;
// imgEl.addEventListener('load', () => {
// setTimeout(() => {
// cb(imgEl);
// }, 1000);
// });
// }
// const containerEl = document.querySelector('.container');
// loadImage('https://www.gstatic.com/webp/gallery/4.jpg', imgEl => {
// containerEl.innerHTML = '';
// containerEl.append(imgEl);
// });
const containerEl = document.querySelector('.container');
const loadImage = (url, cb) => {
const imgEl = document.createElement('img');
imgEl.src = url;
setTimeout(() => {
cb(imgEl);
}, 1000);
};
loadImage('https://www.gstatic.com/webp/gallery/4.jpg', (imgEl) => {
containerEl.innerHTML = '';
containerEl.append(imgEl);
});
// 재귀(Recursive)
let i = 0;
const a = () => {
console.log('A');
i += 1;
if(i < 4){
a();
};
};
a();
const userA = { name: 'A', parent: null, };
const userB = { name: 'B', parent: userA, };
const userC = { name: 'C', parent: userB, };
const userD = { name: 'D', parent: userC, };
const getRootUser = user => {
if (user.parent) {
return getRootUser(user.parent);
}
return user;
};
console.log(getRootUser(userD));
console.log(getRootUser(userC));
console.log(getRootUser(userB));
console.log(getRootUser(userA));
// 호출 스케줄링(Scaheduling a function call)
const hello = () => {
console.log('Hello~');
};
const timeout = setInterval(hello, 2000);
const h1El = document.querySelector('h1');
h1El.addEventListener('click', () => {
console.log('Clear!');
clearInterval(timeout);
});
setTimeout(함수, 시간ms);
clearTimeout(함수);
지정 시간 후 함수 실행
setInterval(함수, 시간ms);
clearInterval(함수);
지정 시간 마다 함수 실행
// this
//// 일반 함수의 this는 호출 위치에서 정의
//// 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의
const user = {
firstName: 'Heropy',
lastName: 'Park',
age: 85,
// getFullName: function () {
// return `${this.firstName} ${this.lastName}`;
// },
getFullName: () => {
return `${this.firstName} ${this.lastName}`;
}
};
console.log(user.getFullName());
undefined undefined
function user() {
this.firstName = 'Neo';
this.lastName = 'Anderson';
return {
firstName: 'Heropy',
lastName: 'Park',
age: 85,
getFullName: () => {
return `${this.firstName} ${this.lastName}`;
},
};
};
const u = user();
console.log(u.getFullName());
Neo Anderson
function user() {
this.firstName = 'Neo';
this.lastName = 'Anderson';
return {
firstName: 'Heropy',
lastName: 'Park',
age: 85,
getFullName: function () {
return `${this.firstName} ${this.lastName}`;
},
};
};
const u = user();
console.log(u.getFullName());
Heropy Park
화살표함수에서 this는 화살표 함수를 감싸고 있는 함수의 값을 참조하고,
일반함수에서 this는 해당 함수의 값을 참조한다.
일반함수로 만들면 call이라는 메소드를 이용해서 다른데서 getFullName()메소드를 사용할 수 있다.
function user() {
this.firstName = 'Neo';
this.lastName = 'Anderson';
return {
firstName: 'Heropy',
lastName: 'Park',
age: 85,
getFullName() {
return `${this.firstName} ${this.lastName}`;
},
};
};
const lewis = {
firstName: 'Lewis',
lastName: 'Yang',
};
const u = user();
console.log(u.getFullName());
console.log(u.getFullName.call(lewis));
setTimeout(함수) 메소드 처럼 매개함수를 선언할 때
매개함수는 setTimeout 안에 선언되기 때문에
여기서 this를 쓰면 setTimeout함수 안에 있는 title을 찾게 되어서
this.title이 정상적으로 출력되지 않는다.
그렇기 떄문에 함수 안에 함수를 쓸때는 화살표 함수로 선언해서
this가 잘 동작할 수 있도록 하자
const timer = {
title: 'TIMER!',
timeout() {
console.log(this.title);
setTimeout(function () {
console.log(this.title);
}, 1000);
}
};
timer.timeout();