
Functions
▽ 7.1 함수 스타일에 대해서는 별도의 스타일 가이드를 제공하지 않는다.
// type 1
function foo() {
// ...
}
// type 2
const foo = function() {
// ...
};
// type 3
const foo = function bar() {
// ...
};
: Naver에서는 함수 스타일에 대해 차별을 두지 않지만, Airbnb의 경우 type3의 명명된 함수식을 권장합니다.
▽ 7.2 즉시 실행함수는 함수를 괄호로 감싼다.
// bad
!function()) {
console.log("Welcome to the Internet. Please follow me.");
}();
// bad - Airbnb권장
(function() {
console.log("Welcome to the Internet. Please follow me.");
}());
// good - Naver권장
(function() {
console.log("Welcome to the Internet. Please follow me.");
})();
: 즉시 실행함수(IIFE, Immediately Involked Function Expression)은 단 한번 호출되며, 재호출이 불가한 함수입니다.
IIFE를 사용하는 이유는 '전역변수 사용을 억제하기 위해서'입니다.
IIFE를 (괄호)로 감싸는 이유는 함수 객체를 생성하기 위함인데, 구체적인 이유는 다음과 같습니다.
- 보통 IIFE는 익명함수를 쓰는 것이 일반적인데, JavaScript엔진이 함수이름을 생략할 수 없어 에러가 발생됩니다.
- 함수이름을 넣더라도 JavaScript엔진이 암묵적으로 세미콜론(;)을 자동 삽입해 함수선언문이 끝나는 위치에 세미콜론이 추가돼 에러가 발생됩니다.
- 세미콜론이 추가되더라도 세미콜론 다음의 괄호는 함수 호출 연산자가 아닌 그룹 연산자로 해석돼 에러가 발생됩니다.
해당 내용에 대해서는 추후 즉시 실행함수에 대해 따로 정리해보겠습니다.
▽ 7.3 함수 이외의 블록(if, while 등) 안에서 함수를 선언하지 않는다.
// bad
let i;
for (i = 10; i; i--) {
(function() {
return i;
})();
}
// bad
while(i) {
let a = function() {
return i;
};
a();
}
// good
const a = function() {};
let i;
for (i = 10; i; i--) {
a();
}
: browser마다 함수 외의 블록 내에 있는 함수를 모두 다르게 해석하기 때문입니다.
▽ 7.4 Airbnb와 다르게 block 내의 함수선언에 대해서는 별도로 가이드 하지 않는다.
이하 Airbnb 내용
// Naver가 아닌 Airbnb 내용입니다.
// bad
if (currentUser){
function test(){
console.log('Nope');
}
}
// good
let test;
if (currentUser){
test = () => {
console.log('Yup');
}
}
▽ 7.5 절대로 파라미터에 arguments를 지정하지 않는다. 이것은 함수 스코프에 전해지는 arguments 오브젝트의 참조를 덮어버린다.
// bad
function nope(name, options, arguments) {
// ...stuff...
}
// good
function yup(name, options, args) {
// ...stuff...
}
: JavaScript 함수에는 '인수객체(arguments)'라는 '내장객체'가 있습니다. 인수객체에는 함수가 호출될 때 사용된 인수 배열이 포함됩니다. 즉 이미 내장객체에 arguments가 있으니 파라미터로 쓸 수 없다는 뜻입니다.
▽ 7.6 절대 arguments를 이용하지 않는다. 대신에 rest 파라미터(...)를 이용한다.
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join("");
}
// good
function concatenateAll(...args) {
return args.join("");
}
: rest 파라미터는 원하는 값에 대해 명확히 표현할 수 있습니다. 하지만 인수객체(arguments)를 쓴다면 오류 유발 가능성이 커집니다.
▽ 7.7 함수의 파라미터를 재정의하지 않는다. 대신 default 파라미터를 이용한다.
// really bad
function handleThings(opts) {
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
: default parameter(기본 매개변수)는 함수에 전달된 파라미터 값이 'undefined'거나 '값이 없을 때, 초기화 설정된 값'을 의미합니다.
'void'은 관용적으로 사용하는 JavaScript 연산자입니다.
- 'undefined' 원시값을 얻기 위해 void 0 또는 void(0)을 사용합니다.
- void는 오버라이드 되지 않고 void 0은 항상 undefined를 리턴합니다.
- undefined는 예약어가 아니라서 어떤 값이든 될 수 있습니다. (ex. var undefined = 0; // 0)
▽ 7.8 side effect를 유발하는 default 파라미터의 이용을 피한다.
var b = 1;
// bad
function count(a = b++) {
console.log(a);
}
count(); // 1
count(); // 2
count(3); // 3
count(); // 3
▽ 7.9 항상 default 파라미터는 뒤쪽에 둔다.
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
▽ 7.10 절대 새 함수를 작성하기 위해 Function constructor를 이용하지 않는다.
// bad
var add = new Function("a", "b", "return a + b");
// still bad
var subtract = Function("a", "b", "return a - b");
: 이런 방식으로 함수를 만들면 취약성을 여는 eval()과 유사한 문자열처럼 처리됩니다. eval()에 관한 글 보기
▽ 7.11 익명함수는 function과 괄호 사이에 공백이 없다. 기명 함수(named function)는 함수 이름과 괄호 사이에 공백이 없다. async arrow function인 경우 async와 arrow function 사이에 공백이 있다.
// bad
const f = function () {};
const g = function a (){};
const h = async(v,i) => {};
// good
const x = function() {};
const y = function a() {};
const z = async (v,i) => {};
: 이는 코드를 일관성 있게 보이게 하며, 이름을 추가하거나 제거할 때 공백을 추가하거나 제거할 필요가 없어 관리가 편합니다.
Naver에서는 async와 arrow function 사이에 공백도 추가했네요.
▽ 7.12 가급적 mutate parameter는 사용하지 않는다. 하지만, 필요에 의해서는 주의하여 사용한다.
// 권장하지 않음.
function f1(obj){
obj.key = 1;
}
: 함수의 파라미터로 전달된 개체를 변형(mutate)하면, caller의 변수에 side effects가 발생할 수 있기 때문입니다.
▽ 7.13 파라미터를 재할당하지 않는다. 단, 파라미터의 속성에 대해서는 재할당이 가능하다.
// bad
function f1(a) {
a = 1;
// ...
}
// bad
function f2(a) {
if (!a) { a = 1; }
// ...
}
// good
function f3(a) {
const b = a || 1;
// ...
}
// good
function f4(a) {
if (!a) { a.b = 1; }
// ...
}
: Airbnb에서는 f4 함수에서 보이는 파라미터 속성값의 재할당 또한 금하고 있습니다.
▽ 7.14 가변함수를 호출할 때는 spread 연산자(...)를 사용한다.
// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);
// good
const x = [1, 2, 3, 4, 5];
console.log(...x);
// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
// good
new Date(...[2016, 8, 5]);
: spread 연산자를 사용하면, 더 깔끔하고 문맥을 제공하지 않아도 됩니다.
▽ 7.15 함수의 정의가 멀티라인인 경우, 오브젝트와 같은 스타일 가이드를 따른다.
// bad
function foo(bar,
baz,
quux) {
// ...
}
// good
function foo(
bar,
baz,
quux,
) {
// ...
}
// bad
console.log(foo,
bar,
baz);
// good
console.log(
foo,
bar,
baz,
);
예상하다시피 JavaScript Function에 대한 컨벤션은 길고, 사전지식이 많이 필요한 것 같습니다. 위 내용에서 궁금한 점도 많이 생겼으니 추후 자세하게 다뤄볼 주제들도 많네요. 다음 주제는 Arrow Function(화살표 함수)입니다.
naver github STYLE_GUIDE.md
'etc > Conventions' 카테고리의 다른 글
#06. [Naver Conventions 전격해부] Strings (0) | 2023.01.01 |
---|---|
#05. [Naver Conventions 전격해부] Destructuring (1) | 2023.01.01 |
#04. [Naver Conventions 전격해부] Arrays (0) | 2022.12.12 |
#03. [Naver Conventions 전격해부] Objects (0) | 2022.12.11 |
#02. [Naver Conventions 전격해부] References (2) | 2022.12.10 |