使用Aurelia进行全局变量订阅

qtu*_*uan 1 javascript aurelia aurelia-binding

我在HTML中的脚本标记中初始化了一些全局变量:

<script>
  count = 0;
  window.count2 = 0;
  var count3 = 0;
</script>
Run Code Online (Sandbox Code Playgroud)

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));  
Run Code Online (Sandbox Code Playgroud)

然后我改变这样的值:

change() {
    count++;
    count2++;
    count3++;
}
Run Code Online (Sandbox Code Playgroud)

只有count&& count2在控制台中被观察到:

Global count:  1 0
window.count2:  1 0
Run Code Online (Sandbox Code Playgroud)

这是GistRun

问题:为什么count3不能观察到?我认为3种形式的初始化是等价的.

Ash*_*ant 6

我玩弄了你的例子,弄清楚出了什么问题.然后我做了一些研究并了解了原因.

那么,问题是你定义一个全局变量的三种方式实际上并不等效(Javascript中的变量声明语法之间的差异(包括全局变量)?).关键是var无法从window对象中删除声明使用的全局变量.这个很重要.

你知道,如果可能的话,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运行).我已经创建了一个在这里展示这个的要点.如果删除"use strict"行,浏览器会让你做任何你想做的事情并且它可以工作,但是在严格模式下它会抛出一个错误.