JavaScript使用prototype属性实现继承操作示例
本文详解JavaScript中利用prototype属性实现继承的机制。文章指出JS无显式继承语法,通过构造函数内部定义方法存在性能与闭包弊端。重点讲解利用prototype属性动态添加方法以实现伪继承,以及将prototype指向父类实例来实现真正继承关系的两种核心模式,并附带完整代码示例。
本文通过具体示例,介绍如何在JavaScript中利用prototype属性完成继承操作,供开发者参考。
JavaScript继承机制概述
JavaScript语言本身并未提供显式的继承语法结构。在该语言中,所有对象本质上都是Object的子类实例,因此对象之间处于平等的地位。
尽管缺乏直接的语法支持,开发者仍可通过特定技术手段模拟出继承的效果。
JavaScript同样不支持直接定义“类”,但可以通过定义函数来构建一个同名的类结构,此时该函数即充当类的构造器。
在定义函数时,以this修饰的变量被视为类实例中的属性。若该属性的值为函数,则可将其视为实例方法。
//定义一个Person类
function Person(name , age)
{
this.name=name;
this.age=age;
//定义一个info函数
this.info=function()
{
document.writeln("年龄"+this.age+"姓名"+this.name);
}
}
//创建Person类的实例对象
var p1= new Person('xiaoming',20);
//调用p1的info方法
p1.info();
var p2= new Person('wang',22);
p2.info();
构造函数内部定义方法的弊端
这种在类(即函数)内部直接定义函数的方式存在明显的局限性:
- 首先,性能表现较差。每次创建对象时,都会生成一个新的info函数副本。若存在多个对象,则会产生多个info函数实例。实际上,我们只需一个info函数即可,这种冗余会占用系统内存,导致性能下降甚至内存泄漏。
- 其次,info函数中的局部变量会形成闭包。闭包机制会扩大局部变量的作用域,使得局部变量在函数执行结束后仍能存活于外部。
为避免上述两种问题,通常不建议在类定义内部直接定义方法,而应采用prototype属性。
利用prototype属性扩展类
JavaScript中所有的类(函数)均拥有一个prototype属性。向该属性添加属性和方法,可视为对类的扩展。
这意味着增加了prototype属性的类可以继承原有类的特性,这构成了JavaScript所提供的伪继承机制。
//定义一个Person类
function Person(name , age)
{
this.name=name;
this.age=age;
//定义一个info函数
this.info=function()
{
document.writeln("年龄"+this.age+"姓名"+this.name);
}
}
//创建Person类的实例对象
var p1= new Person('xiaoming',20);
//调用p1的info方法
p1.info();
//为Person类增加walk方法
Person.prototype.walk=function()
{
document.writeln(this.name+'正在走<br/>');
}
var p2=new Person('xiaohong',20);
//p2可以调用Person中的方法
p2.info();
//也可以调用prototype属性增加的方法
p2.walk();
//JS允许为类动态增加方法和属性,这里p1也可以调用walk
p1.walk();
上述示例通过prototype属性增加方法,可视为为Person类动态添加了新方法。
通过这种方式增加的方法,所有实例将共享同一个walk方法。值得注意的是,Person.prototype属于类的属性,而非特定于某个实例。
由于walk方法并未定义在Person函数内部,因此不会产生闭包问题。
这种为类动态增加属性和方法的操作,可被视作一种伪继承手段。
然而,这种伪继承并未生成新的子类,而是直接修改了原有的类定义。
通过原型链实现继承
接下来,介绍prototype属性实现继承的另一种方式。
prototype属性代表该类原型对象,默认情况下是一个Object对象。若将类的prototype设置为父类的实例,即可实现继承。
function Person(name,age)
{
this.name=name;
this.age=age;
}
Person.prototype.say=function()
{
console.log(this.name+'说话了');
}
var per = new Person('小明',20);
per.say();
//再定义一个student类,欲意继承Person
function Student (grade)
{
this.grade=grade;
}
//将student的prototype设为Person对象
Student.prototype =new Person('小红',22);
//为Student添加方法
Student.prototype.intro= function()
{
console.log(this.name+'是'+this.grade+'年级学生');
}
var stu=new Student(3);
stu.name="小刚";
console.log(stu instanceof Person&& stu instanceof Student);//true
stu.say();//小刚说话了
stu.intro();//小刚是3年级学生
上述示例中定义了Person类,并为其增加了say()方法。
随后定义了Student类,并将Student类的prototype属性设置为Person对象的实例。这表明Student的原型是Person对象。
这意味着Student继承了Person,从而可以获得其方法和属性。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
JS对象数组转字符串为什么推荐用JSON.stringify()
2026-11-05 09:40:31
