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种形式的初始化是等价的.
我玩弄了你的例子,弄清楚出了什么问题.然后我做了一些研究并了解了原因.
那么,问题是你定义一个全局变量的三种方式实际上并不等效(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"行,浏览器会让你做任何你想做的事情并且它可以工作,但是在严格模式下它会抛出一个错误.