Javascript原型和原型链的详解

2023-09-14 16:00:00

 🎬 岸边的风:个人主页

 🔥 个人专栏 :《 VUE 》 《 javaScript 》

⛺️ 生活的理想,就是为了理想的生活 !

在这里插入图片描述

目录

原型(Prototype)

构造函数和原型对象

原型链

原型继承

1. 对象字面量和 Object.create():可以使用字面量对象定义属性和方法,并使用 Object.create() 方法创建一个新对象,并将其原型设置为现有对象的原型。

2. 构造函数和 Object.create():可以使用构造函数定义对象,并通过 Object.create() 方法将新对象的原型连接到现有对象的原型上。

3. 构造函数和 new 关键字:可以使用构造函数创建对象实例,并使用 new 关键字进行实例化。

4. 寄生组合继承


JavaScript是一门支持面向对象编程的语言,它的函数是第一公民,同时也拥有类的概念。不同于传统的基于类的继承,JavaScript的类和继承是基于原型链模型的。在ES2015/ES6中引入了class关键字,但其本质仍然是基于原型链的语法糖。

proto

原型(Prototype)

原型(Prototype)是JavaScript中对象的一个特殊属性,它用于实现属性和方法的继承。在JavaScript中,每个对象都有一个原型属性,它指向另一个对象,这个对象被称为原型对象。通过原型链,对象可以从原型对象继承属性和方法。

原型的概念可以用以下方式解释:每个JavaScript对象都是基于一个构造函数创建的,构造函数是对象的模板或蓝图。在创建对象时,构造函数会创建一个关联的原型对象,对象通过原型链继承原型对象上的属性和方法。原型对象是一个普通的JavaScript对象,它具有自己的属性和方法。

让我们以一个示例来说明原型的概念和作用:

// 构造函数
function Person(name) {
  this.name = name;
}

// 在原型对象上添加方法
Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name);
};

// 创建实例
var person1 = new Person("John");
var person2 = new Person("Alice");

// 调用原型对象上的方法
person1.sayHello(); // 输出: "Hello, my name is John"
person2.sayHello(); // 输出: "Hello, my name is Alice"

在这个示例中,我们定义了一个构造函数Person,它有一个name属性。然后,我们通过给原型对象Person.prototype添加一个sayHello方法,使得所有通过Person构造函数创建的实例都可以访问该方法。我们创建了两个实例person1person2,并分别调用了sayHello方法。

原型的重要性体现在以下几个方面:

  1. 继承:原型链允许对象继承其原型对象上的属性和方法。通过原型链,子对象可以访问和复用父对象的属性和方法,实现了继承的概念。

  2. 代码复用和共享:通过将方法和属性定义在原型对象上,可以实现多个对象共享相同的方法和属性。这样可以节省内存空间,提高性能,同时也方便了代码的维护和扩展。

           +----------------------+
           |     Object.prototype |
           +----------------------+
                      ^
                      |
           +----------------------+
           |    Constructor.prototype |
           +----------------------+
                      ^
                      |
           +----------------------+
           |       Object instance |
           +----------------------+

在这个示意图中,Object.prototype是所有对象的原型,Constructor.prototype是构造函数的原型,Object instance是基于构造函数创建的对象实例。

构造函数和原型对象

构造函数是用于创建对象的特殊函数。它通常以大写字母开头,通过使用 new 关键字来调用构造函数,我们可以创建一个新的对象实例。构造函数在创建对象时可以执行一些初始化操作,并为对象添加属性和方法。

原型对象是构造函数的一个属性,它是一个普通的 JavaScript 对象。原型对象上的属性和方法可以被通过构造函数创建的对象实例所继承。通过将属性和方法定义在原型对象上,我们可以实现方法的共享和节省内存空间。

让我们通过一个示例来说明构造函数和原型对象的概念以及如何使用它们来创建对象和共享方法:

// 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 在原型对象上添加方法
Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
};

// 创建对象实例
var person1 = new Person("John", 25);
var person2 = new Person("Alice", 30);

// 调用共享的方法
person1.sayHello(); // 输出: "Hello, my name is John and I am 25 years old."
person2.sayHello(); // 输出: "Hello, my name is Alice and I am 30 years old."

在这个示例中,我们定义了一个构造函数 Person,它接受 name 和 age 参数,并将它们赋值给对象的属性。然后,我们通过在原型对象 Person.prototype 上添加一个方法 sayHello,使得通过 Person 构造函数创建的对象实例可以访问该方法。我们创建了两个对象实例 person1 和 person2,并分别调用了共享的方法 sayHello

