使用Aurelia进行全局变量订阅

时间:2016-05-04 11:21:03

标签: javascript aurelia aurelia-binding

我在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种形式的初始化是等价的。

1 个答案:

答案 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;在线,浏览器可以让你做任何你想做的事情并且它可以工作,但是在严格模式下它会抛出一个错误。