Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:在对象闭包中使用访问器属性_Javascript_Closures - Fatal编程技术网

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,{/*…*/};