자바스크립트 코딩의 기술_변수할당

자바스크립트 2021. 5. 22. 13:11

(본 포스팅은 길벗의 '자바스크립트-코딩의 기술' 책을 공부하면서 작성되었습니다_내돈내산)

 

1. const로 변하지 않는 값을 표현하라

  • const의 경우 코드를 읽기 쉽게 만들어 줌.
  • const는 블록의 문맥 내에서 재할당할 수 없는 변수 선언 >> 한번 선언하면 변경할 수 없음. >> 하지만 불변값은 아니며, const에 배열을 할당하는 경우에도 배열의 항목은 바뀔수 있음.
  • 값을 할당하고 변경하지 않을 것이라는 것을 표시해 다음의 개발자에게 코드리딩에 있어 방향을 제시할 수 있음.
    export function getTotal() {
    //  # START:totalConst
      const taxRate = 0.1;
    
      const total = 100 + (100 * taxRate);
    
      // Skip 100 lines of code
    
      return `Your Order is ${total}`;
    //  # END:totalConst
    }
    
    export function getTotalVar() {
    //  # START:totalVar
      var taxRate = 0.1;
    
      var total = 100 + (100 * taxRate);
    
      // Skip 100 lines of code
    
      return `Your Order is ${total}`;
    //  # END:totalVar
    }​
  • 위의 코드를 보았을 때, 첫번째 코드에서는 total 이 상수이며 재할당할 수 없다는것을 알기 때문에 반환되는 값이 어떤것인지 가늠할 수 있음. 하지만 두번째에서는 total의 값이 변경될수 있는 var로 할당되어 있기 때문에 반환되어야 할 값이 어떤것인지 알려면 100줄이상의 코드를 전부 훑어봐야 하는 문제가 발생함.
  • const에 할당된 값이 객체 또는 다른 형태의 컬렉션일때는 const로 선언한 값이 다른 항목을 추가할 수 있음. 어쨋든 될수 있으면 const로 선언한 이후에 후반부에 나타나는 조작(mutation)을 피하는것이 최선임.

2. let과 const로 유효범위 충돌을 줄여라

  • 값이 변경되는 경우 가장 좋은 선택은 let이다.
  • let은 재할당할 수 있다는 점에서 var와 유사하지만, var는 어휘적 유효범위(Lexical scope)를 따르는 반면 let은 블록 유효범위(block scope)를 따름.  >> 블록 유효범위 변수는 if블록이나 for반복문 같은 블록의 내부에만 존재가 가능함. 블록밖에서는 블록 유효 범위 변수에 접근이 불가능하다.
function getLowestPrice(item) {
  var count = item.inventory; // <label id="sale.count1"/>
  var price = item.price;

  if (item.salePrice) {
    var count = item.saleInventory; // <label id="sale.count2"/>
    if (count > 0) {
      price = item.salePrice;
    }
  }

  if (count) { // <label id="sale.if2"/>
    return price;
  }

  return 0;
}
  • 위의 코드에서는 count가 if문의 바깥과 안쪽에서 두번 생성됨. 만일 item.saleInventory 값이 0이 되게 되면 두번째 if 문에서 count값이 false로 처리 되어 정상가격인 item.price를 반환하지 못하게 되고 0을 반환하는 문제가 발생함.
  • 이러한 문제의 경우 변수의 재할당을 막는 let을 이용해 해결할 수 있음.
function getLowestPrice(item) {
  let count = item.inventory;
  let price = item.price;

  if (item.salePrice) {
    let count = item.saleInventory;
    if (count > 0) {
      price = item.salePrice;
    }
  }

  if (count) {
    return price;
  }

  return 0;
}
  • if문 바깥에서 let을 통해 count 변수를 선언 및 할당하게 되고 if문에서 재할당하는 과정을 거치게됨. let의 경우 블록단위에 유효변수선언이 가능하므로 if문 바깥에서 선언한 let과 if문 안쪽에서 선언한 let은 다른 count값을 가질 수 있게 되고 item.saleInventory값이 0이 되더라도, 그것은 if문 내부에서만 가지는 값이므로 두번째 if문에는 영향을 주지않고 정상가격인 item.price를 반환하게 됨.
  • 최종적으로 const를 사용해 더 간결하게 코드를 나타낼 수 있음.
