千家信息网

javascript继承的作用是什么

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天小编给大家分享一下javascript继承的作用是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我
千家信息网最后更新 2026年11月01日javascript继承的作用是什么

今天小编给大家分享一下javascript继承的作用是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

javascript继承的作用:1、可以不调用"父类"的构造方法就创造新的实例;2、修改"父类"的prototype可以动态修改所有已经创造的实例;3、可以动态修改一个对象的原型。

本教程操作环境:windows7系统、javascript1.8.5版、Dell G3电脑。

JavaScript 是以对象为基础,以函数为模型,以原型为继承的面向对象开发模式。

javascript继承的作用:

1、可以不调用「父类」的构造方法就创造新的实例

2、修改「父类」的 prototype 可以动态修改所有已经创造的实例

3、可以动态修改一个对象的原型,也就是说爹妈可以换

下面介绍定义 JavaScript 类型的方法,以及实现继承的常用模式。

构造原型

直接使用 prototype 原型设计类的继承存在两个问题。

由于构造函数事先声明,而原型属性在类结构声明之后才被定义,因此无法通过构造函数向原型动态传递参数。这样实例化对象都是一个模样,没有个性。要改变原型属性值,则所有实例都会受到干扰。

当原型属性的值为引用类型数据时,如果在一个对象实例中修改该属性值,将会影响所有的实例。

示例1

简单定义 Book 类型,然后实例化。

function Book () {};  //声明构造函数Book.prototype.o = {x : 1, y : 2};  //构造函数的原型属性o是一个对象var book1 = new Book ();  //实例化对象book1var book2 = new Book ();  //实例化对象book2console.log(book1.o.x);  //返回1console.log(book2.o.x);  //返回1book2.o.x = 3;  //修改实例化对象book2中的属性x的值console.log(book1.o.x);  //返回3console.log(book2.o.x);  //返回3

由于原型属性 o 为一个引用型的值,所以所有实例的属性 o 的值都是同一个对象的引用,一旦 o 的值发生变化,将会影响所有实例。

构造原型正是为了解决原型模式而诞生的一种混合设计模式,它把构造函数模式与原型模式混合使用,从而避免了上述问题的发生。

实现方法:对于可能会相互影响的原型属性,并且希望动态传递参数的属性,可以把它们独立出来使用构造函数模式进行设计。对于不需要个性设计、具有共性的方法或属性,则可以使用原型模式来设计。

示例2

遵循上述设计原则,把其中两个属性设计为构造函数模式,设计方法为原型模式。

