浅析JS中的原型,原型链和继承

 更新时间:2023年09月06日 14:27:52   作者:一花一world  
经典模式和圣杯模式都是用于解决构造函数继承和原型继承的问题,但它们在实现继承的方式上有所不同,本文主要来和大家聊聊经典模式和圣杯模式下原型,原型链和继承的实现,需要的可以参考下

经典模式和圣杯模式区别

经典模式和圣杯模式都是用于解决构造函数继承和原型继承的问题,但它们在实现继承的方式上有所不同。

经典模式是通过将子类的原型对象设置为父类的实例来实现继承,然后将子类的构造函数设置为子类本身。这样子类既可以继承父类的属性,也可以继承父类原型对象的方法。但是经典模式存在一个问题,就是每次创建子类的实例时都会调用一次父类的构造函数,导致父类的属性被重复初始化。

圣杯模式是在经典模式的基础上进行了改进,通过使用一个中间函数来实现继承。这个中间函数将父类的原型对象赋值给一个临时的构造函数,并将子类的原型对象设置为这个临时构造函数的实例。这样子类既可以继承父类原型对象的方法,又不会重复调用父类的构造函数。此外,圣杯模式还通过将子类的原型对象的constructor属性设置为子类本身来修复原型链断裂的问题。

下面是经典模式和圣杯模式的代码示例:

