User Tools

Site Tools


javascript_스타일_가이드

목차

  1. Types
  2. Variables
  3. Semicolons
  4. Blocks
  5. Properties
  6. Hoisting
  7. 반복문
  8. 제어문
  9. Conditional Expressions & Equality
  10. Comments
  11. Whitespace
  12. Type Casting & Coercion
  13. Naming Conventions
  14. Accessors
  15. Constructors
  16. Events
  17. Modules
  18. jQuery
  19. Debug

1. Types


* Primitives: primitive type은 그 값을 직접 조작합니다.

  • string
  • number
  • boolean
  • null
  • undefined

* 여러개의 변수를 선언할 때는 ,를 변수 뒤에 입력합니다. 마지막 변수는 ,를 생략합니다.

* 문자열은 작은 따옴표' '를 사용합니다.

* 긴 문자열은 '문자열 연결' or 'Array#join'을 사용합니다. 문자열 연결을 많이 하면 성능에도 영향을 줄 수 있다.

var foo = 'eyeqmc', // string
    num = 1, // number
    boo = true, // boolean
    nul = null, // null
    undef; // undefined
 
var longString = 'This is a super long error that ' +
    'was thrown because of Batman.' +
    'When you stop to think about ' +
    'how Batman had anything to do ' +
    'with this, you would get nowhere ' +
    'fast.';
 
var messages,
    length,
    items,
    i;
 
messages = [{
    state: 'success',
    message: 'This one worked.'
},{
    state: 'success',
    message: 'This one worked as well.'
},{
    state: 'error',
    message: 'This one did not work.'
}];
 
length = messages.length;
 
function inbox(messages) {
    items = [];
 
    for (i = 0; i < length; i++) {
        items.push(messages[i].message);
    }
 
    return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
}

* Complex: 참조형(Complex)은 참조를 통해 값을 조작합니다.

  • object
  • array
  • function

* Object 선언 시 리터럴 구문을 사용합니다.

* Object 선언 시 키값으로 예약어를 입력하면 안됩니다. 예약어 대신 알기 쉬운 동의어를 사용하여야 합니다.

* JSON 방식은 JavaScript의 객체를 표기하는 방법으로 {Key : Value} 형태의 값을 가진다.

// Object 선언
var item = {}; 
 
var superman = {
    type: 'alien'
};

* 배열 선언 시 리터럴 구문을 사용합니다.

* 길이를 알 수 없는 경우는 Array#push를 사용합니다.

* 배열을 복사 할 필요가있는 경우 Array#slice를 사용합니다.

// 배열 선언
var items = []; 
 
var items.push('abracadabra');
 
var itemsCopy = [];
 
itemsCopy = items.slice();

* Array와 비슷한(Array-Like)한 Object를 Array에 변환하는 경우는 Array#slice를 사용합니다.

function trigger() {
    var args = Array.prototype.slice.call(arguments);
    ...
}

* 함수식(Function expressions)

* 선언적 함수의 경우에는 script 태그를 실행하기 전에 가장 먼저 읽혀지지만, 익명 함수의 경우는 한 줄, 한 줄 실행 됩니다. TOGA에서는 명명된 함수식을 사용합니다.

// 익명함수식(anonymous function expression)
var anonymous = function() {
    return true;
};
 
// 명명된 함수식(named function expression)
var named = function named() {
    return true;
};
 
// 즉시실행 함수식(immediately-invoked function expression (IIFE))
(function() {
    console.log('Welcome to the Internet. Please follow me.');
})();

* (if 및 while 등) 블록 내에서 변수에 함수를 할당하는 대신 함수를 선언하지 마십시오. 브라우저는 허용하지만 모두 다른 방식으로 해석됩니다.

* 매개 변수(parameter)에 arguments를 절대 지정하지 마십시오. 이것은 함수 범위로 전달 될arguments객체의 참조를 덮어 쓸 것입니다.

var test;
if (currentUser) {
    test = function test() {
      console.log('Yup.');
    };
}
 
function yup(name, options, args) {
    // ...stuff...
}

* function의 private과 public

  1. this는 전역 객체를 참조합니다.
  2. 메소드 내부의 this는 해당 메소드를 호출한 부모 객체를 참조합니다.
  3. 생성자 함수 코드 내부의 this는 새로 생성된 객체를 참조합니다.
  4. call()과 apply()메소드로 함수를 호출할 때, 함수의 this는 첫 번째 인자로 넘겨받은 객체를 참조합니다.
  5. 프로토타입 객체 메소드내부의 this도 해당 메소드를 호출한 부모 객체를 참조한다.
  6. JavaScript의 this 키워드는 접근제어자 public역할을 한다.
