Eric Faust 在以下有关 ES6 类的文章中输入了 Circle 构造函数:https://hacks.mozilla.org/2015/07/es6-in-depth-classes/
我想知道:
- 他为什么使用
defineProperty
?我们不能直接在构造函数中实现该行为吗?例如:Circle.draw = function draw() {..}
- 为什么使用
get
/set
而不仅仅是在正常属性中具有状态:Circle.circleCount
? - 哪些属性应该直接在新实例对象上实现,通过
this
在构造函数中,vs onConstructor.prototype
(考虑到两者如何使属性可用于新实例)?
埃里克的代码:
function Circle(radius) {
this.radius = radius;
Circle.circlesMade++;
}
Circle.draw = function draw(circle, canvas) { /* Canvas drawing code */ }
Object.defineProperty(Circle, "circlesMade", {
get: function() {
return !this._count ? 0 : this._count;
},
set: function(val) {
this._count = val;
}
});
Circle.prototype = {
area: function area() {
return Math.pow(this.radius, 2) * Math.PI;
}
};
Object.defineProperty(Circle.prototype, "radius", {
get: function() {
return this._radius;
},
set: function(radius) {
if (!Number.isInteger(radius))
throw new Error("Circle radius must be an integer.");
this._radius = radius;
}
});
let c1 = new Circle(10);
console.log(c1.area());
console.log(Circle.circlesMade);
我的版本:
function Circle(_radius) {
this.radius = _radius;
Circle.draw = function draw(circle, canvas) {
/* Canvas drawing code */
};
!Circle.circleCount ?
(Circle.circleCount = 1) //First construction
:
(Circle.circleCount = Circle.circleCount + 1);
this.area = function area() {
return Math.pow(this.radius, 2) * Math.PI;
};
}
let c1 = new Circle(10);
console.log(Circle.circleCount);
console.log(c1.area());
let c2 = new Circle(20);
console.log(Circle.circleCount);
console.log(c2.area());
最佳答案
我更喜欢将构造函数的原型(prototype)对象用于与实例共享的函数,而不是在每个实例上定义一个新函数。这可以节省内存,因为您只有该函数的一个实例,而不是为您创建的每个实例都有一个新副本。
您还可以在原型(prototype)上定义circleCount
,因为所有实例都需要相同的数字。您只需要稍微小心地更改它,以确保不会在每个实例上创建隐藏属性。然后每个实例可以通过原型(prototype)链直接提供计数。
这样做会使函数变得复杂,但会简化其余代码:
function Circle(_radius) {
this.radius = _radius;
// creating an instance increments the count for everyone
Circle.prototype.circleCount++ // not this.circleCount++ which will create a new property on instance
}
Circle.prototype.draw = function draw(circle, canvas) {
/* Canvas drawing code */
};
Circle.prototype.area = function() {
return Math.pow(this.radius, 2) * Math.PI;
}
Circle.prototype.circleCount = 0
let c1 = new Circle(10);
console.log(c1.circleCount);
console.log(c1.area());
let c2 = new Circle(20);
console.log(c2.circleCount);
console.log(c2.area());
另外,关于Object.defineProperty
的问题。看起来他正在使用它,这样他就可以设置 getter 和 setter 函数,而不仅仅是返回属性。您可以使用 area
来做到这一点,例如:
Object.defineProperty(Circle.prototype, "area", {
get: function() {
return Math.pow(this.radius, 2) * Math.PI;
}
});
这将允许您访问区域,就好像 ti 是每个实例上的属性一样:
c2.area // instead of a function c2.area()
您可以直接将面积设置为属性,但如果更改半径,则还需要更改面积。我想哪个最好取决于半径是否会改变。
关于javascript - 在 JavaScript 中实现 Circle 构造函数,无需 ES6 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51732175/