CoffeeScript의 함수 선언


79

CoffeeScript에서 다음을 사용하여 함수를 정의하면 알 수 있습니다.

a = (c) -> c=1

함수 표현식 만 얻을 수 있습니다 .

var a;
a = function(c) {
    return c = 1;
};

그러나 개인적으로 나는 종종 함수 선언을 사용 합니다 .

function a(c) {
    return c = 1;
}

첫 번째 형식을 사용하지만 CoffeeScript에서 함수 선언을 생성하는 방법이 있는지 궁금합니다. 그런 방법이 없다면 CoffeeScript가이 작업을 피하는 이유를 알고 싶습니다. 함수가 범위의 맨 위에 선언되는 한 JSLint가 선언 오류를 외칠 것이라고 생각하지 않습니다.


4
함수 선언을 원하는 타당한 이유가 있습니까? coffeescript를 사용하는 경우 컴파일 된 JS의 형식이 손상되거나 버그가 발생하지 않는 한 신경 쓰지 않아야합니다.
Raynos

3
대부분의 경우 함수 선언과 함수 표현식은 같은 방식으로 작동하지만 둘 사이에는 약간의 차이가 있습니다. 예를 들어, developer.mozilla.org/en/JavaScript/Reference/… 따라서 어떤 경우에는 같지 않습니다.
Grace Shao

함수 선언이 정의되지 않은 동작 인 코드에 저를 연결했습니다. 정의되지 않은 동작을 남용 할 수 있도록 함수 표현식 대신 함수 선언을 사용 하시겠습니까?
Raynos

5
@Raynos 함수 선언은 함수에 이름이 첨부되어 있으므로 스택 추적 및 기타 디버깅에 유용 할 수 있습니다. 이것이 CoffeeScript에서 classes를 사용하는 이유 입니다.
Trevor Burnham 2011

2
@TrevorBurnham 나는 컴파일 된 js를 디버깅하는 데있어서 약간의 개선 일뿐임을 의미했습니다. 실제로 원하는 것은 coffeescript를 읽을 수있는 디버거입니다.
Raynos

답변:


61

CoffeeScript는 함수 선언 (일명 "명명 된 함수")을 class정의 라는 한 곳에서 사용 합니다. 예를 들어

class Foo

컴파일

var Foo;
Foo = (function() {
  function Foo() {}
  return Foo;
})();

FAQ 에 따르면 CoffeeScript가 다른 곳에서 함수 선언을 사용하지 않는 이유는 다음과 같습니다.

이 문제에 대해 Microsoft를 비난하십시오. 원래는 검색 가능한 이름을 가질 수있는 모든 함수에 하나가 주어졌지만 IE 버전 8 이하에서는 명명 된 함수가 선언과 표현식 모두로 처리되는 범위 지정 문제가 있습니다. 참조 자세한 내용은.

간단히 말해서, 함수 선언을 부주의하게 사용하면 IE (9 이전)와 다른 JS 환경간에 불일치가 발생할 수 있으므로 CoffeeScript는이를 피합니다.


31
그는 명명 된 함수 표현식 (예 :)에 대한 IE의 문제에 대해 이야기하고 var a = function a() {};있습니다. 함수 선언 (예 function a() {}
:)

4
처음에 브라우저에서 CS를 사용하는 것이 제정신이 아니었다면 이것은 나에게 더 이해가 될 것입니다. 브라우저 변형 및 사용 중단을 따라 잡기 위해 DOM 처리 라이브러리에 대한 믿음을 두는 것이 한 가지이지만, 실제 소스 코드 자체에 대해 이야기하는 것은 이중 위험 종속성과 같습니다. CS 커뮤니티가 고갈되고 다음 단계로 넘어 가고 난 후 10 년 만에 레거시 코드베이스를 처리한다고 상상해보십시오. 모든 것이 중단되기 시작하고 더 이상 사용되지 않는 항목을 찾고 CS 파서에서 수정해야 할 사항을 파악해야합니다.
Erik Reppen 2014-08-07