function Book (title, pages) {  //构造函数模式设计    this.title = title;    this.pages = pages;}Book.prototype.what = function () {  //原型模式设计    console.log(this.title + this.pages);};var book1 = new Book("JavaScript 程序设计", 160);var book2 = new Book("C语言程序设计", 240);console.log(book1.title);console.log(book2.title);

构造原型模式是 ECMAScript 定义类的推荐标准。一般建议使用构造函数模式定义所有属性,使用原型模式定义所有方法。这样所有方法都只创建一次,而每个实例都能够根据需要设置属性值。这也是使用最广的一种设计模式。

动态原型

根据面向对象的设计原则,类型的所有成员应该都被封装在类结构体内。例如:

function Book (title, pages) {  //构造函数模式设计    this.title = title;    this.pages = pages;    Book.prototype.what = function () {  //原型模式设计,位于类的内部        console.log(this.title + this.pages);    };}

但当每次实例化时,类 Book 中包含的原型方法就会被重复创建,生成大量的原型方法,浪费系统资源。可以使用 if 判断原型方法是否存在,如果存在就不再创建该方法,否则就创建方法。

function Book (title, pages) {    this.title = title;    this.pages = pages;    if (typeof Book.isLock == "undefined") {  //创建原型方法的锁,如果不存在则创建        Book.prototype.what = function () {            console.log(this.title + this.pages);        };        Book.isLock = true;  //创建原型方法后,把锁锁上,避免重复创建    }}var book1 = new Book("JavaScript 程序设计", 160);var book2 = new Book("C语言程序设计", 240);console.log(book1.title);console.log(book2.title);

typeof Book.isLock 表达式能够检测该属性值的类型,如果返回为 undefined 字符串,则不存在该属性值,说明没有创建原型方法,并允许创建原型方法,设置该属性的值为 true,这样就不用重复创建原型方法。这里使用类名 Book,而没有使用 this,这是因为原型是属于类本身的,而不是对象实例的。

动态原型模式与构造原型模式在性能上是等价的,用户可以自由选择,不过构造原型模式应用比较广泛。

工厂模式

工厂模式是定义类型的最基本方法,也是 JavaScript 最常用的一种开发模式。它把对象实例化简单封装在一个函数中,然后通过调用函数,实现快速、批量生产实例对象。

示例1

下面示例设计一个 Car 类型:包含汽车颜色、驱动轮数、百公里油耗 3 个属性,同时定义一个方法,用来显示汽车颜色。

function Car (color, drive, oil) {  //汽车类    var _car =  new Object();  //临时对象        _car.color = color;  //初始化颜色        _car.drive = drive;  //初始化驱动轮数        _car.oil = oil;  //初始化百公里油耗        _car.showColor = function () {  //方法,提示汽车颜色            console.log(this.color);        };        return _car;  //返回实例}var car1 = Car("red", 4, 8);var car2 = Car("blue", 2, 6);car1.showColor();  //输出"red"car2.showColor();  //输出"blue"

上面代码是一个简单的工厂模式类型,使用 Car 类可以快速创建多个汽车实例,它们的结构相同,但是属性不同,可以初始化不同的颜色、驱动轮数和百公里油耗。

示例2

在类型中,方法就是一种行为或操作,它能够根据初始化参数完成特定任务,具有共性。因此,可以考虑把方法置于 Car() 函数外面,避免每次实例化时都要创建一次函数,让每个实例共享同一个函数。

function showColor () {  //公共方法,提示汽车颜色    console.log(this.color);};function Car (color, drive, oil) {  //汽车类    var _car = new Object();  //临时对象        _car.color = color;  //初始化颜色        _car.drive = drive;  //初始化驱动轮数        _car.oil = oil;  //初始化百公里油耗        _car.showColor = showColor;  //引用外部函数    return _car;  //返回实例}

在上面这段重写的代码中,在函数 Car() 之前定义了函数 showColor()。在 Car() 内部,通过引用外部 showColor() 函数,避免了每次实例化时都要创建一个新的函数。从功能上讲,这样解决了重复创建函数的问题;但是从语义上讲,该函数不太像是对象的方法。

类继承

类继承的设计方法:在子类中调用父类构造函数。

在 JavaScript 中实现类继承,需要注意以下 3 个技术问题。

在子类中,使用 apply 调用父类,把子类构造函数的参数传递给父类父类构造函数。让子类继承父类的私有属性,即 Parent.apply(this, arguments); 代码行。

在父类和子类之间建立原型链,即 Sub.prototype = new Parent(); 代码行。通过这种方式保证父类和子类是原型链上的上下级关系,即子类的 prototype 指向父类的一个实例。

恢复子类的原型对象的构造函数,即 Sub.prototype.constructor=Sub;语句行。当改动 prototype 原型时,就会破坏原来的 constructor 指针,所以必须重置 constructor。

示例1

下面示例演示了一个三重继承的案例,包括基类、父类和子类,它们逐级继承。

//基类Basefunction Base (x) {  //构造函数Base    this.get = function () {  //私有方法,获取参数值        return x;    }}Base.prototype.has = function () {  //原型方法,判断get()方法返回值是否为0    return ! (this.get() == 0);}//父类Parentfunction Parent () {  //构造函数Parent    var a = [];  //私有数组a    a = Array.apply(a, arguments);  //把参数转换为数组    Base.call(this, a.length);  //调用Base类,并把参数数组长度传递给它    this.add = function () {  //私有方法,把参数数组补加到数组a中并返回        return a.push.apply(a, arguments)    }    this.geta = function () {  //私有方法,返回数组a        return a;    }}Parent.prototype = new Base();  //设置Parent原型为Base的实例,建立原型链Parent.prototype.constructor = Parent;  //恢复Parent类原型对象的构造器Parent.prototype.str = function (){  //原型方法,把数组转换为字符串并返回    return this.geta().toString();}//子类Subfunction Sub () {  //构造函数    Parent.apply(this, arguments);  //调用Parent类,并把参数数组长度传递给它    this.sort = function () {  //私有方法,以字符顺序对数组进行排序        var a = this.geta();  //获取数组的值        a.sort.apply(a, arguments);  //调用数组排序方法 sort()对数组进行排序    }}Sub.prototype = new Parent();  //设置Sub原型为Parent实例,建立原型链Sub.prototype.constructor = Sub;  //恢复Sub类原型对象的构造器//父类Parent的实例继承类Base的成员var parent = new Parent (1, 2, 3, 4);  //实例化Parent类console.log(parent.get());  //返回4,调用Base类的方法get()console.log(parent.has());  //返回true,调用Base类的方法has()//子类Sub的实例继承类Parent和类Base的成员var sub = new Sub (30, 10, 20, 40);  //实例化Sub类sub.add(6, 5);  //调用Parent类方法add(),补加数组console.log(sub.geta());  //返回数组30,10,20,40,6,5sub.sort();  //排序数组console.log(sub.geta());  //返回数组10,20,30,40,5,6console.log(sub.get());  //返回4,调用Base类的方法get()console.log(sub.has());  //返回true,调用Base类的方法has()console.log(sub.str());  //返回10,20,30,40,5,6

【设计思路】

设计子类 Sub 继承父类 Parent,而父类 Parent 又继承基类 Base。Base、Parent、Sub 三个类之间的继承关系是通过在子类中调用的构造函数来维护的。

例如,在 Sub 类中,Parent.apply(this, arguments); 能够在子类中调用父类,并把子类的参数传递给父类,从而使子类拥有父类的所有属性。

同理,在父类中,Base.call(this, a.length); 把父类的参数长度作为值传递给基类,并进行调用,从而实现父类拥有基类的所有成员。

从继承关系上看,父类继承了基类的私有方法 get(),为了确保能够继承基类的原型方法,还需要为它们建立原型链,从而实现原型对象的继承关系,方法是添加语句行 Parent.prototype=new Base();。

同理,在子类中添加语句 Sub.prototype=new Parent();,这样通过原型链就可以把基类、父类和子类串连在一起,从而实现子类能够继承父类属性,还可以继承基类的属性。

示例2

下面尝试把类继承模式封装起来,以便规范代码应用。

function extend (Sub, Sup) {  //类继承封装函数    var F = function () {};  //定义一个空函数    F.prototype = Sup.prototype;  //设置空函数的原型为父类的原型    Sub.prototype = new F ();  //实例化空函数,并把父类原型引用传给给子类    Sub.prototype.constructor = Sub;  //恢复子类原型的构造器为子类自身    Sub.sup = Sup.prototype;  //在子类定义一个私有属性存储父类原型    //检测父类原型构造器是否为自身    if (Sup.prototype.constructor == Object.prototype.constructor) {        Sup.prototype.constructor = Sup;  //类继承封装函数    }}

【操作步骤】

1) 定义一个封装函数。设计入口为子类和父类对象,函数功能是子类能够继承父类的所有原型成员,不涉及出口。

function extend (Sub, Sup) {  //类继承封装函数    //其中参数Sub表示子类,Sup表示父类}

2) 在函数体内,首先定义一个空函数 F,用来实现功能中转。设计它的原型为父类的原型,然后把空函数的实例传递给子类的原型,这样就避免了直接实例化父类可能带来的系统负荷。因为在实际开发中,父类的规模可能会很大,如果实例化,会占用大量内存。

3) 恢复子类原型的构造器为子类自己。同时,检测父类原型构造器是否与 Object 的原型构造器发生耦合。如果是,则恢复它的构造器为父类自身。

下面定义两个类,尝试把它们绑定为继承关系。

function A (x) {  //构造函数A    this.x = x;  //私有属性x    this.get = function () {  //私有方法get()        return this.x;    }}A.prototype.add = function () {  //原型方法add()    return this.x + this.x;}A.prototype.mul = function () {  //原型方法mul()    return this.x * this.x;}function B (x) {  //构造函数B    A.call (this.x);  //在函数体内调用构造函数A,实现内部数据绑定}extend (B, A);  //调用封装函数,把A和B的原型捆绑在一起var f = new B (5);  //实例化类Bconsole.log(f.get());  //继承类A的方法get(),返回5console.log(f.add());  //继承类A的方法add(),返回10console.log(f.mul());  //继承类A的方法mul(),返回25

在函数类封装函数中,有这么一句 Sub.sup=Sup.prototype;,在上面代码中没有被利用,那么它有什么作用呢?为了解答这个问题,先看下面的代码。

extend (B, A);B.prototype.add = function () {  //为B类定义一个原型方法    return this.x + "" + this.x;}

上面的代码是在调用封装函数之后,再为 B 类定义了一个原型方法,该方法名与基类中原型方法 add() 同名,但是功能不同。如果此时测试程序,会发现子类 B 定义的原型方法 add() 将会覆盖父类 A 的原型方法 add()。

console.log(f.add());  //返回字符串55,而不是数值10

如果在 B 类的原型方法 add() 中调用父类的原型方法 add(),避免代码耦合现象发生。

B.prototype.add = function () {  //定义子类B的原型方法add()    return B.sup.add.call(this);  //在函数内部调用父类方法add()}

以上就是"javascript继承的作用是什么"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

原型 方法 函数 实例 子类 模式 属性 设计 对象 数组 参数 封装 私有 代码 类型 动态 示例 构造器 汽车 颜色 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 保险科技 互联网保险 华服互联网科技怎么样 西安纸贵互联网科技有限公司 科技金融是不是互联网金融 互联网科技公司的优势 科技创新与互联网经济 互联网科技未来 互联网科技公司名称 互联网科技公司做什么 富国互联网科技创新基金 湖南洣水互联网科技有限公司扣款 济南华为互联网科技产业总部基地 北京华百购互联网科技有限公司 汽车互联网创新科技园 湖南诚度互联网科技有限公司 互联网科技扶贫时间 长沙茂晟互联网科技有限公司 互联网金融科技元年 美国互联网科技公司 数字科技和互联网金融哪个好 喔噻互联网科技 互联网科技公司电话 奇酷互联网科技公司 深圳艾佳互联网科技 互联网科技股有哪些 米聚互联网科技南京有限公司排面 四川慕妮娅互联网科技有限公司 烟台灵鸽互联网科技有限公司 黑云互联网科技有限公司 江苏互联网智能科技产品出厂价
0