سؤال

عند استخدام ClojureScript حاولت تعريف دالة تكون بمثابة إغلاق لمتغير مثل هذا:

(let [x 42] 
  (defn foo [n] (+ x n)))

يقوم بطباعة المصدر التالي في Rhino REPL:

function foo(n){
  return cljs.core._PLUS_.call(null,x__43,n);
}

تعمل الوظيفة كما أتوقع ولكن عند محاولة الوصول إلى المتغير المسمى x__43 لا أستطيع الحصول عليه.اين ذهبت؟

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

المحلول

(let [x 42]
  (defn foo [n] (+ x n)))

يتم تجميعها حاليا ل

var x__1311 = 42;

cljs.user.foo = (function foo(n){
return (x__1311 + n);
});

الرقم الدقيق المرفق x قد تختلف بالطبع من تجميع إلى تجميع و cljs.user سيتم استبداله باسم مساحة الاسم المناسب.

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

لاكتشاف أشياء مثل ما سبق، يمكنك إما استدعاء المترجم باستخدام {:optimizations :simple :pretty-print true} من بين الخيارات أو اطلب منه إصدار بعض JavaScript في ملف REPL (كما هو منصوص عليه في script/repl في شجرة المصدر ClojureScript أو lein repl في مشروع Leiningen مع إعلان ClojureScript باعتباره تبعية):

(require '[cljs.compiler :as comp])

(binding [comp/*cljs-ns* 'cljs.user]
  (comp/emit
   (comp/analyze {:ns {:name 'cljs.user} :context :statement :locals {}}
                 '(let [x 42] (defn foo [n] (+ x n))))))

نصائح أخرى

يتم تعريف المتغير x خارج الدالة foo، في الرابط Let.لا يمكنك "الحصول عليه" لأنك لست ضمن نطاق السماح بالربط.هذا هو الهدف الأساسي من استخدام عمليات الإغلاق.

من الناحية النظرية، دع الارتباطات يتم تنفيذها كاستدعاءات دالة:

(let [x 2] ...)

يعادل

((fn [x] ...) 2)

الذي من المحتمل مشابه ل let يتم تنفيذه في ClojureScript - إما كتحويل ماكرو إلى fn أو مباشرة إلى (function(x){...})(2).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top