CoffeeScript에서 전역 변수를 어떻게 정의합니까?


317

Coffeescript.org에서 :

bawbag = (x, y) ->
    z = (x * y)

bawbag(5, 10) 

컴파일 :

var bawbag;
bawbag = function(x, y) {
  var z;
  return (z = (x * y));
};
bawbag(5, 10);

node.js에서 coffee-script를 통해 컴파일하면 다음과 같이 요약됩니다.

(function() {
  var bawbag;
  bawbag = function(x, y) {
    var z;
    return (z = (x * y));
  };
  bawbag(5, 10);
}).call(this);

문서는 말합니다 :

다른 스크립트에서 사용할 최상위 변수를 작성하려면 창 또는 CommonJS의 내보내기 오브젝트에서 특성으로 해당 변수를 첨부하십시오. CommonJS와 브라우저를 모두 대상으로하는 경우 실존 연산자 (아래에서 설명)는 추가 할 위치를 파악할 수있는 안정적인 방법을 제공합니다. root = exports? 이

CoffeeScript에서 전역 변수를 어떻게 정의합니까? '창에 속성으로 첨부하는 것'은 무엇을 의미합니까?


4
전역 변수를 사용하는 것이 나쁜 것을 메모를 수행 c2.com/cgi/wiki?GlobalVariablesAreBad , 심지어 해로운 것으로 간주 c2.com/cgi/wiki?GotoConsideredHarmful을 . 그리고 전역 변수를 사용하여 해결하는 대부분의 문제를 해결할 수있는 클로저와 같은 훌륭한 기능이 있기 때문에 JavaScript에서 전혀 사용할 이유가 없습니다.
Evgeny 2016 년

9
@Evgeny 여기에 동의하지만 경우에 따라 중앙 '앱'객체를 생성하고 모듈을 연결해야합니다.
jackyalcine

1
중앙 객체는 window객체 또는 객체와 같은 기존 전역 상태 객체에 저장할 수 있습니다 exports. 전역 변수를 만들 필요가 없습니다.
Evgeny

9
@Evgeny 글로벌 변수의 속성으로 저장됩니다 window(또는 globalnodejs에) 개체
shesek

21
예, 전역 변수를 갖는 것은 채소가 아닙니다. 앱을 무심코 괴롭히는 것은 나쁜 습관입니다. 하나를 선언하고 jQuery 또는 네임 스페이스와 같은 어댑터 팩토리로 사용하는 것이 실제로 일반적입니다.
Erik Reppen 2013

답변:


419

coffee script에는 varstatement 가 없으므로 coffee-script의 모든 변수에 대해 자동으로이를 삽입하므로 컴파일 된 JavaScript 버전이 모든 것을 전역 네임 스페이스 로 유출하는 것을 방지합니다 .

따라서 의도적으로 커피 스크립트 측면에서 전역 네임 스페이스에 "누설"무언가를 만들 수있는 방법이 없으므로 전역 변수를 전역 객체의 속성으로 정의해야 합니다 .

창에서 속성으로 첨부

이것은 전역 객체window.foo = 'baz';이므로 브라우저 케이스를 처리하는 것과 같은 것을 수행해야 함을 의미 합니다 .window

Node.js

Node.js에는 window객체 가 없으며 대신 exportsNode.js 모듈을 감싸는 래퍼로 전달되는 객체가 있습니다 ( https://github.com/ry/node/blob/master/src/node.js# 참조). L321 ), 그래서 Node.js를에 당신이해야 할 것 인 것이다 exports.foo = 'baz';.

이제 문서에서 인용 한 내용이 무엇인지 살펴 보겠습니다.

... CommonJS와 브라우저를 모두 대상으로 : root = exports? 이

이것은 분명히 커피 스크립트이므로 실제로 컴파일하는 내용을 살펴 보겠습니다.

var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;

먼저 exportsJavaScript에 존재하지 않는 변수를 참조하려고하면 SyntaxError가 발생하기 때문에 정의되어 있는지 확인합니다 (와 함께 사용되는 경우 제외 typeof)

따라서 exports존재하는 경우 Node.js (또는 잘못 작성된 WebSite ...)의 경우 루트는를 가리키고 exports그렇지 않으면를 가리 킵니다 this. 그래서 무엇 this입니까?

(function() {...}).call(this);

.call함수를 사용 하면 함수 this내부를 전달 된 첫 번째 매개 변수에 바인딩합니다 . 브라우저 this가 이제 window객체가되는 경우 Node.js의 경우 전역 컨텍스트global객체 로도 사용할 수 있습니다 .

그러나 requireNode.js에 함수 가 있으므로 Node.js의 global객체에 무언가를 할당 할 필요가 없으며 대신 객체에 할당 exports한 다음 require함수에 의해 반환됩니다 .

커피 스크립트

모든 설명을 마친 후에는 다음을 수행해야합니다.

root = exports ? this
root.foo = -> 'Hello World'

foo전역 네임 스페이스에서 함수 를 선언합니다 .
그게 다야 :)


