JavaScript面向对象-基于组合和动态原型创建对象 - Web前端
作者:98wpeu发布时间:2026-08-29分类:网页前端技术浏览:10

前面两篇文章我们介绍了javascript中原型的内存模型和原型的重写方法即注意事项。在了解原型之后,我们就可以通过原型来创建JavaScript对象。基于原型的创建方式虽然可以有效的完成封装,但是依然会存在一些问题。
通过原型的方式来创建对象主要会产生2个问题:
1、无法通过构造函数来设置对象的属性值。
2、当属性中有引用类型变量时,可能会存在变量值的重复。
我们来看下面的例子:
function Person(){}
Person.prototype = {
constructor:Person,
name:"Leon",
age:22,
friends:["Ada","Chris"],
say:function(){
console.info(this.name+"["+this.friends+"]");
}
}在上面的代码中,我们创建了一个Person类,并通过原型重写的方式为它设置了一些属性和方法,其中有一个frIEnds属性,是一个引用类型的数组。接下来我们通过Person类来创建对象,代码如下:
var p1 = new Person(); p1.name = "John"; p1.say(); //控制台输出:Jhon[Ada,Chris]
我们通过Person类创建了对象p1,可以看到使用原型方式创建对象时没有办法为对象p1设置属性,我们只有在对象创建之后才设置p1的name属性。接着调用p1的say()方法,控制台会输出Jhon[Ada,Chris],到这里一切都还是正常的。
如果我们接着为对象p1添加一个新的朋友,问题就会出现了。代码如下:
p1.friends.push("Mike"); //为p1增加一个朋友(注意这里是在原型中添加)
p1.say();我们通过数组的push方法为p1添加一个新的朋友“Mike”,此时,在对象p1自己的空间中是没有friends属性的,所以“Mike”会被添加到Person的原型中,如下图所示:

由于新加入的数组元素是放置在原型中的,所以后面创建的所有对象都会共享这个属性,这时我们创建对象p2的话,他的朋友中也会有一个“Mike”。这是我们不希望看到的结果。
var p2 = new Person(); //如果p1 push之后,原型中就多了一个人,p2也多了一个朋友 p2.say();
基于组合原型和构造函数的方式创建对象
为了解决上面的问题,我们可以使用基于组合原型和构造函数的方式来创建对象。也就是将属性在构造函数中定义,将方法在原型中定义。这种方式有效的集合了两者的优点,是我们在Javascript中最常用的一种创建对象的方式。
function Person(name,age,friends){
//属性在构造函数中定义
this.name = name;
this.age = age;
this.friends = friends;
}
Person.PRototype = {
//方法在原型中定义
constructor:Person,
say:function(){
console.info(this.name+"["+this.friends+"]");
}
}通过这种方式创建的对象,所有的属性都是保存在对象自己的空间中的。此时,在创建对象的时候,我们就可以为对象设置它自己的属性。
var p1 = new Person("Leon",22,["Ada","Chris"]);
p1.name = "John";
p1.say(); //控制台输出: John[Ada,Chris]完成上面的代码后,Person类及p1对象的内存模型如下图所示:

