Javascript:在对象闭包中使用访问器属性
我最近从阅读中学到了如何使用函数将对象组合在一起。接下来,我以以下代码结束:Javascript:在对象闭包中使用访问器属性,javascript,closures,Javascript,Closures,我最近从阅读中学到了如何使用函数将对象组合在一起。接下来,我以以下代码结束: function withFlying(o) { let _isFlying = false; return { ...o, fly () { _isFlying = true; }, land () { _isFlying = false; }, isFlying () { return _isFlying }
function withFlying(o) {
let _isFlying = false;
return {
...o,
fly () {
_isFlying = true;
},
land () {
_isFlying = false;
},
isFlying () {
return _isFlying
}
}
};
function withWalking(o) {
let isWalking = false;
return {
...o,
startWalking() {
isWalking = true;
return this
},
stopWalking() {
isWalking = false;
return this
},
isWalking: () => isWalking
}
}
const bird = withWalking(withFlying({}))
这里一切正常。但是,我希望能够将isFlying
作为属性而不是函数调用:
// current (working)
bird.isFlying() // return value of `_isFlying`
// desired
bird.isFlying // return value of `_isFlying`
我知道get
和set
是可以在对象文本中使用的关键字,因此我尝试了以下方法:
function withFlying(o) {
let _isFlying = false
return {
...
get isFlying () {
return _isFlying
}
}
}
但在使用其他函数更新后,它不会显示正确的值。我认为,如果get
属性是一个函数,那么闭包的应用与其他函数类似。我的假设错了吗?是否有我不理解的get
的潜在行为,以及我现在尝试实现的方式是否可能
以下是我尝试使用的代码片段:
飞行功能(o){
让_isFlying=false;
返回{
……哦,
飞(){
_isFlying=true;
},
土地(){
_isFlying=false;
},
_isFlying()的值{
回程飞行;
},
让我飞起来(){
返航
}
}
};
步行功能(o){
让我走=假;
返回{
……哦,
星际之旅{
isWalking=true;
还这个
},
停步{
isWalking=false;
还这个
},
isWalking:()=>isWalking
}
}
const bird=withWalking(withFlying({}))
//渴望的
console.log(bird.isFlying)/\u isFlying启动错误
bird.fly()//应将_isFlying设置为true
console.log(bird.isFlying)//仍然返回false
console.log(bird.valueOf_isFlying())//显示_isFlying为真
问题在于,当您创建新对象时,您正在使用排列符号从原始对象复制属性:
return {
...o,
// ...
};
问题是它复制了访问器属性的当前值,而不是访问器属性的定义。你可以在这里看到:
const obj1={
获取示例(){
返回42;
}
};
log(“注意,属性描述符用于访问器属性:”);
log(Object.getOwnPropertyDescriptor(obj1,“示例”);
常量obj2={…obj1};
log(“注意,属性描述符用于一个简单的数据属性:”);
log(Object.getOwnPropertyDescriptor(obj2,“示例”)代码>
。作为控制台包装器{
最大高度:100%!重要;
}
有更新的很好!是的,这是一种不明显的行为,可能也会让其他人绊倒。您是否允许在copyAndUpdateObject
中进行多次更新,然后传入一个空对象作为第一个参数,以避免改变原始对象?也让它更一般?@LoganWaite-基本上。您使用spread的原始代码没有对原始对象进行变异,因此我继续使用它。循环也是为了通用性。如果希望避免在每个阶段创建新对象,只需在每次调用copyAndUpdateObject
(我刚刚意识到,它的名称已经过时了——最初,在发布答案之前,我让它创建了目标对象,然后决定我应该遵循object.assign
的示例;我将更改名称)。例如,如果你想改变对象,请返回assignPropertyDescriptors(o,{/*…*/};