Javascript getter/setter 范围访问
Javascript getter/setter scope access
我正在尝试使用具有 classic 原型继承的 JS,而不是新的 ES6 class 模型,主要是为了能够访问闭包范围。
在下面的示例中,我想通过 new
运算符创建的 this
对象公开函数 Counter
中声明的变量 current
。
function Counter(start, stop) {
var current = start;
function inc() { if (current < stop) return current++ }
function getCurrent() { return current }
Object.assign(this, { inc, getCurrent,
get current() { return current }, set current(value) { current = value }
})
}
counter = new Counter(0, 3)
while ((v = counter.inc()) !== undefined)
console.log(counter.getCurrent(), counter.current)
我期望得到以下输出:
1 1
2 2
3 3
因为 counter.current
和 counter.getCurrent()
应该 return 相同的结果。但相反,我收到
1 0
2 0
3 0
如果我用下面的代码替换 Object.assign(...)
,它会按预期工作。
Object.assign(inc, getCurrent })
Object.defineProperty(Counter.prototype, 'current',
{ get: () => { return current }, set: (value) => { current = value }
我可以使用这个模型,(目前正在使用),但我想使用前者,因为它更简单,也不那么冗长。好像这里有2个不同的作用域。
我用节点 10、Chrome 73 和 Firefox 68 进行了测试,得到了相同的结果。
我在这里缺少什么?
在上面的示例中,我尽量做到简洁。但为了更准确和更好地说明这一点,请遵循更完整的测试,并附上我尝试过的一些评论。
在这里,我将变量 current
重命名为 _current
以避免与 current
属性 混淆,但这不是强制性的。
function Counter(start, stop) {
var _current = start;
function inc() { if (_current < stop) return _current++ }
function getCurrent() { return _current }
// Object.assign(this.constructor.prototype,
// Object.assign(this.__proto__,
// Object.assign(Counter.prototype, {
Object.assign(this, {inc, getCurrent,
get current() { return _current }, set current(value) { _current = value }
// get current() { return current } // supposed to be read-only, but not
})
// This works as expected
// Object.defineProperty(Counter.prototype, 'current',
// { get: () => { return _current }, set: (value) => { _current = value } })
}
counter = new Counter(0, 3)
while ((v = counter.inc()) !== undefined) {
console.log(counter.getCurrent(), counter.current)
counter.current -= 0.5
}
上面代码的输出是:
1 0
2 -0.5
3 -1
counter.current -= 0.5
在哪里存储它的值?
当您的代码调用 Object.assign()
时,它会传入一个对象,该对象具有 getter 和 setter 用于 current
。因此,在将 属性 值复制到新对象时,Object.assign()
进程本身将调用 getter 来获取 属性 "current" 的值。因此,计数器对象最终 没有 getter 和 setter,这解释了您的结果。它的 "counter" 属性 只是一个简单的 属性,带有构造函数代码 运行.[=16 时局部 counter
变量值的副本=]
Object.assign()
只是复制 属性 值,以与任何其他代码相同的方式访问它们。
请注意,如果您 根本不 调用 Object.assign()
,而只是 return 您传递给它的对象,您将得到一个像你期望的那样工作的对象。
我正在尝试使用具有 classic 原型继承的 JS,而不是新的 ES6 class 模型,主要是为了能够访问闭包范围。
在下面的示例中,我想通过 new
运算符创建的 this
对象公开函数 Counter
中声明的变量 current
。
function Counter(start, stop) {
var current = start;
function inc() { if (current < stop) return current++ }
function getCurrent() { return current }
Object.assign(this, { inc, getCurrent,
get current() { return current }, set current(value) { current = value }
})
}
counter = new Counter(0, 3)
while ((v = counter.inc()) !== undefined)
console.log(counter.getCurrent(), counter.current)
我期望得到以下输出:
1 1
2 2
3 3
因为 counter.current
和 counter.getCurrent()
应该 return 相同的结果。但相反,我收到
1 0
2 0
3 0
如果我用下面的代码替换 Object.assign(...)
,它会按预期工作。
Object.assign(inc, getCurrent })
Object.defineProperty(Counter.prototype, 'current',
{ get: () => { return current }, set: (value) => { current = value }
我可以使用这个模型,(目前正在使用),但我想使用前者,因为它更简单,也不那么冗长。好像这里有2个不同的作用域。
我用节点 10、Chrome 73 和 Firefox 68 进行了测试,得到了相同的结果。
我在这里缺少什么?
在上面的示例中,我尽量做到简洁。但为了更准确和更好地说明这一点,请遵循更完整的测试,并附上我尝试过的一些评论。
在这里,我将变量 current
重命名为 _current
以避免与 current
属性 混淆,但这不是强制性的。
function Counter(start, stop) {
var _current = start;
function inc() { if (_current < stop) return _current++ }
function getCurrent() { return _current }
// Object.assign(this.constructor.prototype,
// Object.assign(this.__proto__,
// Object.assign(Counter.prototype, {
Object.assign(this, {inc, getCurrent,
get current() { return _current }, set current(value) { _current = value }
// get current() { return current } // supposed to be read-only, but not
})
// This works as expected
// Object.defineProperty(Counter.prototype, 'current',
// { get: () => { return _current }, set: (value) => { _current = value } })
}
counter = new Counter(0, 3)
while ((v = counter.inc()) !== undefined) {
console.log(counter.getCurrent(), counter.current)
counter.current -= 0.5
}
上面代码的输出是:
1 0
2 -0.5
3 -1
counter.current -= 0.5
在哪里存储它的值?
当您的代码调用 Object.assign()
时,它会传入一个对象,该对象具有 getter 和 setter 用于 current
。因此,在将 属性 值复制到新对象时,Object.assign()
进程本身将调用 getter 来获取 属性 "current" 的值。因此,计数器对象最终 没有 getter 和 setter,这解释了您的结果。它的 "counter" 属性 只是一个简单的 属性,带有构造函数代码 运行.[=16 时局部 counter
变量值的副本=]
Object.assign()
只是复制 属性 值,以与任何其他代码相同的方式访问它们。
请注意,如果您 根本不 调用 Object.assign()
,而只是 return 您传递给它的对象,您将得到一个像你期望的那样工作的对象。