# Function 개념
1. 독립적으로 분리된 로직. 프로그램 수준에서 이미 정의된, 혹은 사용자가 정의한 실행 단위.
2. 일급객체(First Class Object)
- 객체를 변수나 데이터구조 안에 담을 수 있다
- 인자 전달 및 반환값으로 전달 가능하다
- 런타임에 생성될 수 있다
3. 함수선언(Function Declaration) VS 함수 표현(Function Expression)
- 함수 선언 Function Declaration ( ≒ Function Statement )
- 실행 가능한 코드블럭이 아닌 함수의 정의
- statement 코드 해석에 따른 수행결과가 없음
- function declarations always need names
- 이렇게 선언된 함수는 언제나 호이스팅 가능함
- 함수 표현 Function Expression ( ≒ Function Literal )
- 실행 가능한 코드블럭 - 변수, 데이터 구조 등에 할당되고 있음을 의미함 (즉시 실행 가능)
- 해석과 동시에 실행
- anonymous function expression
- named function expression ★ 해당 함수의 이름은 함수밖에서 사용할 수 없다
- self invoking function expression
- 실행 가능한 코드블럭 - 변수, 데이터 구조 등에 할당되고 있음을 의미함 (즉시 실행 가능)
★ 해당 함수의 이름은 함수밖에서 사용할 수 없다 named function expression
const foo = function bar() {
bar();
};
bar(); //ReferenceError: bar is not defined
★ 함수 표현식 3가지
//anonymous function expression
const foo = function() { console.log('foo'); }
//named function expression
const foo = function foo() {
console.log('foo');
}
//self invoking function expression(IIFE)
(function foo(){ console.log('foo');})();
# Hoisting 호이스팅
인터프리터가 JavaScript 코드를 해석하는데에 있어서
Global 영역에 선언된 코드 블럭을 최상의 스코프scope 로 끌어올리는 것
Global 영역에 선언된 변수 또는 함수는
자바스크립트 엔진이 가장 우선적으로 해석
(선언문은 항시 최우선 해결, 실행 코드는 뒤로 밀린다)
단, 할당구문은 런타임 중 이루어지므로 호이스팅 되지 않음.
※ 코드 가독성이 떨어지므로 호이스팅을 이용한 코드작성은 비추천
function statement(함수선언문)은 호이스팅 되고, 할당은 호이스팅 되지 않음.
//함수 선언문. 호이스팅 됨.
function foo() {//...Global 객체에 등록됨
}
//함수리터럴, 할당구문. 호이스팅 되지 않음.
const foo = function() {//...
}
Quiz about Hoisting
호이스팅과 관련한 퀴즈는 아래 제시된 출처 블로그에서 가져왔다.
좋은 내용이라 여기에 한번 내 답안을 써보려고 한다.
정확한 내용이 궁금하다면 아래의 출처를 통해 원문을 볼 것!
//Question 1:
function foo(){
function bar() {
console.log('hello');
}
return bar();
function bar() {
console.log('world');
}
}
foo();
//Question 2:
function foo(){
var bar= function() {
console.log('hello');
};
return bar();
var bar = function() {
console.log('world');
};
}
foo();
Question 1 :
global 영역으로 function foo() { ...foo... } 가 함수선언문이므로 함수를 호이스팅한다.
블럭 내부{ ...foo...}도 함께 호이스팅 된다.
...foo... : function bar(){} 은 함수선언문으로, Global 영역에 호이스팅 된다.
//Question 1:
function foo(){
function bar() {
console.log('hello');
}
function bar() {
console.log('world');
}
return bar();
}
foo();
호이스팅 되므로 bar는 함수가 덮어 씌워지며
bar() 호출 시 console.log('world') 코드블럭을 실행하게 된다.
따라서 콘솔창에는 'world' 만 찍힌다.
실행문 return bar(); 은 런타임 중 가장 마지막에 실행된다.
Question 2 :
global 영역으로 function foo() { ...foo... } 가 함수선언문이므로 함수를 호이스팅한다.
블럭 내부{ ...foo...}도 함께 호이스팅 된다.
...foo... : var bar 에는 함수 리터럴을 할당하므로, 할당은 실행문과 함께 런타임 시점에서 이루어진다.
런타임 도중 return을 만나면 반환하므로, 콘솔창에는 'hello' 가 찍힌다.
function foo(){
var bar = undefined;
var bar = undefined;
bar = function() { console.log('hello'); }
return bar;
//bar = function() { console.log('world'); } 실행되지 않음
}
foo();
Function 의 개념에 대한 대부분의 내용은 아래 출처에서 공부하여 정리했다.
출처: http://insanehong.kr/post/javascript-function/
07 Functions
1. 함수식보다는 함수선언을 지향
- 이름이 부여된 함수는 콜스택에서 쉽게 확인
- 호이스팅이 가능
- arrow function에서 손쉽게 사용가능
//bad
const func = function() {...};
//good
function func() {...}
2. 함수 이외의 블록(if, while, ... )에서 함수를 선언하지 않는 편이 좋다.
//bad
if(currentUser){
function test() { console.log('Nope.'); }
}
//good
let test;
if(currentuser){
test = () => { console.log('Yes!'); };
}
나쁜 예 ) if 의 블록내에 새로운 함수를 선언한다.
브라우저에 따라 이 함수를 해석하는 방식이 다르기 때문에 유의해야한다.
좋은 예 ) 재할당 예정인 변수 test 를 선언하여, if문 안에 함수식을 할당한다.
3. 파라미터에 절대 arguments 를 지정하지 말 것
함수 스코프에는 자동적으로 arguments 객체가 주어진다.
이 arguments 객체는 유사배열객체로 스프레드 문법이 나오기 전,
함수의 인수 전체를 얻어오는 유일한 방법이었다.
인수전체를 얻어오기에 필요한 인자의 일부만 받아오는 것이 불가능하였고,
배열형태가 아니므로 불편했다.
→ ...args 와 같이 나머지매개변수(rest syntax, spread) 를 이용하는 것을 권장
→ 몇 개의 인자를 원하는지 explicit하게 얻어내고 Array형태로 받아낸다.
function recommended(name, options, ...args){...}
//args는 주어진 인자에서 앞의 두 인자를 제외한 나머지 인수들의 배열
//typeof(args) 는 object([[Prototype]]): Array(0)
함수에 전달된 인자를 까다로운 방법으로 array형태로 변경했던 기존의 방식과 비교해보자.
//old
function factorsArray(){
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
//new
function factorsArray(...args){
return args.join('');
}
4. 함수에 전달되는 파라미터를 변경하는 것보다 default 파라미터를 적극 이용하는 것이 좋다.
//bad
function handleThings(opt){
opt = opt || {} ;
}
//bad
function handleThings(opt){
if(opt === void 0) {opt = {};}
}
//good
function handleThings(opt = {}){
....
}
5. 부작용이 있을 법한 default 값 설정은 피하기 (ex) 전위 증감, 후위증감 등
//never do this
let i=1;
function count(k=i++){
console.log(k);
}
6. default 값 사용 시, 파라미터 중 가장 마지막에 둔다.
function person(name, age, opt = {} ){
console.log(`${name} ${age}`);
}
7. Function Constructor 사용을 금지한다. eval()과 같은 보안 취약점이 있다.
문자열을 평가시켜 새 함수를 작성하는 것은 매우 위험한 일이다.
const add = new Function('a','b', 'return a+b;');
08 Arrow Functions
1. anonymous function expression 인 경우, arrow function 을 사용하는 것이 낫다.
//bad
const foo = function(){...}
//good
const foo = () => {...}
2. 함수 body 부분이 하나의 식으로 구성된 경우 중괄호 {} 생략 가능 → 암시적 return 을 사용한다.
그 외에는 반드시 중괄호를 사용하고, return 명시해준다.
[1,2,3].map( number => number+1 );
[1,2,3].map( number => {
const addNumber = number + 1;
return addNumber;
});
3. 식은 하나이지만 복수행에 걸쳐있는 경우, 가독성을 위하여 소괄호로 감싸는 것이 좋다.
코드의 시작과 끝을 알기 쉽도록 표기
[1,2,3].map( number => (
`this is askdjflkasjdkfljalksdjfklajsdfkljalsjfdksjadklja` +
`Finally, number is ${number}`
));
4. 함수의 인수가 하나인 경우, 소괄호를 생략하는 게 가능하다.
//bad
[1,2,3,4].map((x)=> x*(x+1));
//good
[1,2,3,4].map(x => x*(x+1));
//good
[{x: 1, y: 2},{ x: 3, y: 3},{x: 2, y:1}].map(({x,y})=> x*y);
'JavaScript > 스타일가이드 정리하기' 카테고리의 다른 글
스타일가이드 복습하기 02(Arrays, Destructuring, Strings) (0) | 2023.08.22 |
---|---|
스타일가이드 복습하기 01 (Types, References, Objects) (0) | 2023.08.22 |