我已经看到通过对象文字和属性描述符中的get
和set
关键字定义的访问者属性。
(来自Speaking JavaScript):
// Object literal
var obj = {
get foo() {
return 'getter';
},
set foo(value) {
console.log('setter: '+value);
}
};
// Property descriptor
var obj = Object.create(
Object.prototype, { // object with property descriptors
foo: { // property descriptor
get: function () {
return 'getter';
},
set: function (value) {
console.log('setter: '+value);
}
}
}
);
(来自Eloquent JavaScript):
// Adding to an object's prototype
Object.defineProperty(TextCell.prototype, "heightProp", {
get: function() { return this.text.length; }
});
但是说你正在使用构造函数来创建对象。我还没有看到在构造函数本身中定义访问器的示例(即,访问者是对象的自己的属性。)
在constuctor中使用Object.defineProperty
似乎有效:
function V(x, y) {
this.x = x;
this.y = y;
// accessor (getter) `length`
Object.defineProperty(this, 'length', {
get: function () { return Math.sqrt(this.x*this.x + this.y*this.y); } // (1)
});
}
上面构造函数中的(1)中定义的访问器属性是否存在差异,以及在早期模式中定义的访问器属性(对象文字,直接在对象上的属性描述符)?
(有没有客观的理由不在编码风格偏好之外的构造函数中定义getter和setter?)
答案 0 :(得分:1)
上面构造函数中的(1)中定义的访问器属性是否存在差异,以及在早期模式中定义的访问器属性(对象文字,直接在对象上的属性描述符)?
(1)和之前使用defineProperty
之间没有区别,没有。它与顶部的对象初始值设定项(var obj = ...
)之间存在差异:foo
属性是可枚举,而您的length
属性(1示例和Eloquent JavaScript示例中的heightProp
不是(因为defineProperty
的默认值是将其定义为不可枚举;您可以通过添加enumerable: true
)来更改它。
(有没有客观的理由不在编码风格偏好之外的构造函数中定义getter和setter?)
没有。我会注意到,你的特定例子并不是从自己的财产中获益;所以我可能会在V.prototype
上定义它。但除了使用在原型上定义的东西(共享,可重用性,动态性)的通常好处之外,没有特别的理由偏爱它。定义一次意味着更少的功能对象,但对象相当便宜。
答案 1 :(得分:0)
上面构造函数中的(1)中定义的访问器属性是否存在差异,以及在早期模式中定义的访问器属性(对象文字,直接在对象上的属性描述符)?
Object.defineProperty
和Object.defineProperties
允许对getter / setter的定义方式进行更精细的控制。
(有没有客观的理由不在编码风格偏好之外的构造函数中定义getter和setter?)
是的,取决于您的目的。
prototype
:([]).hasOwnProperty('length') // true, old pre-getter array.
(new Uint8Array(1)).hasOwnProperty('length') // false, new typed array.
您可以访问构造函数闭包的私有属性,这对于某些事情是可取的(WeakMap
可能会使这完全不必要)。
答案 2 :(得分:0)
当使用函数构造函数模式创建新的实例对象时,在创建的每个实例的代码中,您将具有一个作为函数的吸气剂(即另一个对象),因此您将为每个实例创建两个对象。相反,在将getter方法附加到原型的其他解决方案中,对于所有创建的对象,只有一个getter。此外,在对象文字表示法中,属性configurable
和enumerable
默认情况下为true
,而不是函数defineProperty
,默认情况下为false
,但您可以要解决此差异,请在V
函数中显式设置这些属性,或者您可以按照以下方式进行操作:
function V(x, y) {
return { x,
y,
get length(){
return Math.sqrt(this.x*this.x + this.y*this.y);
}
};
}
您可以在构造函数内部返回带有对象文字符号的对象。注意ES6属性值shortand。这样,true
的可配置和可枚举将是length property