function getLowestPrice(item) {
  const count = item.inventory;
  let price = item.price;

  if (item.salePrice) {
    const saleCount = item.saleInventory;
    if (saleCount > 0) {
      price = item.salePrice;
    }
  }

  if (count) {
    return price;
  }

  return 0;
}

3. 블록 유효범위 변수로 정보를 격리하라

  • 블록 유효범위 변수 선언을 이용하면 변수는 블록 내에서만 접근할 수 있음. 그렇지만 반대로 함수 외부에 선언한 변수는 블록 내부에서 접근이 가능함. 함수의 최상위에서 블록 유효 범위 변수를 선언한 경우는 함수 내부의 if문이나 for문에서 접근이 가능함.
  • 반면에 어휘적 유효 범위(Lexical Scope)를 따를 변수는 함수 내부 어디서든 접근이 가능함.
  • let이 아닌 var를 사용했을때 유효범위에 따라 발생할 수 있는 문제를 나타내는 코드를 보자.
function addClick(items) {
  for (var i = 0; i < items.length; i++) {
    items[i].onClick = function () { return i; }; // <label id="scope.set"/>
  }
  return items;
}
const example = [{}, {}];
const clickSet = addClick(example);
clickSet[0].onClick();
  • 위의 코드를 보았을 때, 간단히 생각해보면 item[1]에 대해서는 1을 반환하고, item[2]에 대해서는 2를 반환한다고 생각해볼 수 있다. 하지만 자바스크립트의 경우 var는 함수 유효범위를 따르기 때문에 함수 내에서 마지막으로 할당한 값을 참조하게 됨.
  • 그러므로 코드를 호출한 시점의 i 값을 반환하게되고, addClick()에 의해 함수가 실행되어 items를 반환한 상태의 i값을 반환한다는 것.! 
  • 이러한 방법을 해결하기 위해 클로저나 고차함수, 즉시실행함수 등을 조합하는 방법이 있을 수 있지만. var대신에 let을 사용해 유효범위를 제한해줌으로써 해결이 가능함.
function addClick(items) {
  for (let i = 0; i < items.length; i++) { // <label id="scope.let"/>
    items[i].onClick = function () { return i; };
  }
  return items;
}
const example = [{}, {}];
const clickSet = addClick(example);
clickSet[0].onClick();
  • let은 블록 유효범위를 따르므로, 블록 내에서 선언한 변수는 해당 블록에서만 유효하게 된다..
  • 따라서 반복되어 값이 변경되더라도, 이전에 선언한 함수의 값은 변경되지 않게 된다. 쉽게 말해 let을 사용하게 되면 for문이 반복될 때마다 값을 잠그게 된다.

4. 템플릿 리터럴(template literal)로 변수를 읽을 수 있는 문자열로 변환하라

  • 자바스크립트에서 문자열을 연결하는 것은 특히 어렵다. 변수에 할당한 문자열과 따옴표로 감싼 문자열을 연결하는 경우는 더욱 그렇다.
  • 일반 적인 URL 생성과정을 코드로 나타내보면 다음과 같다(템플릿리터럴을 사용하지 않고)
function getProvider() {
  // stub for get provider
  return 'pragprog.com/cloud';
}

// START:func
function generateLink(image, width) {
  const widthInt = parseInt(width, 10);
  return 'https://' + getProvider() + '/' + image + '?width=' + widthInt;
}
  • 위와같이 + 기호를 이용해 문자열을 연결해 줄 수 있다. 하지만 URL 에 더 많은 요소들이 포함되고 길어진다고 했을때 어려움이 더해질것이다. 이를 위해 템플릿 리터럴을 사용해서 문자열을 연결하고 새로운문자열을 생성가능하다.
  • 템플릿 리터럴은 따옴표 또는 쌍따옴포 대신 백틱(back-tick)(`) d을 사용한다. 
  • 템플릿 리터럴은 변수에 할당한 문자열처럼 단순 문자열이 아니라면 ${stuff}처럼 $기호와 중괄호로 변수나 다른 자바스크립트 코드를 감싸야 한다.
  • 템플릿 리터럴은 문자열과 변수를 연결할 때 가장 자주 사용하게 될 것이다.
//< 실행 예시 >

function greet(name) {
  return `Hi, ${name}`;
}
greet('Leo');
'Hi, Leo';
// END:greet

// START:yell
function yell(name) {
  return `HI, ${name.toUpperCase()}!`;
}
greet('Pankaj');
'HI, PANKAJ!';

 

admin