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를 (괄호)로 감싸는 이유함수 객체를 생성하기 위함인데, 구체적인 이유는 다음과 같습니다.

  1. 보통 IIFE는 익명함수를 쓰는 것이 일반적인데, JavaScript엔진이 함수이름을 생략할 수 없어 에러가 발생됩니다.
  2. 함수이름을 넣더라도 JavaScript엔진이 암묵적으로 세미콜론(;)을 자동 삽입해 함수선언문이 끝나는 위치에 세미콜론이 추가돼 에러가 발생됩니다.
  3. 세미콜론이 추가되더라도 세미콜론 다음의 괄호는 함수 호출 연산자가 아닌 그룹 연산자로 해석돼 에러가 발생됩니다.

해당 내용에 대해서는 추후 즉시 실행함수에 대해 따로 정리해보겠습니다.

 

 

▽ 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

 

+ Recent posts