此时,我们再为对象p1添加一个新的朋友时,会在p1对象自己的内存空间中的friends属性中添加。这样,每个对象的属性都是独立的,不会互相干扰。
p1.friends.push("Mike"); //为p1增加一个朋友(注意这里是在p1自己的空间中添加)
p1.say(); //控制台输出: John[Ada,Chris,Mike]
var p2 = new Person();
p2.say(); //控制台输出: John[Ada,Chris]因此,现在再创建对象p2时,p2对象的friends只会是“Ada”和“Chris”,而没有“Mike”。
动态原型方式创建对象
虽然基于组合原型和构造函数的方式创建对象已经非常完美了,但是它和纯正的面向对象语言创建对象的方式还是有一些差别:类的方法被定义在类之外。为了让定义对象更加符合面向对象规范的需求,我们可以把定义方法的原型代码放置到Person构造函数中。这种方式我们称为动态原型方式创建对象。
// 动态原型方式
function Person(name,age,friends){
this.name = name;
this.age = age;
this.friends = friends;
Person.prototype.say = function(){
console.info(this.name+"["+this.friends+"]");
}
}注意在使用动态原型方式创建对象的时候,我们在定义方法的时候不能够使用原型重写的方式,例如下面的代码是错误的:
// 错误的动态原型方式
function Person(name,age,friends){
this.name = name;
this.age = age;
this.friends = friends;
//不能使用原型重写的方式来设置方法
Person.prototype = {
constructor:Person,
say:function(){
console.info(this.name+"["+this.friends+"]");
}
}
}使用动态原型方式创建对象同样会存在问题,因为类中的方法是通过Person.prototype.say的方式创建的,这样每次创建对象的时候,都会在内存中创建一个新的say()方法。解决这个问题的方法是我们可以先做一个判断,看Person.prototype.say方法是否存在,不存在时才创建,否则就不创建。
// 动态原型方式
function Person(name,age,friends){
this.name = name;
this.age = age;
this.friends = friends;
//判断Person.prototype.say是否存在,不存在就创建
if(!Person.prototype.say){
alert("创建say方法");
Person.prototype.say = function(){
console.info(this.name+"["+this.friends+"]");
}
}
}为了验证判断条件是否起作用,我们在代码中的判断分支中添加了一个弹出对话框语句。我们可以创建2个对象,然后2个对象分别调用say()方法,在结果中,第一个对象在调用say()方法时会弹出对话框,而第二个对象在调用say()方法时就不会在弹出对话框了,也就是说创建第二个对象时不会再添加say()方法。
返回javascript教程主目录>>
相关推荐
- 【SVG】创建和导出SVG的技巧 - Web前端
- JavaScript浏览器对象-history对象 - Web前端
- 【SVG】CSS vs SVG: 最后一节(上部分) - Web前端
- JavaScript文档对象模型-DocumentType类型 - Web前端
- 【SVG】如何操作SVG Text - Web前端
- 【SVG】SVG动画案例的学习 - Web前端
- SVG基础 | SVG图形描边 - Web前端
- 【SVG】详解feColorMatrix - Web前端
- JavaScript文档对象模型-Comment类型 - Web前端
- 分享一款很炫丽的视频分享站,亮瞎你的眼! - Web前端
- 网页前端技术排行
-
- 1[Web前端]用javascript实现默认图片替代未显示的图片 - Web前端
- 2分析Iconfont-阿里巴巴矢量常用图标库 - Web前端
- 3jQuery实例教程:制作网页中可折叠的面板 - Web前端
- 4基于jquery的滚动条滚动固定div(附演示下载) - Web前端
- 5【第六章】Foundation之按钮和下拉功能 - Web前端
- 6jQuery编写widget的一些技巧分享 - Web前端
- 7分享精心挑选的12款优秀jQuery Ajax分页插件和教程 - Web前端
- 8jQuery实现鼠标移到元素上动态提示消息框效果 - Web前端
- 9在Mac/PC上远程调试iPhone/iPad上的网页 - Web前端
- 最近发表
-
- WordPress随机显示特色图片插件:Random Post Thumbnails
- KeePass实现Chrome浏览器自动填充密码方法一
- LNMP一键包nginx 301强制跳转到https教程
- KeePass实现Chrome浏览器自动填充密码方法二
- #建站# 免费的VPS管理软件Xshell8/Xftp8中文版下载
- 使用Xshell 8连接VPS教程_电脑登录vps的方法
- WordPress评论界面添加烟花????效果
- 不同浏览器书签同步方案:坚果云+Floccus_详细使用教程
- iOS端KeePassXC客户端APP:Strongbox Password Safe
- 给WordPress评论中的Gravatar头像图片添加ALT属性