+----------------------------------+
|           Constructor            |
|                                  |
|  +--------------------------+    |
|  |   Prototype Properties   |    |
|  +--------------------------+    |
|                                  |
|  - Property: name               |
|  - Property: age                |
|  - Method: sayHello()           |
|                                  |
+----------------------------------+
        ^
        |
        |
+----------------------------------+
|          Object Instance         |
|                                  |
|  +--------------------------+    |
|  |     Instance Properties   |    |
|  +--------------------------+    |
|                                  |
|  - Property: name               |
|  - Property: age                |
|                                  |
+----------------------------------+

在这个示意图中,构造函数和原型对象之间存在关联,构造函数拥有原型对象的引用。通过构造函数,我们可以创建对象实例,并且这些实例可以通过原型对象继承原型上的属性和方法。

原型链

原型链是 JavaScript 中对象之间通过原型链接起来的机制,用于实现属性和方法的继承。它是由一系列的原型对象组成,每个对象都有一个指向其原型对象的连接,形成了一条链式结构。

原型链的概念可以通过以下方式解释:在 JavaScript 中,每个对象都有一个内部属性 [[Prototype]](__proto__),它指向该对象的原型。当我们访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎会自动沿着原型链向上查找,直到找到匹配的属性或方法或者到达原型链的顶部(Object.prototype)。

让我们通过一个示例来说明原型链的概念和工作原理:

// 父对象构造函数
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);

// 创建子对象实例
var child = new Child();

// 调用父对象原型上的方法
child.sayHello(); // 输出: "Hello, I am Child"

在这个示例中,我们定义了一个父对象构造函数 Parent,它有一个属性 name 和一个原型方法 sayHello。然后,我们定义了一个子对象构造函数 Child,它也有一个属性 name。通过 Object.create() 方法,我们将子对象的原型连接到父对象的原型上,建立了子对象和父对象之间的原型链关系。最后,我们创建了子对象实例 child,并调用了父对象原型上的方法 sayHello

           +----------------------+
           |     Object.prototype |
           +----------------------+
                      ^
                      |
           +----------------------+
           |   Parent.prototype    |
           +----------------------+
                      ^
                      |
           +----------------------+
           |   Child.prototype     |
           +----------------------+
                      ^
                      |
           +----------------------+
           |     Child instance    |
           +----------------------+

在这个示意图中,Object.prototype 是所有对象的顶层原型,Parent.prototype 是父对象的原型,Child.prototype 是子对象的原型,Child instance 是基于子对象构造函数创建的对象实例。

原型链的重要性体现在以下几个方面:

  1. 继承:原型链允许对象通过继承获取其他对象的属性和方法。子对象可以继承父对象的属性和方法,而父对象又可以继承更上层对象的属性和方法,以此类推。

  2. 代码复用和共享:通过原型链,我们可以在原型对象

上定义方法和属性,从而实现多个对象之间的方法共享和代码复用。这样可以节省内存空间,提高性能,并减少代码的冗余。

  1. 扩展和修改:通过在原型对象上添加新的方法和属性,我们可以在整个原型链中的所有对象实例上访问和使用这些扩展。这样可以方便地对现有对象进行功能扩展和修改。

原型继承

原型继承是一种通过继承原型对象来创建新对象的方式。在 JavaScript 中,我们可以使用多种方式实现原型继承。原型继承的概念是通过将一个对象作为另一个对象的原型来实现继承,从而使新对象可以共享原型对象的属性和方法。

1. 对象字面量和 Object.create():可以使用字面量对象定义属性和方法,并使用 Object.create() 方法创建一个新对象,并将其原型设置为现有对象的原型。

var parent = {
  name: "Parent",
  sayHello: function() {
    console.log("Hello, I am " + this.name);
  }
};

var child = Object.create(parent);
child.name = "Child";

2. 构造函数和 Object.create():可以使用构造函数定义对象,并通过 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");

3. 构造函数和 new 关键字:可以使用构造函数创建对象实例,并使用 new 关键字进行实例化。

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");

4. 寄生组合继承

寄生组合继承是一种常用的原型继承方式,结合了构造函数继承和原型链继承的优点,避免了原型链中不必要的属性复制和方法重复定义的问题。这种方式先通过构造函数继承属性,然后通过设置原型链继承方法。

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log("Hello, I am " + this.name);
};

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child("Child", 10);

