ES5 getter 和 setter 是 "potentially surprising and difficult to reason about"
ES5 getters and setters are "potentially surprising and difficult to reason about"
引用最近的Google JavaScript Style Guide:
Do not use JavaScript getter and setter properties. They are potentially surprising and difficult to reason about, and have limited support in the compiler. Provide ordinary methods instead.
Exception: when working with data binding frameworks (such as Angular and Polymer), getters and setters may be used sparingly. Note, however, that compiler support is limited. When they are used, they must be defined either with get foo()
and set foo(value)
in the class or object literal, or if that is not possible, with Object.defineProperties
. Do not use Object.defineProperty
, which interferes with property renaming. Getters must not change observable state.
Illegal:
class Foo {
get next() { return this.nextId++; }
}
这是Google的意见,但我想真正了解原因。
首先,我认为支持有限的"compilers"是Babel / Traceur / TypeScript?还是某些 ES5 引擎缺少支持?
另外,想了解下作者的"surprising and difficult"原因是什么。我看到了这些限制:
Object.assign()
不复制 getter,而是执行它们并复制值;
- 使用
get name()
语法,无法将 getter 添加到现有对象。对于现有对象,必须使用 Object.defineProperty
。
- 无法使用 lambda 定义 getter,此限制可能导致我们在某些情况下使用老派
let that = this
。
我不明白以下语句:"Object.defineProperty
干扰 属性 重命名"。 (什么是"property renaming"?)
我猜他们的意思是:
"[potentially] surprising":
具有 getter 和 setter 的属性不一定像普通属性一样。因此,他们违反了principle of least surprise。假设你有一个 属性 如果分配给它的值为负数则返回 0:
myObj.prop = -7;
expect(myObj.prop).to.equal(-7); // fails
"[potentially] difficult to reason about":
出于类似的原因。具有 getter 和 setter 的属性不一定像普通属性一样,这意味着您不一定能像对普通属性进行推理那样对它们进行推理。
假设我们再次遇到上述 属性。您不能执行以下操作:
myObj.prop = -7;
console.log(myObj.prop * 9);
// use substitution to figure out the result of the above statement:
console.log(-7 * 9); // substitute -7 for myObj.prop
console.log(-63); // wrong - the above actually logs 0
关于 属性 重命名:根据 ,Closure 编译器中的优化器尝试重命名(缩小)属性 名称,但它会以不完整的方式这样做重命名对它们的引用,但不更新 .defineProperty()
调用。使用 .defineProperties()
允许优化器正确重命名属性。
引用最近的Google JavaScript Style Guide:
Do not use JavaScript getter and setter properties. They are potentially surprising and difficult to reason about, and have limited support in the compiler. Provide ordinary methods instead.
Exception: when working with data binding frameworks (such as Angular and Polymer), getters and setters may be used sparingly. Note, however, that compiler support is limited. When they are used, they must be defined either with
get foo()
andset foo(value)
in the class or object literal, or if that is not possible, withObject.defineProperties
. Do not useObject.defineProperty
, which interferes with property renaming. Getters must not change observable state.Illegal:
class Foo { get next() { return this.nextId++; } }
这是Google的意见,但我想真正了解原因。
首先,我认为支持有限的"compilers"是Babel / Traceur / TypeScript?还是某些 ES5 引擎缺少支持?
另外,想了解下作者的"surprising and difficult"原因是什么。我看到了这些限制:
Object.assign()
不复制 getter,而是执行它们并复制值;- 使用
get name()
语法,无法将 getter 添加到现有对象。对于现有对象,必须使用Object.defineProperty
。 - 无法使用 lambda 定义 getter,此限制可能导致我们在某些情况下使用老派
let that = this
。
我不明白以下语句:"Object.defineProperty
干扰 属性 重命名"。 (什么是"property renaming"?)
我猜他们的意思是:
"[potentially] surprising":
具有 getter 和 setter 的属性不一定像普通属性一样。因此,他们违反了principle of least surprise。假设你有一个 属性 如果分配给它的值为负数则返回 0:
myObj.prop = -7;
expect(myObj.prop).to.equal(-7); // fails
"[potentially] difficult to reason about":
出于类似的原因。具有 getter 和 setter 的属性不一定像普通属性一样,这意味着您不一定能像对普通属性进行推理那样对它们进行推理。
假设我们再次遇到上述 属性。您不能执行以下操作:
myObj.prop = -7;
console.log(myObj.prop * 9);
// use substitution to figure out the result of the above statement:
console.log(-7 * 9); // substitute -7 for myObj.prop
console.log(-63); // wrong - the above actually logs 0
关于 属性 重命名:根据 .defineProperty()
调用。使用 .defineProperties()
允许优化器正确重命名属性。