1
@IvoWetzel - 사이의 차이는 무엇인가 global, GLOBAL그리고 rootNode.js를에있는 개체는?
Aadit M Shah

1
자바 스크립트에 존재하지 않는 변수가 그렇지 않으면이 구문 에러 얻을 것이다 참조하려고 할 일이 의미하는 것은 ReferenceError?
alex

12
또는 더 짧은 :(exports ? this).foo = -> 'Hello World'
데인 오코너

3
this.foo는 종종! = window.foo이지만 'this'컨텍스트라면 이미 객체입니다. 이것은 혼란스러운 구문입니다.
케빈

1
사용하는 것에 동의합니다 global = exports ? this. "Node.js의 경우 전역 컨텍스트 일 ​​것입니다 ..."라는 주장은 잘못 this되었거나 node.js에 의해 실행될 때 변수가 모듈 범위로 평가 되기 때문에 잘못되었습니다 . 따라서 소품을 설정하면 전 세계에 액세스 할 수있게 될 것입니다. 실망 할 것입니다. 경우 당신은 Node.js를 맥락에서 세계적으로 설정된 것에 싶어, 당신은 사용할 필요 global가 아닌, 변수를 this.
KFL

58

나에게 @atomicules가 가장 간단한 답변을 가지고있는 것처럼 보이지만 조금 더 단순화 할 수 있다고 생각합니다. 전역 객체로 @컴파일 this.anything하고 this참조 할 수 있도록 전역에 원하는 것을 앞에 배치해야 합니다.

그래서...

@bawbag = (x, y) ->
    z = (x * y)

bawbag(5, 10)

컴파일 ...

this.bawbag = function(x, y) {
  var z;
  return z = x * y;
};
bawbag(5, 10);

node.js가 제공하는 래퍼 내부와 외부에서 작동합니다.

(function() {
    this.bawbag = function(x, y) {
      var z;
      return z = x * y;
    };
    console.log(bawbag(5,13)) // works here
}).call(this);

console.log(bawbag(5,11)) // works here

7
그러나 이미 다른 범위 내에 있다면 작동하지 않습니까? this더 이상 전역 객체를 참조하지 않기 때문에
Sherwin Yu

1
맞습니다. 따라서 적절한 범위에서 변수를 정의하고 다른 변수에서 사용할 수 window.myVariable있습니다.
Billy Moon

2
당신은 사용하는 또 다른 변수를 정의 할 필요가 없습니다 =>대신에 ->지시합니다는이 / 전역 네임 스페이스 아래에있는 함수를 만드는 커피 스크립트
리카르도 Villamil에게

2
이 지금은 별도의 커피 스크립트에서 전역 개체 및 함수를 만들 수 있으므로 도움이되었다
디에고 페르난도 무리 요 Valenci

이것은 훨씬 낫습니다. JS를 CS로
옮기

33

Ivo가 그것을 못 박았지만 스타일 포인트를 사용하려는 경우 권장하지는 않지만 사용할 수있는 더러운 트릭이 하나 있다고 언급합니다. 백틱으로 이스케이프 처리하여 CoffeeScript에 JavaScript 코드를 직접 포함시킬 수 있습니다.

그러나 이것이 일반적으로 나쁜 생각 인 이유는 다음과 같습니다. CoffeeScript 컴파일러는 이러한 변수를 인식하지 못하므로 일반적인 CoffeeScript 범위 지정 규칙을 따르지 않습니다. 그래서,

`foo = 'bar'`
foo = 'something else'

컴파일

foo = 'bar';
var foo = 'something else';

그리고 지금 당신은 foo서로 다른 범위에서 두 가지를 가지고 있습니다. Ivy가 설명했듯이 전역 객체를 참조하지 않고 CoffeeScript 코드 에서 전역 을 수정하는 방법은 없습니다 foo.

물론 이것은 fooCoffeeScript에서 할당을 한 경우에만 문제가됩니다. foo초기 값을받은 후 읽기 전용이 된 경우 (예 : 전역 상수) 내장 JavaScript 솔루션 접근 방식이 다소 수용 가능할 수 있습니다 (여전히 그래도 권장하지 않음).


1
CoffeeScript와 함께 티타늄을 사용하고 있기 때문에 이것은 유용한 솔루션이었습니다. 내보내기 및 창 개체가 존재하지 않습니다.
Pier-Olivier Thibault가

실제로 이것은 호이 스팅으로 foo인해 하나의 로컬 변수 일뿐 입니다 var(JS는 모든 var선언을 미리 스캔 하여 함수의 최상위에있는 것으로 해석합니다)
Kornel

@porneL 당신이 맞습니다; 나는 나쁜 예를 골랐다. 요점은 CoffeeScript 컴파일러가 역틱 이스케이프 된 JavaScript에 대한 분석을 수행하지 않기 때문에 이상한 결과를 얻을 수 있다는 것입니다.
Trevor Burnham

2
@ Pier-OlivierThibault 티타늄에서 Globals를 사용하려면 Ti.App.myGlobalVar = "ImAGlobalVar"를 사용할 수 있으며 백틱이 필요하지 않습니다.
Jakob Lnr

이것이 Node.js에 대한 정답입니다. 일을 expect = require('chai').expect;만든다 expect내 모든 테스트 파일에서 변수 사용 가능!
pocesar

11

node.js에서 coffee-script를 통해 코드를 컴파일 할 때 -b 옵션을 전달할 수 있습니다. 컴파일 된 코드는 coffeescript.org와 동일합니다.


어떻게? -b 옵션을 어디에 두어야합니까?
Harry

1
@Harry- -b/ --barecoffee명령 직후에 간다 .
ocodo

9

Ivo Wetzel의 답변에 추가하려면

Google 그룹 게시물exports ? this 에서만 문서화 / 언급 된 것을 찾을 수 있는 짧은 구문이있는 것 같습니다 .

즉, 웹 페이지에서 함수를 전역 적으로 사용 가능하게하려면 @접두어로 함수를 다시 선언하십시오 .

<script type="text/coffeescript">
    @aglobalfunction = aglobalfunction = () ->
         alert "Hello!"
</script>

<a href="javascript:aglobalfunction()" >Click me!</a>

9
@aglobalfunction의 '@'은 단순히 'this.'로 바뀌므로 'this.aglobalfunction'으로 컴파일됩니다. 이것은 coffeescript 래퍼 함수 (적용된 경우)의 범위가 전체 범위이기 때문에 작동합니다.
Chris

9

나는 당신이 달성하려고하는 것을 다음과 같이 간단하게 수행 할 수 있다고 생각합니다.

커피 스크립트를 컴파일하는 동안 "-b"매개 변수를 사용하십시오.

-b/ --bare 최상위 함수 안전 래퍼없이 JavaScript를 컴파일하십시오.

그래서 이런 식으로 뭔가 : coffee -b --compile somefile.coffee whatever.js

이것은 CoffeeScript.org 사이트에서와 같이 코드를 출력합니다.


7

당신이 나쁜 사람이라면 (나는 나쁜 사람입니다.), 당신은 다음과 같이 간단하게 얻을 수 있습니다 : (->@)()

에서처럼

(->@)().im_a_terrible_programmer = yes
console.log im_a_terrible_programmer

이것은 일반적으로 '함수 호출 패턴 (function-call invocation pattern)'이라고 Reference하는 Function'베어'(즉, 또는 func()대신 )를 호출 할 때 항상 해당 실행 컨텍스트 의 전역 객체에 바인딩 되기 때문에 작동합니다 .new func()obj.func()this

위의 CoffeeScript는 단순히 다음과 같이 컴파일됩니다 (function(){ return this })(). 글로벌 객체에 안정적으로 액세스하기 위해 이러한 동작을 수행하고 있습니다.


훌륭합니다!
metalim

나를 위해 일한 유일한 것. CoffeeScript를 싫어하십시오.
pcv

CoffeeScript를 사랑하십시오. 지금까지는 최고의 프로그래밍 언어입니다. 그것은 취미 프로젝트로 만들어 져서 유지되어 사용 패턴에 혼란과 어리 석음이 생겼습니다.
metalim

3

coffeescript는 자체적으로 거의 사용되지 않으므로 globalnode.js 또는 browserify (그리고 coffeeify, gulp 빌드 스크립트 등과 같은 하위 항목)에서 제공 하는 변수 를 사용할 수 있습니다 .

node.js global에서 전역 네임 스페이스입니다.

browserify에서 global동일하다 window.

그래서 그냥:

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