JavaScript 面向对象编程入门:对象创建、原型与继承详解
本文详细介绍 JavaScript 中面向对象编程的核心概念,涵盖使用 new Object()、文字记号(Literal Notation)及构造函数三种对象创建方式。深入解析原型(prototype)机制在方法共享与对象扩展中的应用,并通过示例演示基于函数的继承实现及对象属性的遍历技巧,帮助开发者掌握 JS 对象模型的基础用法。
JavaScript 对象创建基础
使用 new Object() 构造函数来实例化对象
JavaScript 提供了多种创建对象的方式,开发者可根据具体场景选择最合适的方法。其中最为直观的一种是利用 new 操作符配合 Object 构造函数来生成对象实例。
具体实现代码如下:
<script language="javascript" type="text/javascript">
<!--
person = new Object()
person.name = "Tim Scarfe"
person.height = "6Ft"
person.run = function() {
this.state = "running"
this.speed = "4ms^-1"
}
//-->
</script>上述示例展示了如何定义一个名为 person 的对象,并为其添加属性(如 name、height)以及方法(run)。值得注意的是,在自定义的方法内部,可以通过 this 关键字访问该对象的其他属性。
采用文字记号(Literal Notation)创建对象
除了使用构造函数,JavaScript 还支持通过文字记号直接定义对象,该方法要求 JavaScript 版本在 1.2 或以上。这种创建方式具有更高的灵活性和多样性。
代码示例如下:
<script language="javascript" type="text/javascript">
<!--
// Object Literals
timObject = {
property1 : "Hello",
property2 : "MmmMMm",
property3 : ["mmm", 2, 3, 6, "kkk"],
method1 : function(){alert("Method had been called" + this.property1)}
};
timObject.method1();
alert(timObject.property3[2]) // will yield 3
var circle = { x : 0, y : 0, radius: 2 } // another example
// nesting is no problem.
var rectangle = {
upperLeft : { x : 2, y : 2 },
lowerRight : { x : 4, y : 4}
}
alert(rectangle.upperLeft.x) // will yield 2
//-->
</script>文字记号允许属性值为任意合法的 JavaScript 表达式或数据,包括数组、对象甚至函数。
无论是使用 new 操作符还是文字记号,创建单个对象都简单且符合逻辑。然而,这两种方式的主要缺陷在于生成的对象难以复用,且无法通过不同参数轻松初始化多个相似对象。例如在前面的 person 示例中,若需改变 name 属性,必须重新定义整个对象结构,缺乏灵活性。
构造器与原型机制
对象的构造器与原型机制
在面向对象编程(OOP)体系中,前述方法在需要大量实例化且需保持类型一致的场景下存在局限。我们需要一种能够定义“类”或“蓝图”的方法,使得对象在实例化时能按需分配不同的属性值,而无需重复定义结构。实现这一目标的标准做法是使用对象构造器函数。
对象构造器本质上是一个规范的 JavaScript 函数,它充当容器的角色,用于定义参数、调用其他逻辑等。与普通函数的区别在于,构造器函数通常由 new 操作符调用(如下例所示)。基于这种语法形式,我们可以高效地定义对象的行为。
以现实世界中的猫为例,每只猫都有 name 和 color 属性,以及 meeyow(叫声)方法。不同个体的 name 和叫声内容可能不同。为了构建能适配这些特征的类,我们采用对象构造器来实现。
代码如下:
<script language="javascript" type="text/javascript">
<!--
function cat(name) {
this.name = name;
this.talk = function() {
alert( this.name + " say meeow!" )
}
}
cat1 = new cat("felix")
cat1.talk() //alerts "felix says meeow!"
cat2 = new cat("ginger")
cat2.talk() //alerts "ginger says meeow!"
//-->
</script> 在此示例中,cat() 函数作为对象构造器,其属性和方法通过 this 关键字在函数体内定义。通过 new 操作符实例化对象,我们可以轻松创建多个 cat 实例,每个实例拥有独立的 name 属性,体现了构造器带来的灵活性。
需要明确的是,构造器定义的是对象的蓝图(模板),而非对象本身。
通过原型(prototype)添加方法
在前例中,方法是在构造器内部定义的。另一种实现路径是利用原型(prototype)。
原型是 JavaScript 实现继承的一种机制。我们可以在对象定义完成后,通过原型动态添加方法,这些新增的方法将被该类型的所有现有及未来实例共享。
接下来,我们扩展最初的 cat 对象,增加一个 changeName 方法,并演示如何使用 prototype 方式实现。
代码如下:
<script language="javascript" type="text/javascript">
<!--
cat.prototype.changeName = function(name) {
this.name = name;
}
firstCat = new cat("pursur")
firstCat.changeName("Bill")
firstCat.talk() //alerts "Bill says meeow!"
//-->
</script> 如你所见,仅使用 prototype 关键字即可在对象定义后即时增加 changeName 方法。该方法被所有实例共享,体现了原型机制的优势。
利用原型(prototype)重载 JavaScript 对象
原型机制不仅适用于自定义对象,也可用于选择性重载内置对象(如 Date() 或 String)。这种扩展能力几乎是无限的。
继承与对象遍历
子类与超类的概念
在 Java 和 C++ 等语言中,存在明确的类层次结构概念,每个类可拥有父类(超类)并继承其属性和方法,同时也可被其他类继承(子类化)。
In Java and C++, there is an explicit concept of the class hierarchy. i.e. Every class can have a super class from which it inherits properties and methods. Any class can be extended, or sub-classed so the resulting subclass can inherit its parent's behavior. As we have seen, javascript supports prototype inheritance instead of class based. It's possible for inheritance to happen other ways, however.
The following is an example of inheritance through functions.
以下示例演示了如何通过函数实现继承。
代码如下:
<script language="javascript" type="text/javascript">
<!--
// thanks to webreference
function superClass() {
this.supertest = superTest; //attach method superTest
}
function subClass() {
this.inheritFrom = superClass;
this.inheritFrom();
this.subtest = subTest; //attach method subTest
}
function superTest() {
return "superTest";
}
function subTest() {
return "subTest";
}
var newClass = new subClass();
alert(newClass.subtest()); // yields "subTest"
alert(newClass.supertest()); // yields "superTest"
//-->
</script>基于原型的继承在 JavaScript 应用程序的许多场景中都非常有用。
(基于原型的继承在许多javascript的应用场合是非常有用的。)
将对象视为关联数组
正如所知,(.) 操作符常用于存储和访问属性,而 [] 操作符则常用于数组操作。
代码示例如下:
<!--
// These are the same
object.property
object["property"]
//-->
</script>
<SCRIPT LANGUAGE="javascript">
<!--
function Circle (xPoint, yPoint, radius) {
this.x = xPoint;
this.y = yPoint;
this.r = radius;
}
var aCircle = new Circle(5, 11, 99);
alert(aCircle.x);
alert(aCircle["x"]);
//-->
</SCRIPT>
How do I loop through properties in an object?
You need to use a for/in loop.
我们可以通过 for...in 循环来遍历对象的所有属性。
示例代码如下:
<!--
var testObj = {
prop1 : "hello",
prop2 : "hello2",
prop3 : new Array("hello",1,2)
}
for(x in testObj) alert( x + "-" + testObj[ x ] )
//-->
</script>
<SCRIPT LANGUAGE="javascript">
<!--
var Circle = { x : 0, y : 1, radius: 2 } // another example
for(p in Circle)
alert( p + "-" + Circle[ p ] )
//-->
</SCRIPT>
The important thing to notice is that in the object syntax the property is an identifier, whereas in the array syntax, it's a string. The obvious benefits of using an array syntax to access an object is because of the literal data type, you can easily concat strings and play around with them to access an object. For this to work with the standard syntax, an eval() would need to be used.
值得注意的关键点是:在标准对象语法中,属性名是一个标识符;而在数组语法中,它是一个字符串。使用数组语法访问对象的明显优势在于,由于是字面量数据类型,你可以轻松拼接字符串并通过动态生成的键名来访问对象属性。若要通过标准语法实现类似动态访问,则可能需要借助 eval() 函数。
代码示例如下:
<!--
testObj = {
prop1 : "hello",
prop2 : "hello2",
prop3 : new Array("helloa",1,2)
}
for(x in testObj) alert( x + "-" + testObj[ x ] )
var prop3 = testObj["prop3"];
alert(prop3);
//alert(prop[1]);
alert(typeof(prop3));
alert(eval(prop3)[1]);
alert(typeof(eval(prop3)[1]));
//-->
</script>
网上的东西错误的太多了,jb51.net修正后的测试下
[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