以上是常用的原型继承实现方式,每种方式都有其特点和适用场景。根据具体的需求和代码结构,可以选择最适合的方式来实现原型继承

更多推荐

web大作业 比赛报名页面+ 团队介绍页面 制作

web大作业比赛报名页面+团队介绍页面制作【附源代码】文章目录web大作业比赛报名页面+团队介绍页面制作【附源代码】前言报名界面效果图如下:代码实现计时器效果实现(jquery+boostrap)团队介绍页面模拟框代码:CSS代码前言之前没看过看过上一篇文章的小伙伴,可以看一下之前的文章,里面有一些组件设计是下面没有提

Navidrome - 开源音乐服务器【打造属于自己的音乐播放器】「端口映射」随时随地想听就听

转载自cpolar极点云文章:Navidrome-开源音乐服务器【打造属于自己的音乐播放器】「端口映射」随时随地想听就听1.前言不知从何时开始,我们能用的音乐软件越来越少,笔者使用小米手机很久了,自从小米手机的自带音乐播放器变成了QQ音乐,笔者手机里很多的音乐就无法再自由畅听,要求付费加会员听歌,不然就得忍受被剪切的试

网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)

目录Java网络编程中的常用类TCP通信的实现和项目案例TCP通信入门案例TCP单向通信TCP双向通信创建点对点的聊天应用一对多应用一对多聊天服务器Java网络编程中的常用类Java为了跨平台,在网络应用通信时是不允许直接调用操作系统接口的,而是由java.net包来提供网络功能。下面我们来介绍几个java.net包中

【JAVA】多态的概念与实际利用

个人主页:【😊个人主页】系列专栏:【❤️初识JAVA】前言在面向对象(OOP)的程序设计语言中,多态与封装、继承合称为OOP的三大特性。在今天,我们就来学习一下JAVA中的多态是什么样子的。、多态指一个对象在不同情况下可以表现出不同的行为。Java多态性分为两种:编译时多态性(静态多态性)和运行时多态性(动态多态性)

【三维重建】3D Gaussian Splatting:实时的神经场渲染

文章目录摘要一、前言二、相关工作1.传统的场景重建与渲染2.神经渲染和辐射场3.基于点的渲染和辐射场4.*什么是Tile-basedrasterizer(快速光栅化)三、OVERVIEW四、可微的三维高斯Splatting五、三维高斯自适应密度控制的优化1.优化2.高斯的自适应控制六、高斯分布的快速可微光栅化器(拓展)

DevSecOps内置安全保护

前言随着DevOps的发展,DevOps大幅提升了企业应用迭代的速度。但同时,安全如果不能跟上步伐,不仅会抵消DevOps变革带来的提升,拖慢企业数字化转型进程,还会导致漏洞与风险不约而至。所以安全能力在全球范围内受到的重视越来越高,软件开发内生的安全性成为评价企业DevOps成熟度水平的重要指标。一直以来,业界长期重

自己实现 SpringMVC 底层机制 系列之-实现任务阶段 8- 完成返回 JSON 格式数据-@ResponseBody

😀前言自己实现SpringMVC底层机制系列之-实现任务阶段8-完成返回JSON格式数据-@ResponseBody🏠个人主页:尘觉主页🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉在csdn获奖荣誉:🏆csdn城市之星2名⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣

有机化学英文单词组成以及命名规则

当涉及到有机化合物的命名时,有各种不同的组成部分和功能团可以组合在一起。以下是一些常见的有机功能团和它们的英文名称:|中文|英文||--------------|--------------------||甲基|Methyl||乙基|Ethyl||酸|Acid||醇|Alcohol||醚|Ether||醛|Aldehy

ElasticSearch(三)

1.数据聚合聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:什么品牌的手机最受欢迎?这些手机的平均价格、最高价格、最低价格?这些手机每月的销售情况如何?实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。1.1.聚合的种类聚合常见的有三类:桶

大语言模型之十-Byte Pair Encoding

Tokenizer诸如GPT-3/4以及LlaMA/LlaMA2大语言模型都采用了token的作为模型的输入输出,其输入是文本,然后将文本转为token(正整数),然后从一串token(对应于文本)预测下一个token。进入OpenAI官网提供的tokenizer可以看到GPT-3tokenizer采用的方法。这里以H

面试中的数据可视化:如何用数据支持你的观点

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

热文推荐