// Constructor
function Func(name) {
 
    // private
    var str = "private";
 
    // public
    this.name = name;
    this.getName = function() {
        return this.name;
    }    
}

* function안의 function (Closure)

* 클로저는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.

var sequencer = function() {
    var s = 0;
    return function() {
        return ++s;
    }
};
/*
seq 함수는 이런 구조를 가지고 반환될 것입니다
function seq() {
    return ++s;
}
*/
var seq = sequencer();
seq(); // 1
seq(); // 2

* function의 prototype

* prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다.

function Point(x,y){
    this.x = x;
    this.y = y;
}
 
Point.prototype.add = function(){
    return this.x + this.y;
}   
 
point1 = new Point(5,5);
 
console.log(point1.add());  // 10

2. Variables


* 변수를 선언 할 때는 항상 var를 사용하십시오. 그렇지 않으면 전역 변수로 선언됩니다. 전역 네임 스페이스를 오염시키지 않도록 Captain Planet도 경고하고 있습니다.

var superPower = new SuperPower();

* 여러 변수를 선언하려면 하나의 var를 사용하여 변수마다 줄바꿈하여 선언하십시오. 선두의 콤마는 하지 않습니다.

* 말미의 불필요한 쉼표도 하지 마십시오. 이것은 IE6/7과 quirksmode의 IE9에서 문제를 일으킬 수 있습니다. 또한 ES3의 일부 구현에서 불필요한 쉼표가 있는 경우, 배열 길이를 추가합니다. 이것은 ES5에서 분명해졌습니다.

var items = getItems(),
    goSportsTeam = true,
    dragonball = 'z';

* 정의되지 않은 변수를 마지막으로 선언하십시오. 이것은 나중에 이미 할당된 변수 중 하나를 지정해야하는 경우에 유용합니다. 길이가 긴 변수 순서대로 선언하십시오.

var items = getItems(),
    goSportsTeam = true,
    dragonball,
    length,
    i;

* 변수의 할당은 스코프의 시작 부분에서 해주십시오. 이것은 변수 선언과 Hoisting 관련 문제를 해결합니다. 경우에 따라 변수의 할당을 시작부분이 아닌 다른 곳에서 하는 경우도 있습니다.

function() {
  var name = getName();
 
  test();
  console.log('doing stuff..');
 
  //..other stuff..
 
  if (name === 'test') {
    return false;
  }
 
  return name;
}
 
function() {
  if (!arguments.length) {
    return false;
  }
 
  var name = getName();
 
  return true;
}

3. Semicolons


* ;를 붙이지 않으면 어려운 debug문제가 미묘하게 발생할 수 있습니다. 항상 ;를 붙여줘야 합니다.

* function앞에 ;이 붙는 이유는 build를 돌릴 때 혹시 ;을 안붙였을 때를 대비하기 위함입니다.

(function() {
  var name = 'Skywalker';
  return name;
})();
 
;(function() {
  var name = 'Skywalker';
  return name;
})();

4. Blocks


* 복수행 블록은 중괄호 ({})를 사용하십시오.

if (test) {
  return false;
}
 
function() {
  return false;
}

5. Properties


* 속성에 액세스하려면 도트.를 사용하십시오.

var luke = {
    jedi: true,
    age: 28
};
 
var isJedi = luke.jedi;

* 변수를 사용하여 속성에 접근하려면 대괄호[]을 사용하십시오.

var luke = {
    jedi: true,
    age: 28
};
 
function getProp(prop) {
    return luke[prop];
}
 
var isJedi = getProp('jedi');

6. Hoisting


* 해당 스코프의 시작 부분에 Hoist된 변수선언은 할당되지 않습니다.

// (notDefined가 전역 변수에 존재하지 않는다고 가정했을 경우)
// 이것은 동작하지 않습니다.
function example() {
    console.log(notDefined); // => throws a ReferenceError
}
 
// 그 변수를 참조하는 코드 후에 그 변수를 선언 한 경우
// 변수가 Hoist된 상태에서 작동합니다.
// Note : `true`라는 값 자체는 Hoist되지 않습니다.
function example() {
    console.log(declaredButNotAssigned); // => undefined
    var declaredButNotAssigned = true;
}
 
// 인터 프린터는 변수 선언을 스코프의 시작 부분에 Hoist합니다.
// 위의 예는 다음과 같이 다시 작성할 수 있습니다.
function example() {
    var declaredButNotAssigned;
    console.log(declaredButNotAssigned); // => undefined
    declaredButNotAssigned = true;
}

* 익명 함수의 경우 함수가 할당되기 전에 변수가 Hoist될 수 있습니다. (익명함수를 쓰는 것은 좋은 코드가 아니다.)

function example() {
    console.log(anonymous); // => undefined
 
    anonymous(); // => TypeError anonymous is not a function
 
    var anonymous = function() {
        console.log('anonymous function expression');
    };
}

* 명명 된 함수의 경우도 마찬가지로 변수가 Hoist될 수 있습니다. 함수 이름과 함수 본체는 Hoist되지 않습니다.

function example() {
    console.log(named); // => undefined
 
    named(); // => TypeError named is not a function
 
    superPower(); // => ReferenceError superPower is not defined
 
    var named = function superPower() {
        console.log('Flying');
    };
}
 
// 함수이름과 변수이름이 같은 경우에도 같은 일이 일어납니다.
function example() {
    console.log(named); // => undefined
 
    named(); // => TypeError named is not a function
 
    var named = function named() {
        console.log('named');
    }
}

* 함수 선언은 함수이름과 함수본문이 Hoist됩니다.

function example() {
    superPower(); // => Flying
 
    function superPower() {
        console.log('Flying');
    }
}

7. 반복문


* for문

var array = ['포도', '사과', '바나나'];
 
for(var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

* for in문

* java의 foreach문과 비슷합니다. 배열이 아닌 객체를 순회할 때만 사용해야 합니다.

* 배열 객체에 사용자가 정의한 기능이 추가되었다면 논리적인 오류가 발생할 수 있습니다. 또한 프로퍼티를 열거하는 순서가 정해져있지 않습니다.

var obj = {
    apple : 300,
    banana : 200,
    melon : 500
};
 
for(var i in obj) {
    console.log(obj[i]);
}

* while문

value = 0;
while (value < 5) {
    console.log(value + '번째 반복');
    value++;
}

* do while문

var value = 0;
do {
    console.log(value + '번째 반복문');
    value++;
} while(value < 5);

8. 제어문


* TOGA에서 삼항연산자( ? : )는 추천하지 않는다.

* if 문

var date = new Date();
var hour = date.getHours();
 
if (hour < 11) {
    console.log('아침');
} else if (hour < 15) {
    console.log('점심');
} else {
    console.log('저녁');
}

* switch문

var input = Number(prompt('숫자를 입력하세요.'));
 
switch (input % 2) {
    case 0:
        console.log("짝수입니다.");
        break;
    case 1:
        console.log("홀수입니다.");
        break;
    default:
        console.log("숫자가 아닙니다.");
        break;
}

* try catch문

try {
    /*
    이 블록이 실행되는 동안 오류에 대하여 테스트되도록 정의 할 수 있습니다.
    */
} catch (err) {
    /*
    try 블록에서 오류가 발생하면, 실행될 코드 블록을 정의 할 수 있게 해줍니다.
    */
}

9. Conditional Expressions & Equality


* == 나 != 보다는 === 와 !== 를 사용해 주십시오

* 조건식은ToBoolean 메소드에 의해 엄밀하게 비교됩니다. 항상 이 간단한 규칙에 따라 주십시오.

  • Objectstrue 로 평가됩니다.
  • undefinedfalse 로 평가됩니다.
  • nullfalse 로 평가됩니다.
  • Booleansboolean형의 값 으로 평가됩니다.
  • Numberstrue 로 평가됩니다. 하지만 +0, -0, or NaN 의 경우는 false 입니다.
  • Stringstrue 로 평가됩니다. 하지만 빈문자 ' ' 의 경우는 false 입니다.
var arr = [0, 1, 2, 3];
if (arr[0]) {
    // false
    // 0은 false입니다.
}
 
if(arr[1]) {
    // true
    // Array는 Object 이므로 true 로 평가됩니다.
}

* 짧은형식을 사용하십시오.

var name = '';
if (name) {
    // false
}
 
var name = 'eyeq';
if(name) {
    // true
}
 
// collection이 비어있지 않다면 비교를 하지 않아도 값이 true가 됩니다.
if (collection.length) {
    // ...stuff...
}

10. Comments


* 복수행의 코멘트는 /* * … */ 를 사용해 주십시오. 그 안에는 설명과 모든 매개 변수와 반환 값에 대한 형식과 값을 설명합니다.

/**
 * make() returns a new element
 * based on the passed in tag name
 *
 * @param <String> tag
 * @return <Element> element
 */
function make(tag) {
 
    // ...stuff...
 
    return element;
}

* 한 줄 주석에는 / /를 사용하십시오. 코멘트를 추가하고 싶은 코드의 상단에 작성하십시오. 또한 주석 앞에 빈 줄을 넣어주십시오.

// is current tab
var active = true;
 
function getType() {
    console.log('fetching type...');
 
    // set the default type to 'no type'
    var type = this._type || 'no type';
 
    return type;
}

11. Whitespace


* 탭에는 공백 4개를 설정하십시오.

function() {
∙∙∙∙var name;
}

* 중괄호({})의 앞에 공백을 하나 넣어주십시오.

function test() {
    console.log('test');
}
 
dog.set('attr', {
    age: '1 year',
    breed: 'Bernese Mountain Dog'
});

* 파일의 마지막에는 빈 줄을 하나 넣어주십시오.

(function(global) {
  // ...stuff...
})(this);
 

12. Type Casting & Coercion


* 문장의 시작 부분에서 강제 형 변환을 수행합니다.

* Strings:

//  => this.reviewScore = 9;
 
var totalScore = String(this.reviewScore);
 
var totalScore = this.reviewScore + ' total score';

* 숫자는 parseInt를 사용하십시오. 항상 형변환을 위한 기수(radix)를 인수로 전달하십시오.

var inputValue = '4';
 
var val = Number(inputValue);
 
/*
parseInt(문자열, 진수);
진수는 선택 사항입니다. 
문자열에서 숫자의 기수를 지정하는 2에서 36까지의 값입니다. 
이 인수를 제공하지 않으면 '0x'로 시작되는 문자열은 16진수로 간주됩니다. 
다른 모든 문자열은 10진수로 간주됩니다.
*/
var val = parseInt(inputValue, 10);

* Booleans:

var age = 0;
 
var hasAge = Boolean(age);
 
var hasAge = !!age;

13. Naming Conventions


* 한문자 이름은 피하십시오. 이름에서 의도를 읽을 수 있도록 하십시오.

function query() {
  // ..stuff..
}

* Object, 함수, 그리고 인스턴스로는 camelCase를 사용하십시오.

var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
    name: 'Bob Parr'
});

