Skip to content

Instantly share code, notes, and snippets.

@bynaki
Last active November 18, 2015 21:16
Show Gist options
  • Save bynaki/970c27e4cf553e57117f to your computer and use it in GitHub Desktop.
Save bynaki/970c27e4cf553e57117f to your computer and use it in GitHub Desktop.
Coffee Script - 설치. - Coffee Script 명령어 - JavaScript로 컴파일. -

Coffee Script

설치.

$ npm install -g coffee-script

Coffee Script 명령어

-b --bare 컴파일된 JavaScript를 함수로 감싸지 않는다.
-c --complie JavaScript로 컴파일하고, .js 파일로 저장한다.
-e --eval 명령어 라인에서 전달받은 문자열을 컴파일한다.
-h --help 도움말을 출력한다.
-i --interactive 대화식의 CoffeeScript REPL 모드로 수행한다.
-j --join 컴파일 전에 스크립트들을 합친다.
-m --map generate source map and save as .js.map files
-n --nodes 파서가 생성한 트리를 보여준다.
--nodejs node.js로 전달할 옵션을 지정한다.
--no-header suppress the "Generated by" header
-o --output 컴파일되는 JavaScript 파일 저장 경로를 저정한다.
-p --print 컴파일된 JavaScript를 표준 출력으로 보낸다.
-r --require 스크립트 수행 전에 필요한 라이브러리를 지정한다.
-s --stdio 표준 입출력을 통해 스크립트들을 컴파일한다.
-l --literate treat stdio as literate style coffee-script
-t --tokens Lexer가 만든 토큰을 보여준다.
-v --version CoffeeScript 버전 정보를 나타낸다.
-w --watch 스크립트를 지켜보고 있다 변경되면 다시 명령을 수행한다.
JavaScript로 컴파일.
$ coffee -c mochaccino.coffee
# 자바스크립트로 컴파일 되어 mochaccino.js를 현재 위치에 저장한다.
다른 디렉토리로 컴파일.
$ coffee -co output source
# source 디렉토리에 있는(하위 디렉토리 포함) 모든 .coffee 파일을 컴파일한 뒤 그에 해당하는
# .js 파일들을 output 디렉토리에 생성한다.
소스 파일에 변경이 있을 때마다 재컴파일.
$ coffee -cwo js coffee

Function 함수

익명함수 정의

code:

-> 'Hello, functions!'

익명함수 실행

code:

console.log do -> 'Hello, functions'

result:

Hello, functions

일반적 함수 정의

code:

hi = -> 'Hello, functions!'
console.log hi()

result:

Hello, functions!

인자가 있는 함수 정의.

code:

greeting = (subject) -> "Hi, #{subject}"
console.log greeting 'CoffeeScript'

result:

Hi, CoffeeScript

is 키워드

code:

odd = (num) -> num % 2 is 1
# is는 JavaScript의 === 과 같다.
console.log odd(3)

result:

true

조건과 예외 :: if, throw, try, catch

code:

odd = (num) ->
  if typeof num is 'number'
    if num is Math.round num
      if num > 0
        num % 2 is 1
      else
        throw "#{num}는 양수가 아니다."
    else
      throw "#{num}는 정수가 아니다."
  else
    throw "#{num}는 숫자가 아니다."

try
  odd 5.1
catch e
  console.log e

result:

5.1는 정수가 아니다.

unless

code:

odd = (num) ->
  unless typeof num is 'number'
    throw "#{num} is not a number"
  unless num is Math.round num
    throw "#{num} is an integer"
  unless num > 0
    throw "#{num} is not positive"
  num % 2 is 1

try
  odd 5.1
catch e
  console.log e

result:

5.1 is an integer

변수 범위 :: Scope

#1

code:

age = 99
reincarnate = -> age = 0
reincarnate()
console.log "I am #{age} years old"

result:

I am 0 years old
#2

code:

reincarnate = -> age = 0
age = 99
reincarnate()
console.log "I am #{age} years old"
# 모든 함수는 범위를 만들고, 범위를 생성하는 유일한 방법은 함수 정의를 통해서다.
# 아니면 전역 범위.

result:

I am 99 years old

컨텍스트(@) this :: Context

code:

setName = (name) -> @name = name

cat = {}
cat.setName = setName
cat.setName 'Mittens'
console.log cat.name

