ClojureScript:JS-Objects中的数据共享

时间:2016-04-03 09:12:33

标签: clojurescript

在使用clj->js命令转换ClojureScript中的列表后,我对共享实例有疑问。

我有以下代码:

(def list '(1 (5 6 7) 3 4 5))

(def jslist1 (clj->js (pop list)))
(def jslist2 (clj->js (pop list)))
(.log js/console "js:")
(.log js/console (= (get jslist1 0) (get jslist2 0)))

(def cljlist1 (pop list))
(def cljlist2 (pop list))
(.log js/console "clj:")
(.log js/console (= (get cljlist1 0) (get cljlist2 0)))

如果我运行此代码,我会得到控制台输出:

js:
false
clj:
true

我原以为,JS对象也引用了(5 6 7)数组的同一个实例。相反,它似乎创造了一个新的。有谁知道,为什么这个行为与clj列表不同?

2 个答案:

答案 0 :(得分:0)

我假设在Clojure世界中这两个列表是相等的,因为这两个变量保存对内存中同一对象的引用。 Pop返回对同一对象的引用。

在Javascript世界中,这两个列表成为数组,即对象,并通过Javascript规则进行比较。两个对象,即使它们包含相同的值,也不相等,因为它们是两个不同的引用,内存中有两个不同的位。

答案 1 :(得分:0)

如果查看clj->js的来源,您会看到适用于集合的代码:

(coll? x) (let [arr (array)]
            (doseq [x (map clj->js x)]
              (.push arr x))
            arr)

创建 JS array,并将集合的全部内容复制到JS数组 - 每次 clj->js为调用。

据推测,该数组是一个防御性副本,可以防止原始的ClojureScript列表及其内容被修改。