* Class와 생성자에는 PascalCase를 사용하십시오.

function User(options) {
    this.name = options.name;
}
 
var good = new User({
    name: 'yup'
});

* private 속성 이름은 밑줄 _ 을 사용하십시오.

this._firstName = 'Panda';

* this의 참조를 저장할 때 _this 를 사용하십시오.

function() {
    var _this = this;
    return function() {
      console.log(_this);
    };
}

* 함수에 이름을 붙여주십시오. 이것은 stack traces를 추적하기 쉽게하기 때문입니다.

var log = function log(msg) {
    console.log(msg);
};

14. Accessors


* 속성을 위한 접근자(Accessor) 함수는 필요 없습니다.

* 접근자 함수가 필요한 경우 getVal() 이나 setVal('hello') 라고 사용합니다.

dragon.getAge();
 
dragon.setAge(25);

* 속성이 boolean의 경우 isVal() 이나 hasVal() 라고 사용합니다. TOGA에서는 isVal()로 사용한다.

if (!dragon.isAge()) {
    return false;
}

* 일관된다면 get() 이나 set() 이라는 함수를 작성해도 좋습니다.

function Jedi(options) {
    options || (options = {});
    var lightsaber = options.lightsaber || 'blue';
    this.set('lightsaber', lightsaber);
}
 
Jedi.prototype.set = function(key, val) {
    this[key] = val;
};
 
Jedi.prototype.get = function(key) {
    return this[key];
};

15. Constructors


* 새 Object에서 프로토타입을 재정의하는 것이 아니라, 프로토타입 객체에 메서드를 추가해 주십시오. 프로토타입을 재정의하면 상속이 불가능합니다. 프로토타입을 리셋하는것으로 베이스 클래스를 재정의 할 수 있습니다.

function Jedi() {
    console.log('new jedi');
}
 
Jedi.prototype.fight = function fight() {
    console.log('fighting');
};
 
Jedi.prototype.block = function block() {
    console.log('blocking');
};

* 메소드의 반환 값으로 this를 반환함으로써 메소드 체인을 할 수 있습니다.

Jedi.prototype.jump = function() {
    this.jumping = true;
    return this;
};
 
Jedi.prototype.setHeight = function(height) {
    this.height = height;
    return this;
};
 
var luke = new Jedi();
 
luke.jump().setHeight(20);

* 독자적인 toString()을 만들 수도 있지만 올바르게 작동하는지, 부작용이 없는 것만은 확인해 주십시오.

function Jedi(options) {
    options || (options = {});
    this.name = options.name || 'no name';
}
 
Jedi.prototype.getName = function getName() {
    return this.name;
};
 
