JavaScript 自定义对象的高效运用与优化
1. 自定义对象概述
在 JavaScript 中,自定义对象就如同定制一杯独特的咖啡,可以根据需求编写代码,利用属性和方法的优势,实现可复用的面向对象代码,有效扩展 JavaScript 语言。
2. YouCube 博客对象分析
2.1 现有博客对象问题
YouCube 博客由 Ruby 创建,当前的 Blog 对象虽能工作,但在面向对象设计上存在不足。其构造函数创建对象时,会为每个对象创建方法的新副本,造成资源浪费和效率低下。例如,若博客有六个条目,就会有六个副本的三个 Blog 方法。
function Blog(body, date) {
// Assign the properties
this.body = body;
this.date = date;
// Return a string representation of the blog entry
this.toString = function() {
return "[" + (this.date.getMonth() + 1) + "/" + this.date.getDate() + "/" +
this.date.getFullYear() + "] " + this.body;
};
// Return a formatted HTML representation of the blog entry
this.toHTML = function(highlight) {
// Use a gray background as a highlight, if specified
var blogHTML = "";
blogHTML += highlight ? "<p style='background-color:#EEEEEE'>" : "<p>";
// Generate the formatted blog HTML code
blogHTML += "<strong>" + (this.date.getMonth() + 1) + "/" +
this.date.getDate() + "/" + this.date.getFullYear() + "</strong><br />" +
this.body + "</p>";
return blogHTML;
};
// See if the blog body contains a string of text
this.containsText = function(text) {
return (this.body.toLowerCase().indexOf(text.toLowerCase()) != -1);
};
}
2.2 类与实例的区别
类是对象的描述模板,实例是根据类创建的实际对象。实例拥有自己的属性副本,以保证对象的独特性;而方法应在对象间共享。
2.3 使用
this
关键字访问实例属性
this
关键字用于在实例方法中访问实例属性,构造函数创建和初始化属性时需使用
this
。
function Blog(body, date) {
this.body = body;
this.date = date ;
}
2.4 类拥有的方法
类拥有的实例方法可被所有实例共享,避免方法代码的重复。可通过
prototype
对象将方法添加到类中。
Blog.prototype.toHTML = function() {
// 方法体
};
2.5 YouCube 博客的优化
将 Blog 对象的方法存储在
prototype
对象中,使方法由类拥有,提高代码效率。
function Blog(body, date) {
// Assign the properties
this.body = body;
this.date = date;
}
// Return a string representation of the blog entry
Blog.prototype.toString = function() {
return "[" + (this.date.getMonth() + 1) + "/" + this.date.getDate() + "/" +
this.date.getFullYear() + "] " + this.body;
};
// Return a formatted HTML representation of the blog entry
Blog.prototype.toHTML = function(highlight) {
// Use a gray background as a highlight, if specified
var blogHTML = "";
blogHTML += highlight ? "<p style='background-color:#EEEEEE'>" : "<p>";
// Generate the formatted blog HTML code
blogHTML += "<strong>" + (this.date.getMonth() + 1) + "/" + this.date.getDate() + "/" +
this.date.getFullYear() + "</strong><br />" + this.body + "</p>";
return blogHTML;
};
// See if the blog body contains a string of text
Blog.prototype.containsText = function(text) {
return (this.body.toLowerCase().indexOf(text.toLowerCase()) != -1);
};
3. 类属性的使用
3.1 类属性的概念
当数据对所有实例都相同时,可使用类属性,它只有一个副本存储在类中。例如,YouCube 博客的签名对所有条目都相同,应作为类属性存储。
3.2 创建类属性
使用
prototype
对象创建类属性,代码如下:
Blog.prototype.signature = "Puzzler Ruby";
3.3 类属性与全局变量的区别
类属性与全局变量类似,但与类和实例对象相关联,需通过实例访问。
3.4 显示类属性
在 Blog 方法中显示签名属性的代码如下:
alert(this.signature);
4. 扩展标准对象
4.1 利用
prototype
扩展对象
可通过
prototype
对象扩展标准 JavaScript 对象,添加属性和方法。例如,为 Date 对象添加
shortFormat
方法:
Date.prototype.shortFormat = function() {
return (this.getMonth() + 1) + "/" + this.getDate() + "/" + this.getFullYear();
};
4.2 类方法
类方法由类拥有,不能访问实例属性,但可访问类属性。例如,创建 Blog 类的
showSignature
方法:
Blog.showSignature = function() {
alert("This blog created by " + Blog.prototype.signature + ".");
};
4.3 博客排序方法的优化
将博客排序比较函数移至 Blog 类的类方法
blogSorter
中,提高代码的封装性。
Blog.blogSorter = function(blog1, blog2) {
return blog2.date - blog1.date;
};
function showBlog(numEntries) {
// First sort the blog
blog.sort(Blog.blogSorter);
...
}
5. 支持博客图片
5.1 存储博客图片
将博客图片作为字符串属性
image
存储在 Blog 对象中。
5.2 修改构造函数
修改 Blog 构造函数,支持图片属性,并将其作为可选参数。
function Blog(body, date, image) {
// Assign the properties
this.body = body;
this.date = date;
this.image = image;
}
5.3 显示博客图片
在
toHTML
方法中添加代码,根据图片属性的值决定是否显示图片。
if (this.image) {
blogHTML += "<strong>" + this.date.shortFormat() +
"</strong><br /><table><tr><td><img src='" + this.image +
"'/></td><td style='vertical-align:top'>" + this.body + "</td></tr></table><em>" +
this.signature + "</em></p>";
}
else {
blogHTML += "<strong>" + this.date.shortFormat() + "</strong><br />" + this.body +
"<br /><em>" + this.signature + "</em></p>";
}
6. 总结
通过合理使用类、实例、类属性、类方法以及扩展标准对象,可优化 JavaScript 代码,提高代码的效率和可维护性。同时,为博客添加图片功能,提升用户体验。
表格总结
| 概念 | 描述 | 示例代码 |
|---|---|---|
| 类 | 对象的描述模板 |
function Blog(body, date) {... }
|
| 实例 | 根据类创建的实际对象 |
var blogEntry = new Blog("内容", new Date());
|
| 类属性 | 所有实例共享的属性 |
Blog.prototype.signature = "Puzzler Ruby";
|
| 类方法 | 由类拥有,不能访问实例属性 |
Blog.showSignature = function() {... };
|
| 实例属性 | 每个实例独有的属性 |
this.body = body;
|
| 实例方法 | 可通过实例调用的方法 |
Blog.prototype.toHTML = function() {... };
|
mermaid 流程图
graph LR
A[创建 Blog 类] --> B[添加实例属性]
A --> C[添加类属性]
A --> D[添加实例方法]
A --> E[添加类方法]
B --> F[创建实例]
F --> G[访问实例属性和方法]
C --> H[实例共享类属性]
E --> I[调用类方法]
D --> J[实例调用实例方法]
通过以上优化和扩展,YouCube 博客的代码更加高效、可维护,同时具备了更多实用功能。
7. JavaScript 相关概念问答
7.1 类与实例的区别
类是为了更方便地创建和复用对象而存在的。如果每次创建相似对象都从头开始,就像建筑师每次建同样的房子都重新绘制图纸一样,会浪费大量精力。而类就像一个模板,创建一个类后,可以用它来创建任意数量的实例,大大减少了工作量。
7.2
this
和
prototype
的作用
-
this关键字用于在对象的方法内部访问该对象的实例。它主要用于访问实例属性,例如在方法内部访问属性x时,需要使用this.x,否则代码会将x视为普通变量。在构造函数中创建和初始化属性时,也必须使用this。 -
prototype是 JavaScript 中创建类的机制。JavaScript 不像 C++ 和 Java 那样直接支持类,而是通过原型来模拟类。将属性或方法存储在prototype对象中,就可以使其成为类的一部分,供所有实例共享。
7.3 构造函数在类中的作用
构造函数在 JavaScript 类中非常重要,它负责创建对象实例。可以将构造函数和原型看作 JavaScript 类的两个主要部分。构造函数负责为实例设置所有必要的内容,而原型则处理类级别的所有内容。这两者协同工作,使得我们可以根据需要将一些成员放在实例级别,一些放在类级别。
7.4 对象命名约定
类名通常使用大写字母开头,而实例名使用小写驼峰命名法。这是因为实例实际上就是变量,而变量标识符通常使用小写驼峰命名法。例如,
Blog
是类名,而
blogEntry
或
blog[0]
是实例名。
表格总结
| 概念 | 描述 |
|---|---|
| 类与实例 | 类是模板,实例是根据模板创建的实际对象 |
this
| 用于在对象方法内部访问实例属性 |
prototype
| 用于创建类,存储类属性和类方法 |
| 构造函数 | 负责创建对象实例 |
| 命名约定 | 类名大写,实例名小写驼峰 |
8. 实例属性与类属性的对比
8.1 实例属性的作用
实例属性允许对象实例保持独特性,并跟踪自己的属性值。每个实例都有自己的属性副本,这使得实例之间可以相互区别。例如,在一个博客系统中,每个博客条目都有自己独特的内容和日期,这些都可以作为实例属性存储。
8.2 类属性的适用场景
当数据对所有实例都相同时,使用类属性更为合适。例如,一个博客的作者签名对所有博客条目都是相同的,此时将签名作为类属性存储在类中,所有实例都可以共享这个属性,避免了数据的重复存储。
8.3 实例属性与类属性的对比示例
| 属性类型 | 特点 | 示例 |
|---|---|---|
| 实例属性 | 每个实例有自己的副本,用于存储独特数据 |
this.body = body; this.date = date;
|
| 类属性 | 所有实例共享一个副本,用于存储公共数据 |
Blog.prototype.signature = "Puzzler Ruby";
|
mermaid 流程图
graph LR
A[实例属性] --> B[每个实例独立存储]
B --> C[实例数据独特]
D[类属性] --> E[所有实例共享]
E --> F[存储公共数据]
9. 代码优化与扩展的实际应用
9.1 消除重复代码
在 YouCube 代码中,存在一些重复的日期格式化代码。为了消除这些重复代码,可以添加一个日期格式化方法到
Blog
对象中。考虑到日期格式化实际上是
Date
对象的一种行为,将该方法添加到
Date
对象的原型中更为合适。
Date.prototype.shortFormat = function() {
return (this.getMonth() + 1) + "/" + this.getDate() + "/" + this.getFullYear();
};
9.2 博客排序功能的优化
将博客排序比较函数移至
Blog
类的类方法
blogSorter
中,使
showBlog
函数不再需要关注博客排序的具体细节,提高了代码的封装性。
Blog.blogSorter = function(blog1, blog2) {
return blog2.date - blog1.date;
};
function showBlog(numEntries) {
// First sort the blog
blog.sort(Blog.blogSorter);
// 其他代码
}
9.3 添加图片支持
为了让 YouCube 博客支持图片,需要对
Blog
对象进行扩展。具体步骤如下:
1. 在
Blog
构造函数中添加一个可选的
image
属性,用于存储博客图片的文件名。
function Blog(body, date, image) {
this.body = body;
this.date = date;
this.image = image;
}
-
在
toHTML方法中添加代码,根据image属性的值决定是否显示图片。
if (this.image) {
blogHTML += "<strong>" + this.date.shortFormat() +
"</strong><br /><table><tr><td><img src='" + this.image +
"'/></td><td style='vertical-align:top'>" + this.body + "</td></tr></table><em>" +
this.signature + "</em></p>";
} else {
blogHTML += "<strong>" + this.date.shortFormat() + "</strong><br />" + this.body +
"<br /><em>" + this.signature + "</em></p>";
}
10. 总结与展望
通过合理运用 JavaScript 中的类、实例、类属性、类方法以及扩展标准对象等技术,我们可以对代码进行优化,提高代码的效率和可维护性。在 YouCube 博客的优化过程中,我们消除了重复代码,将排序功能封装到类方法中,还添加了图片支持,使博客具备了更多实用功能。
未来,我们可以进一步扩展 YouCube 博客的功能。例如,支持多博主功能,将签名属性改为实例属性,并在构造函数中添加参数以传递签名信息;还可以添加更多的交互功能,如评论、点赞等,提升用户体验。同时,持续关注代码的性能优化,确保博客在高并发情况下仍能稳定运行。
表格总结
| 优化点 | 操作步骤 | 示例代码 |
|---|---|---|
| 消除重复代码 |
为
Date
对象添加
shortFormat
方法
|
Date.prototype.shortFormat = function() {... };
|
| 优化博客排序 |
将排序比较函数移至
Blog
类的类方法中
|
Blog.blogSorter = function(blog1, blog2) {... };
|
| 添加图片支持 |
修改
Blog
构造函数,在
toHTML
方法中添加图片显示逻辑
|
function Blog(body, date, image) {... };
和
if (this.image) {... } else {... }
|
mermaid 流程图
graph LR
A[代码优化] --> B[消除重复代码]
A --> C[优化排序功能]
A --> D[添加图片支持]
B --> E[扩展 Date 对象]
C --> F[创建 Blog 类方法]
D --> G[修改构造函数]
D --> H[修改 toHTML 方法]
E --> I[提高代码复用性]
F --> J[增强代码封装性]
G --> K[支持图片存储]
H --> L[支持图片显示]
通过不断地优化和扩展,JavaScript 代码可以变得更加高效、灵活,为用户提供更好的体验。
JavaScript自定义对象优化实践
超级会员免费看
3000

被折叠的 条评论
为什么被折叠?



