iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >javascript继承的作用是什么
  • 156
分享到

javascript继承的作用是什么

2024-04-02 19:04:59 156人浏览 安东尼
摘要

今天小编给大家分享一下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 ();  //实例化对象book1
var book2 = new Book ();  //实例化对象book2
console.log(book1.o.x);  //返回1
console.log(book2.o.x);  //返回1
book2.o.x = 3;  //修改实例化对象book2中的属性x的值
console.log(book1.o.x);  //返回3
console.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

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

//基类Base
function Base (x) {  //构造函数Base
    this.get = function () {  //私有方法,获取参数值
        return x;
    }
}
Base.prototype.has = function () {  //原型方法,判断get()方法返回值是否为0
    return ! (this.get() == 0);
}
//父类Parent
function 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();
}
//子类Sub
function 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,5
sub.sort();  //排序数组
console.log(sub.geta());  //返回数组10,20,30,40,5,6
console.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);  //实例化类B
console.log(f.get());  //继承类A的方法get(),返回5
console.log(f.add());  //继承类A的方法add(),返回10
console.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继承的作用是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网node.js频道。

--结束END--

本文标题: javascript继承的作用是什么

本文链接: https://www.lsjlt.com/news/88322.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • javascript继承的作用是什么
    今天小编给大家分享一下javascript继承的作用是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起...
    99+
    2024-04-02
  • Javascript的类继承是什么
    本篇内容介绍了“Javascript的类继承是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!说到Jav...
    99+
    2024-04-02
  • VB.NET中继承的作用是什么
    这篇文章给大家介绍VB.NET中继承的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。VB.NET继承相关内容概要:(1)Inherits表述--用来说明当前的类是继承了哪一个已经存在的类(基本类),Inher...
    99+
    2023-06-17
  • javascript中继承指的是什么
    今天小编给大家分享一下javascript中继承指的是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起...
    99+
    2024-04-02
  • JavaScript的继承方式是什么
    本文小编为大家详细介绍“JavaScript的继承方式是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“JavaScript的继承方式是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。JavaScript中...
    99+
    2023-06-30
  • javascript中什么是组合继承
    javascript中什么是组合继承?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、说明用原型链实现原型属性和方法的继承,借用构造函数技术实现实例属性的继承。2、缺点组合模式...
    99+
    2023-06-15
  • JavaScript的继承和原型链是什么
    小编给大家分享一下JavaScript的继承和原型链是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、前言JavaScri...
    99+
    2024-04-02
  • javascript组合继承的意思是什么
    这篇文章主要介绍“javascript组合继承的意思是什么”,在日常操作中,相信很多人在javascript组合继承的意思是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”javascript组合继承的意思...
    99+
    2023-06-20
  • JavaScript实现继承的方法是什么
    这篇文章主要介绍了JavaScript实现继承的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript实现继承的方法是什么文章都会有所收获,下面我们一起来看看吧。0. 继承继承是面向对象编...
    99+
    2023-07-04
  • javascript是怎么实现继承的
    这篇文章将为大家详细讲解有关javascript是怎么实现继承的,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 方法:1、利用原型让一个引用类...
    99+
    2024-04-02
  • javascript的原型式继承的原理是什么
    这篇文章给大家介绍javascript的原型式继承的原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1、说明利用空对象作为中介,将某个对象直接分配给空对象构造函数的原型。2、缺点原型链继承多个实例的引用类型属性...
    99+
    2023-06-15
  • JavaScript中的继承采用什么方式
    这篇文章主要讲解了“JavaScript中的继承采用什么方式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript中的继承采用什么方式”吧! ...
    99+
    2024-04-02
  • javascript继承方法有什么
    本篇内容介绍了“javascript继承方法有什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!javascript继承方法有:1、使用ca...
    99+
    2023-06-14
  • 什么是Java继承
    本篇内容主要讲解“什么是Java继承”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“什么是Java继承”吧!一、继承的概念什么是继承在现实生活中,继承指的是子女继承父辈的财产。在程序中,当一个类A...
    99+
    2023-06-15
  • Javascript继承机制的设计原理是什么
    这篇文章主要讲解了“Javascript继承机制的设计原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Javascript继承机制的设计原理是什么”...
    99+
    2024-04-02
  • c# 继承是什么/怎么用
    本篇内容介绍了“c# 继承是什么/怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在面向对象当中继承是非常重要的,也是面向对象的三大特性...
    99+
    2023-06-14
  • CSS中的继承是什么
    这篇文章主要讲解了“CSS中的继承是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“CSS中的继承是什么”吧!CSS的继承是由所使用的样式属性定义的。换句...
    99+
    2024-04-02
  • css继承性是什么
    这篇“css继承性是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“css继承性是什么”...
    99+
    2024-04-02
  • javascript是如何实现继承的
    本篇内容介绍了“javascript是如何实现继承的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • es6继承的原理是什么
    ES6继承的原理是通过使用`class`关键字和`extends`关键字来创建子类,并通过`super`关键字调用父类的构造函数和方...
    99+
    2023-10-09
    es6
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作