javascript - 在 JavaScript 中实现 Circle 构造函数,没有 ES6 类
问题描述
Eric Faust 在以下关于 ES6 类的文章中键入了一个 Circle 构造函数:https ://hacks.mozilla.org/2015/07/es6-in-depth-classes/
我想知道:
- 他为什么用
defineProperty
?我们不能直接在构造函数中实现行为吗?例如:Circle.draw = function draw() {..}
- 为什么使用
get
/set
而不是仅仅在正常属性中使用状态:Circle.circleCount
? - 哪些属性应该直接在新实例对象上实现,通过
this
构造函数与 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());
解决方案
我更喜欢将构造函数的原型对象用于将与实例共享的函数,而不是在每个实例上定义一个新函数。这可以节省内存,因为您只有一个函数实例,而不是为您创建的每个实例创建一个新副本。
您也可以circleCount
在原型上定义,因为所有实例都需要相同的编号。您只需要稍微小心地更改它,以确保您不会在每个实例上创建阴影属性。然后每个实例可以直接通过原型链提供计数。
这样做会使函数复杂化,但会简化其余代码:
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;
}
});
这将允许您访问 area ,就好像 ti 是每个实例的属性一样:
c2.area // instead of a function c2.area()
您可以直接将区域设置为属性,但是如果您更改半径,您还需要更改区域。我想哪个最好取决于半径是否会改变。
推荐阅读
- python - AttributeError:“NoneType”对象在 request_json 中没有“get”属性
- java - 如何从ability_main.xml 初始化 RgbColor?
- ruby - 在 ruby cli 应用程序上创建多个选择选项并返回选项
- python - 程序自动四舍五入并检查数据帧中的两个数字是否相等
- shell - 使用 SAR 命令监控可用磁盘空间数据
- django - Django 无法在管理页面中加载 ckeditor
- android - Flutter - 播放视频时显示Google Drive“此时无法播放此视频”
- x++ - DefaultDimension 未显示在表单上
- java - 为什么在 MockMvc.perform 上出现空指针异常?
- javascript - 将图像上传到 Firebase 时出现问题。React Native、Firebase、Redux