對比 react 和 vue 的 template expression
react 這邊比較簡單,是純粹的js,看編譯後的結果即可:

無論是作用域還是語法,都是常規js。
Babel · The compiler for next generation JavaScript
vue那邊好像會複雜一點。雖然vue聲稱支援 the full power of JavaScript expressions
,但它編譯後的結果並不是像react那樣的直接。 沒法直接看清楚它的作用域範圍是如何的,具體的原理隱藏在編譯過程中了,沒細看原始碼。google了一圈,也沒搜到什麼討論。

<h1>{{ [msg, this.msg, window.msg, Math.abs(msg), someFn(msg), encodeURIComponent(msg), console.log(msg)] | filter1 | filter2}}</h1>
這樣一個語句,編譯後的結果是
_c("h1", [ _vm._v( _vm._s( _vm._f("filter2")( _vm._f("filter1")([ _vm.msg, this.msg, _vm.window.msg, Math.abs(_vm.msg), _vm.someFn(_vm.msg), encodeURIComponent(_vm.msg), _vm.console.log(_vm.msg) ]) ) ) ) ]),
也就是說,vue對於表示式這裡的內容是做了語法分析的,這個語法分析我覺得主要是作用域(scope)方面的改動。
vue的文件有這麼一句:
Template expressions are sandboxed and only have access to a whitelist of globals such as Math
and Date
. You should not attempt to access user defined globals in template expressions.
vue會幫不在白名單中的變數加上 vm 自身作為作用域。我之前還以為vue這塊的作用域是通過 with
操作符做到的,不過with的效率據說是不高的。之前我在 ejs 這個模板語言裡面看到的,就是通過 with 來自動查詢本地作用域: https:// github.com/tj/ejs/blob/ master/lib/ejs.js
但文件中所說的 sandboxed 並沒有看到什麼體現。 我以為會是類似 node.js 的vm這種api, Node.js v11.7.0 Documentation ,不過如果引入了vm這樣的隔離性,帶來的問題說不定比解決的更多。