12

그래 넌 할수있어:

hello()

`function hello() {`
console.log 'hello'
dothings()
`}`

백틱`를 통해 순수한 JS를 이스케이프합니다.

함수 본문에서는 들여 쓰기 할 수 없습니다.

건배


19
이것은 coffeescript에서 수행되고 있음을 나타내지 않습니다. coffeescript 만 javascript로 이스케이프 할 수 있습니다. 또한 이것은 불쾌합니다!
Mr Wilde

9
사용하기 전에 정의는 더 불쾌한의 xD입니다
자이드 Daghestani

1
또한 함수 선언 은 v8 이후 버전에서 크게 최적화 된 것으로 보입니다 .
James M. Lay

쓸 수 있습니다 function updateSettings() {. do-> dothings () }는 들여 쓰기를 허용합니다. github.com/jashkenas/coffeescript/issues/...
avalanche1

6

CoffeeScript에서 명심해야 할 한 가지는 항상 JavaScript로 돌아갈 수 있다는 것입니다. CoffeeScript는 명명 된 함수 선언을 지원하지 않지만 언제든지 JavaScript로 돌아와이를 수행 할 수 있습니다.

http://jsbin.com/iSUFazA/11/edit

# http://jsbin.com/iSUFazA/11/edit
# You cannot call a variable function prior to declaring it!
# alert csAddNumbers(2,3) # bad!

# CoffeeScript function
csAddNumbers = (x,y) -> x+y

# You can call a named function prior to
# delcaring it
alert "Calling jsMultiplyNumbers: " + jsMultiplyNumbers(2,3) # ok!

# JavaScript named function
# Backticks FTW!
`function jsMultiplyNumbers(x,y) { return x * y; }`

CoffeeScript에서 큰 함수를 작성한 다음 백틱 트릭을 사용하여 JavaScript가 다른 함수를 호출하도록 할 수도 있습니다.

# Coffeescript big function
csSomeBigFunction = (x,y) ->
   z = x + y
   z = z * x * y
   # do other stuff
   # keep doing other stuff

# Javascript named function wrapper
`function jsSomeBigFunction(x,y) { return csSomeBigFunction(x,y); }`

1

아니요, 커피 스크립트에서 함수를 정의하고 커피 스크립트에서 함수 선언을 생성하도록 할 수 없습니다.

그냥 써도

-> 123

생성 된 JS는 괄호로 래핑되어 함수 표현식이됩니다.

(function() {
  return 123;
});

내 생각 엔 이것이 커피 스크립트 소스의 논리적 흐름을 깨뜨리는 함수 선언이 둘러싸는 범위의 맨 위로 "게양"되기 때문입니다.


11
게양은 정확히 내가 함수 선언을 사용하려는 이유입니다!
ivanreese 2013-08-05

1
CoffeeScript는 범위의 맨 위에 var를 사용하여 변수를 미리 선언하기 때문에 이미 "호이스트"합니다. 따라서 함수는 서로를 참조 할 수 있으며 순서는 중요하지 않습니다.
Evan Moran 2013 년

15
@EvanMoran CoffeeScript가 변수를 미리 선언하는 것은 사실이지만, 함수 표현식까지 변수가 정의되지 않은 상태로 남아 있기 때문에 함수가 호이스트되지 않습니다. 따라서 정의 될 때까지 함수를 사용할 수 없습니다.
jasonkarns 2013 년

1

이전 게시물이지만 향후 Google 직원을 위해 대화에 추가하고 싶었습니다.

OP는 순수 CoffeeScript에서 함수를 선언 할 수 없다는 점에서 정확합니다 (CoffeeScript 파일 내에서 순수 JS를 이스케이프하기 위해 백틱을 사용하는 아이디어 제외).

하지만 우리가 할 수있는 것은 함수를 창에 바인딩하는 것이며 본질적으로 이름이 지정된 함수 인 것처럼 호출 할 수있는 것으로 끝납니다. 나는 이것이 명명 된 함수 라고 말하는 것이 아니라, 순수한 CoffeeScript를 사용하여 OP가 실제로하고 싶은 일 (코드 어딘가에서 foo (param)과 같은 함수 호출)을 수행하는 방법을 제공하고 있습니다.

다음은 coffeescript의 창에 연결된 함수의 예입니다.

window.autocomplete_form = (e) ->
    autocomplete = undefined
    street_address_1 = $('#property_street_address_1')
    autocomplete = new google.maps.places.Autocomplete(street_address_1[0], {})
    google.maps.event.addListener autocomplete, "place_changed", ->
        place = autocomplete.getPlace()

        i = 0

        while i < place.address_components.length
            addr = place.address_components[i]
            st_num = addr.long_name if addr.types[0] is "street_number"
            st_name = addr.long_name if addr.types[0] is "route"

            $("#property_city").val addr.long_name if addr.types[0] is "locality"
            $("#property_state").val addr.short_name if addr.types[0] is "administrative_area_level_1"
            $("#property_county").val (addr.long_name).replace(new RegExp("\\bcounty\\b", "gi"), "").trim() if addr.types[0] is "administrative_area_level_2"
            $("#property_zip_code").val addr.long_name if addr.types[0] is "postal_code"
            i++

        if st_num isnt "" and (st_num?) and st_num isnt "undefined"
            street1 = st_num + " " + st_name
        else
            street1 = st_name

        street_address_1.blur()
        setTimeout (->
            street_address_1.val("").val street1
            return
            ), 10
        street_address_1.val street1
        return

이것은 Google 지역 정보를 사용하여 주소 정보를 반환하여 양식을 자동으로 채 웁니다.

따라서 페이지에로드되는 Rails 앱에 부분이 있습니다. 즉, DOM이 이미 생성되었으며 초기 페이지로드시 위의 함수를 호출하면 (ajax 호출이 부분을 렌더링하기 전에) jQuery는 $ ( '# property_street_address_1') 요소를 볼 수 없습니다. 티).

따라서 요소가 페이지에 표시 될 때까지 google.maps.places.Autocomplete ()를 지연시켜야합니다.

부분이 성공적으로로드되면 Ajax 콜백을 통해이를 수행 할 수 있습니다.

            url = "/proposal/"+property_id+"/getSectionProperty"
            $("#targ-"+target).load url, (response, status, xhr) ->
                if status is 'success'
                    console.log('Loading the autocomplete form...')
                    window.autocomplete_form()
                    return

            window.isSectionDirty = false

그래서 여기서 본질적으로 우리는 foo ()를 호출하는 것과 같은 일을하고 있습니다.


1

왜? 때문에 함수 선언은 악이다. 이 코드를보세요

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

출력에 무엇이 표시됩니까?

b
b

함수 정의를 사용하면

var a = function() {
        return 'a';
}

console.log(a());

a = function() {
        return 'b';
}

console.log(a());

출력은 다음과 같습니다.

a
b

8
함수 선언에는 나쁜 것이 없습니다. JS에서 변수 및 함수 선언이 어떻게 호이스트되는지 이해하기 만하면됩니다. 가변 호이 스팅기능 호이
Ben Harold

함수 정의는 함수 선언보다 더 직관적입니다.
Tomasz Jakub Rup 2011

0

이 시도:

defineFct = (name, fct)->
  eval("var x = function #{name}() { return fct.call(this, arguments); }")
  return x

이제 다음은 "true"를 인쇄합니다.

foo = defineFct('foo', ()->'foo')
console.log(foo() == foo.name)

나는 실제로 이것을 사용하지 않지만 때때로 커피 기능에 내성을위한 이름이 있기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.