Javascript 如何使用代理查看变量是否(不再)未定义
请原谅我的错误。。。 在全局变量阶段不再未定义之后,我尝试使用代理来执行一些代码。以下是我天真的尝试: ```Javascript 如何使用代理查看变量是否(不再)未定义,javascript,ecmascript-6,es6-proxy,Javascript,Ecmascript 6,Es6 Proxy,请原谅我的错误。。。 在全局变量阶段不再未定义之后,我尝试使用代理来执行一些代码。以下是我天真的尝试: ``` var阶段=未定义 让myObj; 设st={ 阶段:阶段,, } 设lr={ 获取:函数(对象:任意,属性:任意):LightRay{ myObj=newsomeobjthatneedstage(obj[prop])//更新的答案 您说过您无法控制阶段的设置方式 监视更改是一个反模式和代码维护的噩梦。寻找任何其他可以的解决方案,例如使一个模块依赖于另一个模块,以便在模块运行之前知道
var阶段=未定义
让myObj;
设st={
阶段:阶段,,
}
设lr={
获取:函数(对象:任意,属性:任意):LightRay{
myObj=newsomeobjthatneedstage(obj[prop])//更新的答案
您说过您无法控制阶段的设置方式
监视更改是一个反模式和代码维护的噩梦。寻找任何其他可以的解决方案,例如使一个模块依赖于另一个模块,以便在模块运行之前知道它已加载
但是,你说过没有其他办法,所以:
您不能为此使用代理,因为为了使其有效,代码设置stage
必须通过代理进行设置,而不是直接进行设置
您说过您不控制如何声明stage
。这意味着您不能为此使用Object.defineProperty
,因为var
创建的全局对象上的属性具有可配置:false
如果在你的模块和你正在做的阶段
之间绝对没有办法取得协调,你将不得不求助于计时器循环。这不是一个好主意,但可能是你唯一的实际选择:
var stop = Date.now() + 30000;
var timer = setInterval(function() {
if (typeof stage !== "undefined" || Date.now() > stop) {
clearInterval(timer);
timer = 0;
// Your code here, if `stage` is still undefined, you hit the timeout
}
}, 50); // 50ms interval or whatever you need
原始答案
到目前为止这里最好的解决方案是:不要这样做。相反,使用带有setter的对象:
var stuff = {
_stage: undefined,
get stage() {
return _stage;
},
set stage(value) {
if (_stage === undefined && value !== undefined) {
_stage = value;
// Trigger your code here
}
}
};
然后让另一个代码做这个设置。如果你真的需要观察stage
被其他东西定义时的变化,并且stage
是全局的,那么简单的解决方案是使用旧的good getter:
let myObj;
Object.defineProperty(window, 'stage1', {
set (value) {
myObj = new SomeObjThatNeedsStage(stage)
return value
}
})
在上面的例子中,确保你没有var stage=undefined
你不再需要它了。这听起来像是一个问题。你为什么认为你想写代码来监视全局变量的值发生变化?应该定义什么stage
变量?仅供参考:监视变化是一种反模式和代码维护噩梦。寻找任何其他解决方案,比如让一个模块依赖于另一个模块,以便在模块运行之前知道它已加载。是的,我知道这是一个坏主意,但我必须处理它,因为Adobe Animate CC导出Create.js代码和Create.js的奇怪方式令人烦恼地没有发出('ready'))事件,该事件将告诉我该阶段已启动并正在运行。这不在我的控制范围内。“在这种情况下,我如何使用代理?”-您不能。我们可以使用对象。defineProperty
用于此目的?@zabusa:是的,但不能保证使用主机提供的对象。(也就是说:它可能与窗口
/全局对象一起工作。)是的,Windows/document和getter从未出现过问题。@dfsq:很好。浏览器在过去几年中在使其主机提供的对象与JS兼容方面做得非常好。啊,对不起,我的回答很匆忙。没有对更新的版本给予足够的关注。我很抱歉。只是仔细看看你的回答。本质上是sa我,你的还有一个额外的好处,就是定时器超时时间太长了,所以我撤销了我的答案。你的答案肯定更好。干杯……提供的defineProperty
可以在全局对象上工作,在浏览器上是主机提供的;主机提供的对象不一定要支持它。另外:set
不应该eturn该值,您可能需要一个get
。无法工作。setter从未被调用。顺便说一句,是的,stage是全局的,我无法控制它。您提供的代码是从UMD模块执行的。我正在使用typescript(向下传输到es5)。Object.defineProperty()在我的浏览器中可用。