Jedi.prototype.toString = function toString() {
    return 'Jedi - ' + this.getName();
};

16. Events


* (DOM 이벤트나 Backbone events와 같은 고유의) 이벤트 탑재체(payloads)의 값을 전달하는 경우 원시 값(raw value) 대신 해시 인수(hash)를 전달합니다. 이렇게하는 것으로 나중에 개발자가 이벤트와 관련된 모든 핸들러를 찾아 업데이트 하지 않고 이벤트 탑재체(payloads)에 값을 추가 할 수 있습니다.

$(this).trigger('listingUpdated', { listingId : listing.id });
 
...
 
$(this).on('listingUpdated', function(e, data) {
  // do something with data.listingId
});

17. Modules


* 모듈의 시작은 ! 로 시작하십시오. 이것은 문말에 세미콜론을 넣는것을 잊은 모듈을 연결할때 런타임 오류가 발생하지 않기 때문입니다.

* 파일 이름은 camelCase를 사용하여 같은 이름의 폴더에 저장해주십시오. 또한 단독으로 공개할 경우 이름을 일치시켜주십시오.

* noConflict() 라는 명칭으로 (이름이 겹쳐 덮어 써지기 전의) 모듈을 반환하는 메서드를 추가해주십시오.

* 항상 모듈의 시작 부분에서'use strict';를 선언해주십시오.

* TOGA는 richfaces에서의 jQuery랑 $ 사용이 겹쳐서 사용 못하고있다.

// fancyInput/fancyInput.js
 
!function(global) {
    'use strict';
 
    var previousFancyInput = global.FancyInput;
 
    function FancyInput(options) {
      this.options = options || {};
    }
 
    FancyInput.noConflict = function noConflict() {
      global.FancyInput = previousFancyInput;
      return FancyInput;
    };
 
    global.FancyInput = FancyInput;
}(this);

18. jQuery


* jQuery Object의 변수 앞에는 $을 부여해 주십시오.

var $sidebar = $('.sidebar');

* jQuery 쿼리결과를 캐시해주십시오.

function setSidebar() {
    var $sidebar = $('.sidebar');
    $sidebar.hide();
 
    // ...stuff...
 
    $sidebar.css({
      'background-color': 'pink'
    });
}

* DOM 검색은 Cascading $('.sidebar ul') 이나 parent > child $('.sidebar > ul') 를 사용해주십시오.

* jQuery Object 검색은 스코프가 붙은 find를 사용해주십시오.

$('.sidebar ul').hide();
 
$sidebar.find('ul');

* 반복문 .each

<div>
    <span>첫번째</span>
    <span>두번째</span>
    <span>세번째</span>
</div>
 
$('div').find('span').each(function(i, e){
    console.log($(this).text());
});

* 객체병합 .extend

/**
* 재귀적으로 두 객체를 병합하여 첫 번째 객체를 수정합니다.
*/
var object1 = {
    apple: 0,
    banana: { 
        weight: 52, 
        price: 100 
    },
    cherry: 97
};
var object2 = {
    banana: { 
        price: 200 
    },
    durian: 100
};
 
$.extend( true, object1, object2 );
 
/**
* 기본값을 수정하지 않고, 기본값 및 옵션을 병합합니다.
*/
var defaults = { 
    validate: false, 
    limit: 5, 
    name: "foo" 
};
var options = { 
    validate: true, 
    name: "bar" 
};
 
var settings = $.extend( {}, defaults, options );

19. Debug


* F12 키를 눌러 개발자 도구로 Debug를 할 수 있습니다.

* Debug시 alert가 아닌 console로 값을 확인합니다. alert는 Object의 값이 보이지 않기 때문입니다.

* console 사용법

console.log() // 콘솔에 로그 메세지를 보냅니다. 가장 많이 사용합니다.
console.info() // 콘솔에 정보 메세지를 보냅니다. 메세지 앞에 정보 아이콘이 있습니다.
console.warn() // 콘솔에 경고 메세지를 보냅니다. 메세지 앞에 경고 아이콘이 있습니다.
console.error() // 콘솔에 오류 메세지를 보냅니다. 메세지 색을 빨간색이고 앞에는 오류 아이콘이 있습니다.
console.trace() // 콘솔에 stack trace를 기록합니다.
console.dir() // 해당 객체의 트리뷰(tree view)를 보여줍니다. 객체의 properties를 출력합니다.
console.clear() // 콘솔에 메세지를 삭제합니다.

* console 창이 떠있는지 확인하는 방법

if (console){
    console.log('콘솔창이 떠있습니다.');
}
javascript_스타일_가이드.txt · Last modified: 2015/05/11 16:38 by nmaruchi