كيف يمكنني تحديد المتغيرات العالمية في Coffescript؟

StackOverflow https://stackoverflow.com/questions/4214731

  •  26-09-2019
  •  | 
  •  

سؤال

على Coffescript.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 يلف ذلك:

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

تقول المستندات:

إذا كنت ترغب في إنشاء متغيرات من المستوى الأعلى لاستخدام البرامج النصية الأخرى ، أو إرفاقها كخصائص على النافذة ، أو على كائن التصدير في CommonJs. يمنحك المشغل الوجودي (المغطى أدناه) طريقة موثوقة لمعرفة مكان إضافتها ، إذا كنت تستهدف كل من CommonJs والمتصفح: الجذر = الصادرات؟ هذه

كيف يمكنني تحديد المتغيرات العالمية ثم في القهوة. ماذا يعني "إرفاقها كخصائص على النافذة"؟

هل كانت مفيدة؟

المحلول

منذ أن لم يكن للنص القهوة var البيان يقوم تلقائيًا بإدراجها لجميع المتغيرات في نص القهوة ، وبهذه الطريقة ، يمنع إصدار JavaScript المترجم من تسرب كل شيء إلى مساحة الاسم العالمية.

لذلك نظرًا لعدم وجود طريقة لجعل شيئًا "تسرب" في مساحة الاسم العالمية من الجانب المصمم من القهوة من الأشياء عن قصد ، تحتاج إلى تحديد متغيراتك العالمية كخصائص كائن عالمي.

إرفاقها كخصائص على النافذة

هذا يعني أنك بحاجة إلى القيام بشيء مثل window.foo = 'baz';, ، الذي يتعامل مع قضية المتصفح ، لأن هناك كائن عالمي هل window.

node.js

في node.js لا يوجد window كائن ، بدلاً من ذلك exports الكائن الذي يتم تمريره في الغلاف الذي يلف وحدة Node.js (انظر: https://github.com/ry/node/blob/master/src/node.js#l321 ) ، لذلك في node.js ما عليك القيام به هو exports.foo = 'baz';.

الآن دعونا نلقي نظرة على ما ينص عليه في اقتباسك من المستندات:

... استهداف كل من commonjs والمتصفح: الجذر = الصادرات؟ هذه

من الواضح أن هذا نص قهوة ، لذلك دعونا نلقي نظرة على ما يجمعه هذا بالفعل:

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

أولاً سوف تحقق ما إذا كان exports تم تعريفه ، نظرًا لأن محاولة الرجوع إلى متغير غير موجود في JavaScript من شأنه أن ينتج عن بناء جملة (باستثناء عند استخدامه مع typeof)

حتى إذا exports موجود ، وهذا هو الحال في node.js (أو في موقع ويب مكتوب بشكل سيء ...) سوف يشير الجذر إلى exports, ، وإلا ل this. اذا، ماذا this?

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

استخدام .call على الوظيفة سوف يربط this داخل الوظيفة إلى المعلمة الأولى التي تم تمريرها ، في حالة المتصفح this سيكون الآن window كائن ، في حالة node.js سيكون السياق العالمي وهو متاح أيضًا مثل global هدف.

ولكن بما أن لديك require وظيفة في node.js ، ليست هناك حاجة لتعيين شيء إلى global كائن في node.js ، بدلاً من ذلك يمكنك تعيينه إلى exports الكائن الذي يتم إرجاعه بعد ذلك بواسطة require وظيفة.

صرف القهوة

بعد كل هذا التفسير ، إليك ما عليك القيام به:

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

هذا سوف يعلن وظيفتنا foo في مساحة الاسم العالمية (مهما كان ذلك).
هذا كل شئ :)

نصائح أخرى

بالنسبة لي ، يبدو أن 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

قامت IVO بتسميرها ، لكنني سأذكر أن هناك خدعة متسخة يمكنك استخدامها ، على الرغم من أنني لا أوصي بها إذا كنت ستذهب للحصول على نقاط النمط: يمكنك تضمين رمز JavaScript مباشرة في Coffescript الخاص بك عن طريق الهروب من ذلك باستخدام Backticks.

ومع ذلك ، هذا هو السبب في أن هذه عادة ما تكون فكرة سيئة: لم يكن برنامج التحويل البرمجي Coffescript غير مدرك لتلك المتغيرات ، مما يعني أنها لن تطيع قواعد تحديد النطاق القهوة العادية. لذا،

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

يجمع

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

والآن لديك نفسك اثنان fooS في نطاقات مختلفة. لا توجد طريقة لتعديل عالمي foo من رمز Coffescript دون الرجوع إلى الكائن العالمي ، كما وصف Ivy.

بالطبع ، هذه ليست سوى مشكلة إذا قمت بإجراء مهمة foo في Coffescript - إذا foo أصبحت القراءة فقط بعد إعطائها قيمتها الأولية (أي أنها ثابتة عالمية) ، ثم قد يكون نهج حل JavaScript المضمن مقبول نوعًا ما (على الرغم من أنه لا يزال غير موصى به).

يمكنك تمرير خيار -B عند تجميع الرمز عبر Coffee -Scriper ضمن Node.js. سيكون الرمز المترجم هو نفسه كما في Coffescript.org.

إضافة إلى إجابة إيفو ويتزل

يبدو أن هناك بناء جملة مختصرة ل exports ? this أنه لا يمكنني إلا أن أجد موثقة/مذكورة على أ نشر مجموعة Google.

IE في صفحة ويب لإتاحة وظيفة على مستوى العالم ، تعلن الوظيفة مرة أخرى باستخدام @ اختصار:

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

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

أعتقد أن ما تحاول تحقيقه يمكن القيام به مثل هذا:

أثناء تجميع Coffescript ، استخدم المعلمة "-b".

-b / --bare قم بتجميع JavaScript بدون غلاف أمان الوظيفة العليا.

لذلك شيء من هذا القبيل: coffee -b --compile somefile.coffee whatever.js

سيؤدي هذا إلى إخراج الكود الخاص بك كما هو الحال في موقع Coffescript.org.

إذا كنت شخصًا سيئًا (أنا شخص سيء.) ، فيمكنك الحصول على بسيط مثل هذا: (->@)()

كما في ،

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

هذا يعمل ، لأنه عند استدعاء أ Reference إلى Function "عارية" (هذا ، func(), ، بدلاً من new func() أو obj.func()) ، شيء يشار إليه عادة باسم "نمط استدعاء الوظيفة" ، دائماً يربط this للكائن العالمي لذلك سياق التنفيذ.

يجمع القهوة أعلاه ببساطة إلى (function(){ return this })(); ؛ لذلك نحن نمارس هذا السلوك للوصول إلى الكائن العالمي بشكل موثوق.

نظرًا لأن Coffescript نادرًا ما يتم استخدامه بمفرده ، يمكنك استخدامه global المتغير الذي توفره إما node.js أو المتصفح (وأي نسل مثل Coffeefy و Gulp Build Scripts ، إلخ).

في node.js global هي مساحة الاسم العالمية.

في المتصفح global يساوي window.

اذن فقط:

somefunc = ->
  global.variable = 123
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top