CoffeeScript'te global değişkenleri nasıl tanımlarım?


317

Coffeescript.org sitesinde:

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

bawbag(5, 10) 

derlemek:

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

node.js altında kahve-betiği ile derlemek şöyle:

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

Dokümanlar şunları söylüyor:

Diğer komut dosyalarının kullanması için üst düzey değişkenler oluşturmak istiyorsanız, bunları pencereye veya CommonJS'deki dışa aktarma nesnesine özellik olarak ekleyin. Varoluşçu operatör (aşağıda ele alınmıştır), hem CommonJS'yi hem de tarayıcıyı hedefliyorsanız, bunları nereye ekleyeceğinizi anlamanız için güvenilir bir yol sağlar: root = export? bu

Global Değişkenleri o zaman CoffeeScript'te nasıl tanımlarım. 'Bunları pencereye özellik olarak ekle' ne anlama geliyor?


4
Global değişkenleri kullanmanın kötü olduğunu, c2.com/cgi/wiki?GlobalVariablesAreBad ve hatta zararlı olarak kabul edildiğini unutmayın , c2.com/cgi/wiki?GotoConsideredHarmful . Ve bunları JavaScript'te kullanmak için hiçbir neden yoktur, çünkü küresel değişkenleri çözmek için kullandığınız çoğu sorunu çözebilecek kapaklar gibi harika özelliklere sahipsiniz.
Evgeny

9
@Evgeny Burada sizinle aynı fikirde olmakla birlikte, bazı durumlarda merkezi bir 'uygulama' nesnesi oluşturmak ve ona modüllerin bağlanması gerekir.
jackyalcine

1
merkezi nesneler, windownesne veya nesne gibi mevcut genel durum nesnelerine kaydedilebilir exports. global değişkenler oluşturmaya gerek yok.
Evgeny

9
@Evgeny global değişkenleri window(veya globalnodejs) nesnesinin özellikleri olarak kaydedilir
shesek

21
Evet, küresel bir varlığa sahip olmak kötü değil. Düşüncesizce onlarla uygulamanızı hortum için sadece kötü uygulama. Birini bildirmek ve bunu jQuery veya bir tür ad alanı gibi bir adaptör fabrikası olarak kullanmak gerçekten yaygın bir uygulamadır.
Erik Reppen

Yanıtlar:


419

Kahve betiğinin bir vardeyimi olmadığından , kahve betiğindeki tüm değişkenler için otomatik olarak ekler, böylece derlenmiş JavaScript sürümünün her şeyi genel ad alanına sızmasını önler .

Bu nedenle , amaçlanan şeylerin kahve komut dosyası tarafından küresel ad alanına "sızıntı" yapmanın bir yolu olmadığından , küresel değişkenlerinizi global nesnenin özellikleri olarak tanımlamanız gerekir .

pencerede özellikler olarak ekleyin

Bu window.foo = 'baz';, küresel nesne olduğu için tarayıcı durumunu işleyen gibi bir şey yapmanız gerektiği anlamına gelir window.

node.js

Node.js'de windownesne yok , bunun yerine exportsNode.js modülünü saran sarmalayıcıya aktarılan nesne var (Bkz: https://github.com/ry/node/blob/master/src/node.js# L321 ), bu nedenle Node.js'de yapmanız gereken şey exports.foo = 'baz';.

Şimdi, dokümanlardaki teklifinizde neyin belirtildiğine bir göz atalım:

... hem CommonJS'yi hem de tarayıcıyı hedefliyoruz: root = export? bu

Açıkçası kahve betiği, bu yüzden bunun gerçekte ne derlediğine bir göz atalım:

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

İlk olarak exports, tanımlanıp tanımlanmadığını kontrol edecektir , çünkü JavaScript'te var olmayan bir değişkene başvurmaya çalışmak başka türlü bir SyntaxError getirecektir (bununla birlikte kullanıldığı zamanlar hariç typeof)

Varsa exports, Node.js'de (veya kötü yazılmış bir Web Sitesinde ...) kökte olduğu gibi exports, aksi takdirde işaret eder this. Ne olmuş yani this?

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

