簡體   English   中英

將JavaScript對象轉換為ClojureScript:Getter和Setter屬性

[英]Convert JavaScript Object to ClojureScript: Getter and Setter Properites

我正在努力解決以下問題:

通常,JS對象通過js-> clj轉換為ClojureScript。 這適用於原型對象的對象。 對於其他的我正在使用:

(defn jsx->clj [o]
  (reduce (fn [m v] (assoc m (keyword v) (aget o v)))  {} (.keys js/Object o)))

我發現,這些“屬性”是幕后的吸氣功能,無法通過這些操作進行轉換。

有人對此有任何經驗嗎?

我不確定當您說“幕后的getter函數無法通過這些操作轉換”時的意思。

問題之一是,當您將JS對象這樣轉換為CLJS映射時,getter和setter不會綁定到原始JS對象,因此它們將無法訪問此對象的屬性。

考慮以下代碼:

;; This is your function, no changes here.
(defn jsx->clj [o]
  (reduce (fn [m v] (assoc m (keyword v) (aget o v)))  {} (.keys js/Object o)))


;; This is an improved version that would handle JS functions that
;; are properties of 'o' in a specific way - by binding them to the
;; 'o' before assoc'ing to the result map.
(defn jsx->clj2 [o]
  (reduce (fn [m v]
            (let [val (aget o v)]
              (if (= "function" (goog/typeOf val))
                (assoc m (keyword v) (.bind val o))
                (assoc m (keyword v) val))))
          {} (.keys js/Object o)))

;; We create two JS objects, identical but distinct. Then we convert
;; both to CLJS, once using your function, and once using the improved
;; one.
;; Then we print results of accessing getter using different methods.
(let [construct-js (fn [] (js* "new (function() { var privProp = 5; this.pubProp = 9; this.getter = function(x) { return privProp + this.pubProp + x; }; })"))
      js-1 (construct-js)
      js-2 (construct-js)
      clj-1 (jsx->clj js-1)
      clj-2 (jsx->clj2 js-2)]
  (.log js/console "CLJS objects: " (.getter js-1 10) ((:getter clj-1) 10) (.getter js-2 10) ((:getter clj-2) 10)))

打印:

CLJS objects:  24 NaN 24 24

這意味着以下代碼: ((:getter clj-1) 10)失敗,而((:getter clj-2) 10)工作。 第二個有效,因為.bind()已用於將函數與JS對象正確綁定。

如果確實為您帶來了問題,那么此問題等同於有時在JS中執行的以下錯誤:

var Constructor = function() {
  var privProp = 5;
  this.pubProp = 9;
  this.getter = function(x) {
    return privProp + this.pubProp + x;
  };
}
var obj1 = new Constructor();
var obj2 = new Constructor();
var fn1 = obj1.getter;             // Invalid, fn1 will not be bound to obj1.
var fn2 = obj2.getter.bind(obj2);  // Note .bind here.
console.log(fn1(10), fn2(10));

打印類似的輸出:

NaN 24

同樣,尚未綁定到obj1 fn1返回無效輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM