我在HTML中的脚本标记中初始化了一些全局变量:
<script>
count = 0;
window.count2 = 0;
var count3 = 0;
</script>
在app.js
中,我订阅观察他们的更改:
let subscription = bindingEngine.propertyObserver(window, 'count')
.subscribe((newValue, oldValue) => console.log('Global count: ', newValue, oldValue));
let subscription2 = bindingEngine.propertyObserver(window, 'count2')
.subscribe((newValue, oldValue) => console.log('window.count2: ', newValue, oldValue));
let subscription3 = bindingEngine.propertyObserver(window, 'count3')
.subscribe((newValue, oldValue) => console.log('Global count3: ', newValue, oldValue));
然后我改变这样的值:
change() {
count++;
count2++;
count3++;
}
仅限count
&amp;&amp; count2
在控制台中被观察到:
Global count: 1 0
window.count2: 1 0
这是GistRun
问题:为什么count3
无法被观察到?我认为3种形式的初始化是等价的。
答案 0 :(得分:6)
我玩弄你的例子,弄清楚出了什么问题。然后我做了一些研究并学习了为什么。
所以,问题是你定义一个全局变量的三种方式实际上是不等价(Difference between variable declaration syntaxes in Javascript (including global variables)?)。关键是无法从窗口对象中删除使用var
声明的全局变量。这很重要。
你知道,如果可能的话,Aurelia并没有使用脏检查。当告诉它观察对象的属性时,它会将该属性包装在SetterObserver
对象中,该对象允许Aurelia知道属性的值何时被更改。这样可以避免脏检查,而无需更改设置属性值的方式。
因此,Aurelia用包装器替换您创建的属性。它通过使用Reflect.defineProperty
方法完成此操作。这是一个内置的API(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty)。但请记住,全局变量无法从窗口对象中删除。这也意味着Reflect.defineProperty
无法重新定义该属性。
最后,这意味着它是浏览器自身API的限制。
有一点需要注意,这只适用于严格模式(Aurelia运行)。我已经创建了一个显示此here的要点。如果删除&#34;使用严格&#34;在线,浏览器可以让你做任何你想做的事情并且它可以工作,但是在严格模式下它会抛出一个错误。