.callBir fonksiyonun kullanılması , fonksiyonun thisiçinde geçen ilk parametreye bağlanır, tarayıcının thisşimdi windownesne olması durumunda, Node.js durumunda , nesne olarak da kullanılabilen global bağlam olacaktır global.

Ancak requireNode.js'de işleve sahip olduğunuz için , Node.js'de globalnesneye bir şey atamanıza gerek yoktur , bunun yerine işleve exportsgeri döndürülen nesneye atarsınız require.

Kahve-Senaryo

Tüm bu açıklamalardan sonra, yapmanız gerekenler:

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

Bu foo, global ad alanındaki işlevimizi ilan eder (ne olursa olsun).
Bu kadar :)


1
@IvoWetzel - arasındaki fark nedir global, GLOBALve rootnode.js nesnelerin?
Aadit M Shah

1
JavaScript'te var olmayan bir değişkene başvurmaya çalışmak başka türlü bir SyntaxError verir mi demek istemediniz ReferenceError?
alex

12
Veya daha da kısa:(exports ? this).foo = -> 'Hello World'
Dane O'Connor

3
this.foo sık sık! = window.foo 'eğer' siz iseniz bu içerik zaten bir nesnedir. Bu kafa karıştırıcı bir sözdizimidir.
Kevin

1
Kullanmaya katılırken global = exports ? this. "Node.js durumunda genel bağlam olur ..." iddiası yanlıştır, çünkü thisgerektiğinde veya node.js tarafından çalıştırılan değişken modül kapsamı olarak değerlendirilir. Bu nedenle, sahne ayarının küresel olarak erişilebilir olmasını bekliyorsanız hayal kırıklığına uğrayacaksınız. Eğer siz node.js bağlamda küresel set şeyler istiyorsun, kullanmak gerek globalziyade, değişken this.
KFL

58

Bana göre @atomicules en basit cevaba sahip, ama bence biraz daha basitleştirilebilir. @Küresel olmak istediğiniz herhangi bir şeyden önce bir nesneyi koymanız gerekir , böylece küresel nesneyi derler this.anythingve ona thiskarşılık gelir.

yani...

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

bawbag(5, 10)

derler ...

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

node.js tarafından verilen paketin içinde ve dışında çalışır

