目前无法告诉分析器/编译器直接调用函数,即使我们知道某物只能是函数,并且永远不会是 IFn/可变参数/多态函数。
(ns test.invoke)
(defn call-me [some-fn arg]
(some-fn arg))
(call-me #(js/console.log %) "foo")
产生
test.invoke.call_me = (function test$invoke$call_me(some_fn,arg){
return (some_fn.cljs$core$IFn$_invoke$arity$1 ? some_fn.cljs$core$IFn$_invoke$arity$1(arg) : some_fn.call(null,arg));
});
test.invoke.call_me((function (p1__91346_SHARP_){
return console.log(p1__91346_SHARP_);
}),"foo");
如您所见,总是有 {{some_fn.cljs$core$IFn$_invoke$arity$1}} 属性测试,这总是会失败并通过 {{.call}} 运行。这对于可能接受 {{cljs.core/IFn}} 实现的东是合理的,但有很多情况只会接收普通的函数(例如,JS 交互),应该能够通过某种注解告诉编译器,使其能够生成更优化的 {{some_fn(arg)}} 代码。{{:advanced}} 编译也不会处理这个问题。
我在这里创建了一个基准测试套件,它表明 prop/call 样式调用始终慢 30-40%,我想在一些罕见的情况下进行优化。
请参阅:
https://jsbench.me/2qjugq4795/1
我们可以通过已经存在的 {{^js}} 注解来处理这个问题,或者创建一个新的像 {{^fn}}。
(defn call-me [^js some-fn arg]
(some-fn arg))
;; and/or
(defn call-me [^fn some-fn arg]
(some-fn arg))
(defn call-me [some-fn arg]
^fn (some-fn arg))
这是一种与 {{^not-native}} 提供的类似优化,应谨慎且少量使用。