본문 바로가기

개발/JavaScript

[JavaScript] 클린코드 참고자료 - 2 (객체)

객체

Object freeze

 
1차원적인 것만 가능 OPTIONS 같은 경우는 freeze 되지 않는다.
const STATUS = Object.freeze({
  PENDING: "PENDING",
  SUCCESS: "SUCCESS",
  FAIL: "FAIL",
  OPTIONS: {
    GREEN: "GREEN",
    RED: "RED",
  },
});

STATUS.PENDING = "P";
console.log(STATUS.PENDING); // PENDING - 변하지않음

STATUS.NEW_PROP = "PP";
console.log(STATUS); // {"PENDING":"PENDING","SUCCESS":"SUCCESS","FAIL":"FAIL"} - 추가되지 않음

console.log(Object.isFrozen(STATUS.FAIL)); // true

Object.isFrozen(STATUS.OPTIONS); // false
STATUS.OPTIONS.GREEN = "G";
STATUS.OPTIONS.YELLOW = "Y";
console.log(STATUS.OPTIONS); // {"GREEN":"G","RED":"RED","YELLOW":"Y"}

 

직접 접근 지양하기

BAD

const model = {
  isLogin: false,
  isValidToken: false,
};

function login() {
  model.isLogin = true;
  model.isValidToken = true;
}

function validToken() {
  model.isLogin = false;
  model.isValidToken = false;
}

someElement.addEventListener("click", login);

 

GOOD

const model1 = {
  isLogin: false,
  isValidToken: false,
};

//model에 대신 접근
function setLogin(bool) {
  model.isLogin = bool;
  serverAPI.log(model.isLogin);
}

function setValidToken(bool) {
  model.isValidToken = bool;
  serverAPI.log(model.isValidToken);
}

function login() {
  setLogin(true);
  setValidToken(true);
}

function logout() {
  setLogin(false);
  setValidToken(false);
}

 

복잡한 인자 관리하기 

필수적인 매개변수는 에러 처리하기

function createCar({ name, brand, color, type }) {
  if (!name) {
    throw new Error("name is a required");
  }
  if (!brand) {
    throw new Error("brand is a required");
  }
}

createCar({ name: "CAR", type: "SUV" });

 

Default Value 설정하기

function createCarousel(options) {
  options = options || {};
  var margin = options.margin || 0;
  var center = options.center || false;
  var navElement = options.navElement || "div";

  return {
    margin,
    center,
    navElement,
  };
}
createCarousel();

 

Upgrade!

function createCarousel({
  margin = 0,
  center = false,
  navElement = "div",
} = {}) {
  return {
    margin,
    center,
    navElement,
  };

 

more upgrade!

const required = (argName) => {
  throw new Error("required is " + argName);
};

function createCarousel({
  items = required("items"),
  margin = required("margin"),
  center = false,
  navElement = "div",
} = {}) {
  return {
    items,
    margin,
    center,
    navElement,
  };
}
createCarousel();

 

Rest Parameters 나머지 매개변수

나머지 매개변수는 마지막 파라미터로만 사용가능하다.

function sumTotal(initValue, bonusValue, ...args) {
  return args.reduce((acc, curr) => acc + curr, initValue);
}
console.log(sumTotal(100, 99, 1, 2, 3, 4, 5));

Arrow Function 화살표 함수

화살표 함수에서는 메서드 리턴값을 저장할 수 없다.

argument, call, apply, bind도 사용할 수 없다.

 

BAD

const user = {
  name: 'Bob',
  getName: () => {
    return this.name;
  }
}

console.log(user.getName()); // undefined

 

GOOD

const user = {
  name: "Bob",
  getName() {
    return this.name;
  },
};

console.log(user.getName()); // Bob

 

화살표 함수로 만든 함수는 생성자로 사용할 수 없다.

BAD

const Person = (name, city) => {
  this.name = name;
  this.city = city;
};

const person = new Person('Bob', 'korea');
console.log(person); // Uncaught TypeError: Person is not a constructor

 

GOOD

function Person(name, city) {
  this.name = name;
  this.city = city;
}

const person1 = new Person("Bob", "korea");
console.log(person1); // {"name":"Bob","city":"korea"}

 

Callback Function 콜백 함수

 

BAD

function register() {
  const isConfirm = confirm("회원가입에 성공했습니다.");

  if (isConfirm) {
    redirectUserInfoPage();
  }
}

function login() {
  const isConfirm = confirm("로그인에 성공했습니다.");

  if (isConfirm) {
    redirectUserInfoPage();
  }
}

 

GOOD

function confirmModal(message, cbFunc) {
  const isConfirm = confirm(message);
  if (isConfirm && cbFunc) {
    cbFunc();
  }
}

function register() {
  confirmModal("회원가입에 성공했습니다.", redirectUserInfoPage);
}

function login() {
  confirmModal("로그인에 성공했습니다.", redirectUserInfoPage);
}

 

Pure Function 순수 함수

 

BAD

// 함수를 사용할 때 예측이 불가능하다.
let num1 = 10;
let num2 = 20;

function impureSum1() {
  return num1 + num2;
}

function impureSum2(newNum) {
  return num1 + newNum;
}

console.log(impureSum1()); // 30
num1 = 30;
console.log(impureSum1()); // 50
console.log(impureSum2(30)); // 80

 

GOOD

// 예측 가능하다
let num1 = 10;
let num2 = 20;

function pureSum1(num1, num2) {
  return num1 + num2;
}

function pureSum2(newNum) {
  return num1 + newNum;
}

console.log(pureSum1(10, 20)); // 30
console.log(pureSum1(10, 20)); // 30
console.log(pureSum1(30, 100)); // 130
console.log(pureSum1(30, 100)); // 130

 

BAD

 

객체나 배열은 새롭게 만들어서 반환해야 한다 (깊은 복사)

const obj1 = { one: 1 };
function changeObj(targetObj) {
  targetObj.one = 100;
  return targetObj;
}

console.log(changeObj(obj1)); // {"one":100}
console.log(obj1); // {"one":100} - 덮어씌여짐

 

GOOD

const obj2 = { one: 1 };
function changeObj(targetObj) {
  return { ...targetObj, one: 100 };
}

console.log(changeObj(obj2)); // {"one":100}
console.log(obj2); // {"one":1}

 

Closure 클로저

예제 - 1 

function add(num1) {
  return function sum(num2) {
    return num1 + num2;
  };
}

const addOne = add(1);
const addTwo = add(2);

console.log(addOne(3)); // 4
console.log(addTwo(3)); // 5

 

예제 - 2

function log(value) {
  return function (fn) {
    fn(value);
  };
}

const logFoo = log("foo");
logFoo((v) => console.log(v));
logFoo((v) => console.info(v));
logFoo((v) => console.error(v));
logFoo((v) => console.warn(v));

 

클로저 변환 전

const arr = [1, 2, 3, 'A', 'B', 'C'];

function isTypeOf(value, type){
    return (typeof value === type);
}

console.log(isTypeOf(arr[0], 'number'))

 

변환 후 

const arr1 = [1, 2, 3, "A", "B", "C"];

function isTypeOf(type) {
  return function (value) {
    return typeof value === type;
  };
}

const isNumber = isTypeOf("number");
console.log(isNumber(arr1[0])); // true

const isString = isTypeOf("string");
console.log(isNumber(arr1[4])); // false

et cetera

parseInt는 인자가 두개이다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/parseInt

 

parseInt() - JavaScript | MDN

parseInt() 함수는 문자열 인자를 파싱하여 특정 진수(수의 진법 체계에서 기준이 되는 값)의 정수를 반환합니다.

developer.mozilla.org

 

arr.push()에도 반환값이 있다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/push

 

Array.prototype.push() - JavaScript | MDN

push() 메서드는 배열의 끝에 하나 이상의 요소를 추가하고, 배열의 새로운 길이를 반환합니다.

developer.mozilla.org