(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
Ama zaten başka bir kapsamın içindeyseniz bu işe yaramaz değil mi? Çünkü o zaman thisartık küresel nesneyi ifade etmiyor
Sherwin Yu

1
Bu doğrudur, bu nedenle değişkeninizi uygun bir kapsamda tanımlayabilir (ve başkalarında kullanabilirsiniz) veya window.myVariablehangisinin herhangi bir yerde çalışacağını tanımlayabilirsiniz .
Billy Moon

2
Başka bir değişken tanımlamanıza gerek yoktur, =>bunun yerine sadece ->bu / global ad alanı altında işlev yaratması için kahve tablasına talimat verir
Ricardo Villamil

2
Bu çok yardımcı oldu, şimdi ayrı bir kahve betiğinde küresel nesneler ve işlevler oluşturabilirim
Diego Fernando Murillo Valenci

Bu çok daha iyi.
JS'yi CS'ye aktarmak

33

Ivo çivilenmiş, ancak kullanabileceğiniz bir kirli hile olduğunu söyleyeceğim, ancak stil noktaları için gidiyorsanız bunu önermiyorum: JavaScript kodunu geri çekmelerden kaçarak doğrudan CoffeeScript'inize gömebilirsiniz.

Ancak, işte bu genellikle kötü bir fikirdir: CoffeeScript derleyicisi bu değişkenlerden habersizdir, bu da normal CoffeeScript kapsam belirleme kurallarına uymayacakları anlamına gelir. Yani,

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

derlemek

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

ve şimdi foofarklı kapsamlarda iki s var . Değiştirmek için bir yolu yoktur küresel foo Sarmaşık açıklandığı gibi küresel nesne başvuran olmadan CoffeeScript kodundan.

Tabii ki, bu sadece fooCoffeeScript'te bir atama yaparsanız bir sorundur - foobaşlangıç ​​değeri verildikten sonra salt okunur hale gelirse (yani küresel bir sabittir), gömülü JavaScript çözüm yaklaşımı biraz sorta kabul edilebilir (yine de tavsiye edilmez).


1
CoffeeScript ile Titanium kullandığım için bu benim için yararlı bir çözümdü. İhracat ve pencere nesnesi orada mevcut değildir.
Pier-Olivier Thibault

Aslında bu sadece bir yerel foodeğişken, varkaldırma nedeniyle (JS tüm varbeyanları tarar ve bunları işlevin tepesindeymiş gibi yorumlar)
Kornel

@porneL Haklısınız; Kötü bir örnek seçtim. Önemli olan, CoffeeScript derleyicisinin ters çentiklerden kaçan JavaScript analizi yapmamasıdır, böylece tek çıktı elde edebilirsiniz.
Trevor Burnham

2
@ Pier-OlivierThibault Global'leri Titanyum'da kullanmak istiyorsanız Ti.App.myGlobalVar = "ImAGlobalVar" kullanabilirsiniz ve backticks gerekmez
Jakob Lnr

en azından Node.js için doğru cevap budur. yapıyor değişken tüm test dosyalarımda kullanılabilir expect = require('chai').expect;hale getirir expect!
pocesar

11

Node.js altında kahve-betiği ile kod derlerken -b seçeneğini iletebilirsiniz. Derlenen kod, coffeescript.org'daki ile aynı olacaktır.


Nasıl? -B seçeneğini nereye koyabilirim?
Harry

1
@Harry - -b/ komuttan --barehemen sonra gider coffee.
ocodo

9

Ivo Wetzel'in cevabına eklemek için

exports ? thisSadece bir Google grubu yayınında belgelenmiş / sözü edilen bulabildiğim için kestirme bir sözdizimi var gibi görünüyor .

Yani web sayfasında bir işlevi global olarak kullanılabilir yapmak için işlevi bir @önekle tekrar bildirirsiniz:

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

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

9
@ Aglobalfunction içindeki '@' yerine 'this' yazılır, bu yüzden 'this.aglobalfunction' ile derlenir. Bu, kahve sarmalayıcı işlevinin kapsamı (uygulanmışsa) genel kapsam olduğu için çalışır.
Chris

9

Bence elde etmeye çalıştığınız şey şu şekilde yapılabilir:

Kahve tablasını derlerken "-b" parametresini kullanın.

-b/ --bare JavaScript'i en üst düzey işlev güvenlik sarmalayıcısı olmadan derleyin.

Yani böyle bir şey: coffee -b --compile somefile.coffee whatever.js

Bu, kodunuzu aynen CoffeeScript.org sitesindeki gibi verir.


7

Eğer kötü bir insansan (ben kötü bir insansım), bu kadar basit olabilirsin: (->@)()

De olduğu gibi,

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

Bu eserler, bir çağrılırken çünkü Referencebir etmek Function(olduğunu, 'çıplak' func()yerine new func()ya obj.func()), bir şey genellikle 'işlevi çağrı çağırma desen' olarak anılacaktır hep bağlar thisbunun için küresel nesneye yürütme içeriği .

Yukarıdaki CoffeeScript (function(){ return this })(); bu nedenle, global nesneye güvenilir bir şekilde erişmek için bu davranışı uyguluyoruz.


Bu harika!
metalim

Benim için işe yarayan tek şey. CoffeeScript'ten nefret ediyorum.
pcv

CoffeeScript'i seviyorum. Şimdiye kadar buradaki en iyi programlama dili. Çok kötü bir hobi projesi olarak yaratılmış ve sürdürülmüş, kullanım kalıplarında kaosa ve aptallığa yol açmıştır.
metalim

3

Coffeescript nadiren kendi başına kullanıldığından, globalnode.js veya browserify tarafından sağlanan değişkeni (ve coffeeify, gulp build komut dosyaları vb.)

Node.js'de globalgenel ad alanı vardır.

Browserify globaleşittir window.

Bu yüzden sadece:

somefunc = ->
  global.variable = 123
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.