经典模式:

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child(name) {
  Parent.call(this, name);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

圣杯模式:

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function inherit(C, P) {
  function F() {}
  F.prototype = P.prototype;
  C.prototype = new F();
  C.prototype.constructor = C;
}
function Child(name) {
  Parent.call(this, name);
}
inherit(Child, Parent);

经典模式和圣杯模式都是用于实现继承的方式,但圣杯模式在解决经典模式中的问题上更加优化和完善。

圣杯模式

1. 原型

原型是JavaScript中用来实现对象之间继承关系的概念。每个JavaScript对象都有一个原型对象,它是一个普通的对象,包含了对象的属性和方法。当我们访问一个对象的属性或方法时,如果对象本身不存在该属性或方法,JavaScript会自动去原型对象中查找。

2. 原型链

原型链是一种通过原型对象来实现对象之间继承关系的机制。每个对象都有一个原型对象,通过原型链,一个对象可以访问其原型对象的属性和方法。原型链是由一系列原型对象组成的,当我们访问一个对象的属性或方法时,JavaScript会自动沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端。

3. 继承

继承是一种面向对象编程中的重要概念,它允许我们创建一个新的对象,并从一个已有的对象中继承属性和方法。通过继承,我们可以避免重复编写相同的代码,提高代码的复用性和可维护性。

相应的代码示例

a. 原型链继承

原型链继承是一种简单的继承方式,它通过将子类的原型对象设置为父类的实例来实现继承。这样子类就可以访问父类原型对象的属性和方法。

function Parent() {
  this.name = 'Parent';
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child() {
  this.name = 'Child';
}
Child.prototype = new Parent();
var child = new Child();
child.sayHello(); // 输出: Hello, I am Child

在这个例子中,我们定义了一个父类Parent和一个子类Child。在子类中,我们将其原型对象设置为父类的实例,这样子类就可以继承父类的属性和方法。在子类的实例中,我们可以调用父类原型对象的方法。

b. 构造函数继承

构造函数继承是一种通过调用父类的构造函数来实现继承的方式。子类通过调用父类的构造函数来继承父类的属性,并在子类的构造函数中使用call方法来调用父类的构造函数。

function Parent(name) {
  this.name = name;
}
function Child(name) {
  Parent.call(this, name);
}
var child = new Child('Child');
console.log(child.name); // 输出: Child

在这个例子中,我们定义了一个父类Parent和一个子类Child。在子类的构造函数中,我们使用call方法调用父类的构造函数,并将子类的实例作为this参数传递给父类的构造函数。这样子类就可以继承父类的属性。

c. 组合继承

组合继承是一种通过同时使用原型链继承和构造函数继承来实现继承的方式。它通过将子类的原型对象设置为父类的实例,并在子类的构造函数中调用父类的构造函数来实现继承。

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child(name) {
  Parent.call(this, name);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child = new Child('Child');
child.sayHello(); // 输出: Hello, I am Child

在这个例子中,我们定义了一个父类Parent和一个子类Child。在子类的构造函数中,我们使用call方法调用父类的构造函数,并将子类的实例作为this参数传递给父类的构造函数。然后,我们将子类的原型对象设置为父类的实例,并将子类的构造函数设置为子类本身。这样子类既可以继承父类的属性,也可以继承父类原型对象的方法。

详细代码说明

a. 原型链继承

function Parent() {
  this.name = 'Parent';
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child() {
  this.name = 'Child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child = new Child();
child.sayHello(); // 输出: Hello, I am Child

在这个例子中,我们使用Object.create()方法将子类的原型对象设置为父类的原型对象的一个副本。这样子类就可以继承父类原型对象的属性和方法。

b. 构造函数继承

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child(name) {
  Parent.call(this, name);
}
var child = new Child('Child');
child.sayHello(); // 输出: TypeError: child.sayHello is not a function

在这个例子中,我们通过调用父类的构造函数来继承父类的属性,但是子类无法继承父类原型对象的方法。

c. 组合继承

在这个例子中,我们使用Object.create()方法将子类的原型对象设置为父类的原型对象的一个副本,并将子类的构造函数设置为子类本身。这样子类既可以继承父类的属性,也可以继承父类原型对象的方法。

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
}
function Child(name) {
  Parent.call(this, name);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child = new Child('Child');
child.sayHello(); // 输出: Hello, I am Child

到此这篇关于浅析JS中的原型,原型链和继承的文章就介绍到这了,更多相关JS原型 原型链 继承内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 微信小程序实战之自定义toast(6)

    微信小程序实战之自定义toast(6)

    这篇文章主要为大家详细介绍了微信小程序实战之自定义toast的相关方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • 小程序云开发教程如何使用云函数实现点赞功能

    小程序云开发教程如何使用云函数实现点赞功能

    这篇文章主要为大家详细介绍了小程序云开发教程如何使用云函数实现点赞功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • Rollup处理并打包JS文件项目实例代码

    Rollup处理并打包JS文件项目实例代码

    rollup是一款用来es6模块打包代码的构建工具(支持css和js打包)。这篇文章主要介绍了Rollup处理并打包JS文件项目实例,需要的朋友可以参考下
    2018-05-05
  • JS控件的生命周期介绍

    JS控件的生命周期介绍

    JS控件的生命周期跟其他平台UI的生命周期类似,但是又有自己的特点,我们只有将控件的生命周期划分清晰,所有的控件编写、mixins的编写和plugin的编写才能遵循控件的生命周期做统一的管理
    2012-10-10
  • three.js中gsap动画库实现物体的动画

    three.js中gsap动画库实现物体的动画

    本文主要介绍了three.js中gsap动画库实现物体的动画,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Highcharts使用简例及异步动态读取数据

    Highcharts使用简例及异步动态读取数据

    Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习、个人网站和非商业用途使用,通过本文给大家介绍Highcharts使用简例及异步动态读取数据的相关知识,感兴趣的朋友一起学习吧
    2015-12-12
  • js表数据排序 sort table data

    js表数据排序 sort table data

    对于表格的排序,是很不错的一个功能,方便用户快速的分析一些数据。
    2009-02-02
  • 兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码

    兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码

    html里的marqueen也能实现内容的滚动,但滚动是间断的,运用JavaScript可以使这一问题得到改观,实现无间断的滚动,让页面看起来更美观
    2013-04-04
  • js print打印网页指定区域内容的简单实例

    js print打印网页指定区域内容的简单实例

    下面小编就为大家带来一篇js print打印网页指定区域内容的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • 详解JavaScript表单验证(E-mail 验证)

    详解JavaScript表单验证(E-mail 验证)

    这篇文章主要为大家详细介绍了JavaScript表单验证,重点介绍了E-mail验证,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03

最新评论