JavaScript 실행 환경에서 global에 새로운 변수를 등록할 때는 또 다른 제3의 스크립트가 등록한 변수와의 있을지 모를 충돌을 피하려는 노력의 하나로 지극히 제한되게 그 사용을 최소화하도록 권장하고 있다. JavaScript의 기본 문법에는 Module을 구현하는 기능을 갖추고 있지 않아서 (ECMAScript 6th Edition, Harmony에선 Module System이 추가될 전망), 이를 비슷하게나마 구현하기 위한 여러 패턴이 소개됐으며 그 중 가장 널리 쓰이는 패턴이 바로 Rrevealing Module Pattern이다.

아래는 개인적으로 이 패턴에다 IIFE를 더 해서 쓰고 있는 snippet.

;(function(globaldocnameSpaceundefined) {
  'use strict';
 
  var privateVar = 1;
  var privateMethod = function(args) {
 
  };
 
  nameSpace.publicMethod = function(args) {
 
  };
 
  global.nameSpace = nameSpace;
}(this, this.document, this.nameSpace || {}));

JavaScript의 function scope와 closures 덕분에 function 안에 선언된 methods나 variables는 기본적으로 외부에 노출되지 않어서, 그 안의 또 다른 function 이외엔 접근할 수 없도록 차단되어 있는데, 그 중 원하는 것만 꼭 집어서 global에 하나로 공개된 자기만의 namespace가 가지고 있는 property에다 갖다 붙여준다. 이렇게 하면 global 환경에 공개된 기존의 variables와 methods 이름과의 충돌을 최소화할 수 있다.

맨 앞에 희한하게 붙어 있는 세미콜론(;)은 JavaScript 로딩 속도를 최소화하려고 압축해서 다른 스크립트 파일과 하나로 합치는 과정에서, 만약에 다른 스크립트 파일에 있는 마지막 statement 끝에 세미콜론이 빠져있을 경우, 합치는 과정에서 IIFE가 함수 arguments로 오인되는 일을 미리 방지하기 위한 것인데, 이와 관련된 자세한 내용의 글. – IIFE Leading semicolon

남의 밭에서 신발 끈 묶을 땐 항상 조심스럽게.

JavaScript 파일을 웹페이지에 추가하는 방법은 여러 가지가 있는데, 과거엔 주로 head tag에다 추가해 줄 때가 많았으나, 이렇게 하면 브라우저가 JavaScript 파일을 다 읽어 들이는 동안 웹페이지의 렌더링이 잠깐 멈추게 되는 부작용이 있어서, 최근엔 웹페이지를 되도록 빠르게 화면에 뿌려주려고 body tag 마지막에 얹어 주는 것을 권장하고 있다.

그런데 최근 날로 웹 애플리케이션의 개발과 그 활용 방법론이 많이 알려지면서 JavaScript 파일이 점점 더 커지는 경향이 있는데, 무조건 내려받게 되는 이런 JavaScript 파일의 용량을 조금이라도 줄이려는 노력도 따라서 필요해진다. 그래서 페이지에 얹어진 JavaScript 파일 중에 특정 기능이 빈번히 사용되지 않고 특별한 경우에만 쓰이는 것이라면, 이마저도 주요 JavaScript 파일에서 빼어내 특정 조건에 따라 필요할 때만 로딩해주는 기술이 쓰일 수 있다.

jQeury에선 이럴 때에 꼭 안성맞춤인 jQuery.getScript() 함수를 제공하고 있는데, 사용법은 다음과 같다.

$.getScript("ajax/test.js", function(datatextStatusjqxhr) {
   console.log(data); //data returned 
   console.log(textStatus); //success 
   console.log(jqxhr.status); //200 
   console.log('Load was performed.');
});

jQuery를 쓰지 않고 일반 JavaScript로 구현하려면 javascript_loader.js를 참고해서 구현해 볼 수도 있다.
웹페이지 로딩 후, 필요할 때에만 특정 JavaScript 파일을 읽어 들이는 방법(이)란 제목의 글 마저 읽기 →

JavaScript에서 간단하게 다음과 같이 탐지할 수가 있다.

if (document.body.scrollWidth > window.innerWidth) {
  // horizontal scrollbar is visible. 
}

이 시점은 가령 기존 데스크탑 전용 웹페이지를 반응형 디자인으로 구현하고자 할 때, 여러 breakpoints 중 하나의 후보가 될 수 있다. 하지만 미리 마련된 어떤 기준에 따라 나머지 적당한 breakpoints를 자동 탐지해 내는 것은 너무 복잡한 일이다.

결국, 나머진 그냥 눈대중?

전에는 나 자신도 미처 눈치채지 못하고 그냥 버릇처럼 써왔던 것인데, 자주는 아니지만 그래도 간혹, 지금도 html body 끝에 링크된 jQuery 사용 JavaScript 파일이 아래처럼 무조건 jQuery의 ready() 함수로 감싸서 작성된 것을 목격하게 된다.

$(document).ready(function() {
  // Stuff to do as soon as the DOM is ready; 
});

혹은 더 짧게,

$(function() {
 // Handler for .ready() called. 
});

하지만 DOM parsing 작업을 방해하지 않으려고 </body> tag 바로 위에다 스크립트를 추가했다면, 이미 웹 브라우저에선 DOM 해석을 끝낸 시점이기 때문에, 굳이 DOM이 준비되어 있는지 확인하는 작업은 불필요하단 얘기다.

물론 이렇게 한다고 해서 얻을 수 있는 성능상의 이득은 거의 없지만, 불필요한 작업인 것은 분명하다.
추가 참고 문서: You Don’t Need the DOM Ready Event

가령, CSS3 애니메이션 효과를 적용할 때 미지원 브라우저한테는 대신에 JavaScript를 써서 애니메이션 효과를 대체하려고 할 때 유용한 gist로 jQuery plugin 형태로 다음과 같은 것이 있다.

$.support.cssProperty = (function() {
  function cssProperty(prp) {
    var b = document.body || document.documentElement,
    s = b.style;
 
    // No css support detected 
    if(typeof s == 'undefined') { return false; }
 
    // Tests for standard prop 
    if(typeof s[p] == 'string') { return rp ? p : true; }
 
    // Tests for vendor specific prop 
    v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms', 'Icab'],
    p = p.charAt(0).toUpperCase() + p.substr(1);
    for(var i=0; i<v.length; i++) {
      if(typeof s[v[i] + p] == 'string') { return rp ? (v[i] + p) : true; }
    }
  }
 
  return cssProperty;
})();

출처 – Extends the jQuery.support object to CSS Properties

처음부터 무조건 JavaScript를 써서 애니메이션 효과를 주지 않는 이유는, 당연 CSS3 애니메이션 효과를 지원하는 브라우저에선 더 매끄러울 테니까 그렇다.
사용 예: CSS3 Dropdown Menu – CodePen