pig = {}
setName.apply pig, ['Babe']
# setName.call pig, 'Babe' 와 같다.
console.log pig.name

horse = {}
cat.setName.apply horse, ['Mr. Ed']
console.log horse.name

Dog = setName
dog1 = new Dog('Jimmy')
dog2 = new Dog('Jake')
console.log dog1.name
console.log dog2.name

setName 'LuLu'
console.log name
console.log @name

result:

Mittens
Babe
Mr. Ed
Jimmy
Jake
LuLu
undefined

바운드(=>) 함수 :: bind()

code:

apply = (callback) -> callback()
Dog = ->
  callback = => @name = 'Merry'
  # var callback = (function() { this.name = 'Merry'; }).bind(this);
  apply callback
dog = new Dog()
console.log dog.name

result:

Merry

속성 인자 (@arg)

code:

setName = (@name) ->
# setName = (name) -> @name = name
setName 'naki'
console.log name

result:

naki

기본 인자 (arg=)

#1

code:

ringFireAlarm = (isDrill = true) -> isDrill
console.log ringFireAlarm()
console.log ringFireAlarm(false)

result:

true
false
#2

code:

chooseMeals = (breakfast = 'waffles', lunch = 'gyros', dinner = 'pizza') ->
  console.log breakfast, lunch, dinner
chooseMeals null, 'burrito', null

result:

waffles burrito pizza
#3

code:

dontTryThisAtHome = (noArgNoProblem = @iHopeThisWorks()) ->
  ...

존재 연산자 ?

  • undefined 또는 null 인지 채크한다.
  • x? 라고 하면 'x가 존재하는가?' 라고 생각하면 된다.

code:

a = 'a defined'
b = 'b defined'
console.log a ? b
console.log c ? b

myFun?()
myFun = (c) ->
  c ?= a # c가 정의되지 안았다면 값 a로 정의.
  console.log "myFun: c = #{c}"
myFun()
myFun?() # myFun가 존재한다면 실행.

reuslt:

a defined
b defined
myFun: c = a defined
myFun: c = a defined

Splats (...)

#1

code:

refine = (wheat, chaff...) ->
  console.log "The best: #{wheat}"
  console.log "The rest: #{chaff.join(', ')}"
refine 'great', 'not bad', 'so-so', 'meb'

sandwich = (beginning, middle..., end) ->
  console.log beginning, middle, end
sandwich 'apple', 'tomato'
# Splats가 아닌 인자부터 우선 지정된다.

spoiler = (fillter..., theEnding) ->
  console.log theEnding
spoiler 'Darth vader is Luke\'s father!'

result:

The best: great
The rest: not bad, so-so, meb
apple [] tomato
Darth vader is Luke's father!
#2

code:

birds = ['duck', 'duck', 'duck', 'duck', 'goose!']
[ducks..., goose] = birds
console.log ducks

console.log 1, 2, 3, 4
arr = [1, 2, 3]
console.log arr, 4
console.log arr..., 4

result:

[ 'duck', 'duck', 'duck', 'duck' ]
1 2 3 4
[ 1, 2, 3 ] 4
1 2 3 4

객체 :: Object

간소화된 JSON :: CSON

code:

father =
  name: 'John'
  daughter:
    name: 'Jill'
  son:
    name: 'Jack'
console.log father

result:

{ name: 'John',
  daughter: { name: 'Jill' },
  son: { name: 'Jack' } }

동일한 이름의 키-값 쌍

code:

delta = '\u0394'
greekUnicode = {delta}
console.log greekUnicode
users = {'naki', 'miki'}
console.log users

result:

{ delta: 'Δ' }
{ naki: 'naki', miki: 'miki' }

Soaks :: a?.b

#1

code:

a = b?.property ? c # good
#2

code:

obj?.greet()
obj = {}
obj?.greet?()
obj.greet = -> console.log 'Hello!!'
obj?.greet?()

result:

Hello!!

배열 :: Array

범위 :: Range

code:

console.log [1..5]
console.log [1...5]
console.log [5..1]
console.log [5...1]

result:

[ 1, 2, 3, 4, 5 ]
[ 1, 2, 3, 4 ]
[ 5, 4, 3, 2, 1 ]
[ 5, 4, 3, 2 ]

Slice, Splice

#1

code:

console.log ['a', 'b', 'c', 'd'].slice 0, 3
console.log ['a', 'b', 'c', 'd'][0...3]
console.log ['a', 'b', 'c', 'd'][0..3]
console.log ['a', 'b', 'c', 'd'][3...0]
# console.log(['a', 'b', 'c', 'd'].slice(3, 0))
console.log 'The year is 3022'[-4..]
console.log ['this', 'that', 'the other'][1..]
console.log ['this', 'that', 'the other'][1...]

result:

[ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
[ 'a', 'b', 'c', 'd' ]
[]
3022
[ 'that', 'the other' ]
[ 'that', 'the other' ]
#2

code:

arr = ['a', 'c']
arr[1...2] = ['b']
console.log arr

arr = ['a', 'c']
arr[1...1] = ['b']
console.log arr

arr = ['a', 'c']
arr = ['b', arr...]
console.log arr

steveAustin = ['regular', 'guy']
replacementParts = ['better', 'stronger', 'faster']
steveAustin[0..] = replacementParts
console.log steveAustin

result:

[ 'a', 'b' ]
[ 'a', 'b', 'c' ]
[ 'b', 'a', 'c' ]
[ 'better', 'stronger', 'faster' ]

컬렉션에서의 반복문 :: for of, for in

#1

code:

obj = naki: 'hi, naki', miki: 'hi, miki'
for key, value of obj # JavaScript의 for in 과 같다.
  console.log key, value
# 대상이 객체일때 사용한다.

console.log '-----------------------'
Obj2 = ->
Obj2.prototype = obj
obj2 = new Obj2()
obj2.john = 'hi, john'
console.log obj2.hasOwnProperty('naki')
console.log obj2.hasOwnProperty('john')
for key, value of obj2
  console.log key, value
for own key, value of obj2
  console.log key, value

console.log '-----------------------'
array = ['naki', 'miki', 'suni', 'mooni', 'youghee']
for value in array
  console.log value
# 대상이 배열일때 사용한다.

console.log '-----------------------'
sum = 0
for value in [1..10]
  sum += value
console.log 'sum: ', sum

result:

naki hi, naki
miki hi, miki
-----------------------
false
true
john hi, john
naki hi, naki
miki hi, miki
john hi, john
-----------------------
naki
miki
suni
mooni
youghee
-----------------------
sum:  55
#2

code:

decimate = (army) ->
  execute(soldier) for soldier in army by 10
# 10단위씩 실행한다.

animate = (startTime, endTime, framesPerSecond) ->
  for pos in [startTime..endTime] by 1 / framesPerSecond
    addFrame pos
# 분수도 가능하다.

countdown = (max) ->
  console.log x for x in [max..0] by -1
# 음수값도 사용할 수 있지만 배열에서는 사용할 수 없다.
#3

code:

fruits = ['apple', 'cherry', 'tomato']
console.log 'tomato' in fruits
germanToEnglish = {ja: 'yes', nein: 'no'}
console.log 'ja' of germanToEnglish
console.log germanToEnglish['ja']?

result:

true
true
true

조건식을 포함한 반복문 :: while, until, loop

code:

makeHay() while sunShines()
makeHay() until sunSets() # while not

loop
  console.log 'Home'
  break if @flag is true
  console.log 'Sweet'
  @flag = true

a = 0
loop break if ++a > 999 console.log a # 1000
# loop는 접두 표기를 사용한다.

함축 :: Comprehensions

code:

negativeNumbers = (-num for num in [1, 2, 3, 4])
console.log negativeNumbers

chars = ['a', 'b', 'c']
handlKeyPress = -> chars.pop()
keysPressed = (char while char = handlKeyPress())
console.log keysPressed


code = ['U', 'U', 'D', 'D', 'L', 'R', 'L', 'R', 'B', 'A']
codeKeyValues = for key in code
  switch key
    when 'L' then 37
    when 'U' then 38
    when 'R' then 39
    when 'D' then 40
    when 'A' then 65
    when 'B' then 66
console.log codeKeyValues

evens = (x for x in [2..10] by 2)
console.log evens
isInteger = (num) -> num is Math.round(num)
numsThatDivid960 = (num for num in [1..960] when isInteger(960 / num))
console.log numsThatDivid960

result:

[ -1, -2, -3, -4 ]
[ 'c', 'b', 'a' ]
[ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65 ]
[ 2, 4, 6, 8, 10 ]
[ 1,
  2,
  3,
  4,
  5,
  6,
  8,
  10,
  12,
  15,
  16,
  20,
  24,
  30,
  32,
  40,
  48,
  60,
  64,
  80,
  96,
  120,
  160,
  192,
  240,
  320,
  480,
  960 ]

패턴 매칭 (할당 해체) :: Pattern Matching (or, Destructuring Assignment)

code:

[firstName, middleInitial, lastName] = ['Joe', 'T', 'Plumber']
console.log firstName, middleInitial, lastName

newBoss = 'naki'
oldBoss = 'mike'
[newBoss, oldBoss] = [oldBoss, newBoss]
console.log newBoss, oldBoss

[theBest, theRest...] = ['naki', 'mike', 'youghee']
console.log theBest, theRest

myRect =
  x: 100
  y: 200
{x: myX, y: myY} = myRect
console.log 'myX: ', myX, 'myY: ', myY

{x, y} = myRect
console.log 'x: ', x, 'y: ', y

{ok, strictEqual} = require 'assert'

{languages: [favoriteLanguage, otherLanguages...]} = resume

result:

Joe T Plumber
mike naki
naki [ 'mike', 'youghee' ]
myX:  100 myY:  200
x:  100 y:  200

모듈 :: Module

#1

code:

root = global ? window
# file1.coffee
root.emergencyNumber = 911
# 글로벌 영역에 변수를 만들려면 root를 참조해야한다. (익명함수에 감싸져 있기때문.)

# file2.coffee
console.log emergencyNumber # '911'
emergencyNumber is root.emergencyNumber # true
#2

code:

root = global ? window
# file1.coffee
root.dogName = 'Fido'
dogName is root.dogName # true

# file2.coffee
console.log dogName # undefined
# 이 파일 영역의 익명함수 맨 위에 var dogName; 이 선언되기 때문이다.
dogName = 'Bingo'
dogName is root.dogName # false

클래스 :: Class

프로토타입 :: Prototype

#1

code:

Boy = ->
Boy::sing = -> console.log "It isn't easy being a boy named Sue"
# Boy.prototype.sing 을 의미한다.
# ::는 prototype 을 의미한다.
sue = new Boy()
sue.sing()

result:

It isn't easy being a boy named Sue
#2

code:

Gift = (@name) ->
  Gift.count++
  @day = Gift.count
  @announce()

Gift.count = 0
Gift::announce = ->
  console.log "On day #{@day} of Christmas I received #{@name}"

gift1 = new Gift('a partridge in a pear tree')
gift2 = new Gift('two turtle doves')

result:

On day 1 of Christmas I received a partridge in a pear tree
On day 2 of Christmas I received two turtle doves
#3

code:

Raven = ->
Raven::quoth = -> console.log 'Navermore'
raven1 = new Raven()
raven1.quoth()

Raven::quoth = -> console.log "I'm hungry"
raven1.quoth()

raven2 = new Raven()
raven2.quoth = -> console.log "I'm my own kind of raven"
raven1.quoth()
raven2.quoth()

console.log raven1.hasOwnProperty('quoth')
console.log raven2.hasOwnProperty('quoth')

result:

Navermore
I'm hungry
I'm hungry
I'm my own kind of raven
false
true

클래스 :: Class

code:

class Tribble
  constructor: ->
    @isAlive = true
    Tribble.count++

  # Prototype properties
  breed: -> new Tribble if @isAlive
  die: ->
    Tribble.count-- if @isAlive
    @isAlive = false

  # Class-level properties
  @count: 0
  @makeTrouble: -> console.log ('Trouble!' for i in [1..@count]).join(' ')


tribble1 = new Tribble()
tribble2 = new Tribble()
Tribble.makeTrouble()

tribble1.die()
Tribble.makeTrouble()

tribble2.breed().breed().breed()
Tribble.makeTrouble()

result:

Trouble! Trouble!
Trouble!
Trouble! Trouble! Trouble! Trouble!

상속 :: Inheritance with ’extends’

상속 :: Inheritance

#1

code:

class Pet
  constructor: -> @isHungry = true
  eat: -> @isHungry = false

class Dog extends Pet
  eat: ->
    console.log '*crunch, crunch*'
    super()   # Pet::eat.call this
  fetch: ->
    console.log 'Yip yip!'
    @isHungry = true
#2

code:

class Appliance
  constructor: (warranty) ->
    warrantyDb.save(this) if warranty

class Toaster extends Appliance
  constructor: (warranty) ->
    super
    # 생성자의 모든 인자를 전달하려면 간단하게 괄호 없는 super 를 사용하면 된다.

다형성 :: Polymorphism

code:

class Shape
  constructor: (@width) ->
  computeArea: -> throw new Error('I am an abstract class!!')

class Square extends Shape
  computeArea: -> Math.pow @width, 2

class Circle extends Shape
  radius: -> @width / 2
  computeArea: -> Math.PI * Math.pow @radius(), 2

showArea = (shape) ->
  unless shape instanceof Shape
    throw new Error('showArea requires a Shape instance!')
  console.log shape.computeArea()

showArea new Square(2)
showArea new Circle(2)

result:

4
3.141592653589793

Switch

#1

code:

requisitionStarship = (captain) ->
  switch captain
    when 'Kirk', 'Picard', 'Archer'
      new Enterprise()
      # 암묵적으로 처리가 중단된다
    when 'Janeway'
      new Voyager()
    else
      throw new Error('Invalid starship captain')
  # switch의 결과가 반환된다.
#2

code:

console.log switch 1
  when 0
    '0!!'
  when 1
    '1!!'
  when 2
    '2!!'
  else
    'invalidated value!!'

result:

1!!

브라우저 기반 CoffeeScript 사용 :: Browser, Front End

code: index.html

<html>
  <head>
    <title></title>
    <script type="text/javascript" src="coffee-script.js"></script>
    <script type="text/javascript" src="jquery-1.5.2.min.js"></script>
    <script type="text/coffeescript" src="Dictionary.coffee"></script>
    <link rel="stylesheet" type="text/css" href="./style.css" />
  </head>
  <body>
  </body>
</html>

code: Dictionary.coffee

root = exports ? window
# node.js 라면 exports, 브라우저라면 window
root.Dictionary = Dictionary
...

Node.js 에서 CoffeeScript 사용. :: JavaScript 에서 CoffeeScript 사용.

code: first.coffee

exports.greet = ->
  console.log "I'm first.coffee!!"

code: second.js

var CoffeeScript = require('coffee-script');
CoffeeScript.register();
// or require('coffee-script/register');
var greet = require('./first').greet;
greet();

result:

I'm first.coffee!!
{"noteId":"1510fa58be0-922421e5","main":"1510fa58be0-922421e5.md","title":"Coffee Script - 설치. - Coffee Script 명령어 - JavaScript로 컴파일. - 다른 디렉토리로 컴파일. - 소스 파일에 변경이 있을 때마다 재컴파일. - Function 함수 - 익명함수 정의 - 익명함수 실행 - 일반적 함수 정의 - 인자가 있는 함수 정의. - is 키워드 - 조건과 예외 :: if, throw, try, catch - unless - 변수 범위 :: Scope - #1 - #2 - 컨텍스트(@) this :: Context - 바운드(=&gt;) 함수 :: bind() - 속성 인자 (@arg) - 기본 인자 (arg=) - #1 - #2 - #3 - 존재 연산자 ? - Splats (...) - #1 - #2 - 객체 :: Object - 간소화된 JSON :: CSON - 동일한 이름의 키-값 쌍 - Soaks :: a?.b - #1 - #2 - 배열 :: Array - 범위 :: Range - Slice, Splice - #1 - #2 - 컬렉션에서의 반복문 :: for of, for in - #1 - #2 - #3 - 조건식을 포함한 반복문 :: while, until, loop - 함축 :: Comprehensions - 패턴 매칭 (할당 해체) :: Pattern Matching (or, Destructuring Assignment) - 모듈 :: Module - #1 - #2 - 클래스 :: Class - 프로토타입 :: Prototype - #1 - #2 - #3 - 클래스 :: Class - 상속 :: Inheritance with ’extends’ - 상속 :: Inheritance - #1 - #2 - 다형성 :: Polymorphism - Switch - #1 - #2 - 브라우저 기반 CoffeeScript 사용 :: Browser, Front End - Node.js 에서 CoffeeScript 사용. :: JavaScript 에서 CoffeeScript 사용."}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment