JS 原型和原型链

server/2024/10/21 7:56:19/

构造函数

封装是面向对象思想中比较重要的一部分,js 面向对象可以通过构造函数实现的封装。

  • 同样的将变量和函数组合到了一起并能通过 this 实现数据的共享,所不同的是 JS 借助构造函数创建出来的实例对象之间是彼此不影响的

在这里插入图片描述

  • 存在浪费内存的问题,我们希望所有的对象使用同一个函数,这样就比较节省内存,那么我们要怎样做呢?
    在这里插入图片描述

原型

1、prototype

目标:能够利用原型对象实现方法共享

  • 构造函数通过原型分配的函数是所有对象所 共享的

  • JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象

  • 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存

  • 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

  • 构造函数和原型对象中的this 都指向 实例化的对象

  • 注意:这里不可以使用箭头函数,因为箭头函数的this指向上一层

应用

举例【 我们可以把那些不变的方法,直接定义在 prototype 对象上】

javascript"> // 我们可以把那些不变的方法,直接定义在 prototype 对象上function Star(uname, age) {this.uname = unamethis.age = age}Star.prototype.sing = function() {console.log(唱歌)}const ldh = new Star('刘德华',55)const zxy = new Star('张学友',58)console.log(ldh.sing === zxy.sing); //true

【构造函数和原型对象中的this 都指向 实例化的对象】

javascript"> let thatfunction Star(uname) {that = thisthis.uname = uname}let that2Star.prototype.sing = function() {that2 = thisconsole.log('唱歌');}// 构造函数中的this指向实例化对象const ldh = new Star('刘德华')console.log(that === ldh) // true// 原型对象中的this指向实例化对象ldh.sing()console.log(that2 === ldh) // true

①:给数组扩展求最大值方法和求和方法

比如: 以前学过 const arr = [1,2,3]。arr.reverse() 结果是 [3,2,1]

扩展完毕之后:arr.sum() 返回的结果是 6

javascript">  // 求最大值Array.prototype.max = function() {return Math.max(...this) // 展开运算符}Array.prototype.min = function() {return Math.min(...this) // 展开运算符}Array.prototype.sum = function() {return this.reduce( (prev,item)=> prev + item,0)}const arr = new Array(1,2,3) // 数组实例化console.log(arr);console.log(arr.max());console.log(arr.min());console.log(arr.sum());

2、constructor 属性

每个原型对象 prototype 里面都有个constructor 属性(constructor 构造函数)

作用: 该属性指向该原型对象的构造函数, 简单理解,就是指向我的爸爸,我是有爸爸的孩子

在这里插入图片描述

javascript">  function Star() {}const ldh = new Star()console.log(Star.prototype.constructor === Star); // true

constructor 的具体作用讲解:

javascript">  // 背景需求:我们在原型中添加函数的时候,有可能需要一次性加很多个。function Star2() {}// Star2.prototype.sing = function() {//   console.log('唱歌');// }// Star2.prototype.dance = function() {//   console.log('跳舞');// }console.log(Star2.prototype); // {constructor: ƒ}console.log(Star2.prototype.constructor); //ƒ Star2() {}// 我们想到或许可以用这种方法添加函数:Star2.prototype = {sing: function() {console.log('唱歌');},dance: function() {console.log('跳舞');}}console.log(Star2.prototype); //{sing: ƒ, dance: ƒ}console.log(Star2.prototype.constructor); // ƒ Object() { [native code] }// 但是这种方式出现了问题,这样子的prototype是赋值,不是追加。// 原型失去了原本的constructor
javascript">// 解决方法是 加一条constructor: Star 重新指回去。这就是加一条constructor的用处Star2.prototype = {constructor: Star,sing: function() {console.log('唱歌');},dance: function() {console.log('跳舞');}}console.log(Star2.prototype); // {sing: ƒ, dance: ƒ}console.log(Star2.prototype.constructor); // ƒ Star2() {}

3、对象原型

在这里插入图片描述
对象都会有一个属性 __proto__指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

在这里插入图片描述
__proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数

javascript">  function Star() {}const ldh = new Star()console.log(ldh);// 当前实例对象指向哪个原型对象prototypeconsole.log(ldh.__proto__ === Star.prototype); //true// __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数console.log(ldh.__proto__.constructor === Star); //true

构造函数、实例对象、原型的关系

先有构造函数 function Star。用户通过 new Star,创建实例对象。构造函数 Star中 有属性:prototype原型(因为原型是一个对象,所以也叫作原型对象)。

实例对象 new Star()中:

实例对象有一个属性__proto__(对象原型)指向构造函数的 prototype属性(原型对象)。

实例对象的__proto__.constructor指回构造函数 Star。

原型对象prototype中:

constructor指回构造函数 Star。

在这里插入图片描述

  • 练习
  1. prototype是什么?哪里来的?

原型(原型对象)

构造函数都自动有原型

  1. constructor属性在哪里?作用干啥的?

prototype原型和对象原型__proto__里面都有

都指向创建实例对象/原型的构造函数

  1. __proto__属性在哪里?指向谁?

在实例对象里面

指向原型 prototype

在这里插入图片描述

4、原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承的特性。

说明:

有女人构造函数Women、男人构造函数Men。

javascript">  function Women() {this.eyes = 2this.head = 1}const red = new Women()console.log(red);function Men() {this.eyes = 2this.head = 1}const black = new Men()console.log(black);

因为构造函数中的属性都是一样,所以可以提取一个Person

javascript">  const Person = {eyes = 2head = 1}function Women() {}function Man() {}Women.prototype = Person // 通过原型继承Women.prototype.constructor = Women //  补充一个指回Man.prototype = PersonMan.prototype.constructor = Manconst red = new Women()console.log(red);const black = new Man()console.log(black);

通过原型继承

现在想要给女人增加一个生孩子函数 baby

javascript">Women.prototype.baby = function { console.log('生孩子')}console.log(red);
console.log(black);

结果发现男人也能生孩子。这是因为两者都继承了同一个对象Person

所以通过 Women.prototype = Person 和 Man.prototype = Person 这种继承是不合理的

所以可以通过构造函数 new对象,而不是const 生成对象

javascript">function Person() {this.eyes = 2this.head = 1
}
function Women() {}
function Man() {}Women.prototype = new Person() // 通过原型继承
Women.prototype.constructor = Women //  补充一个指回Man.prototype = new Person()
Man.prototype.constructor = Man//实例验证
Women.prototype.baby = function() {console.log('baby')
}
const red = new Women()
console.log(red);
const black = new Man()
console.log(black);

在这里插入图片描述

5、原型链

__proto__属性的链状结构

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链

在这里插入图片描述

  • 举例说明
javascript">  // function Object() {// }function Person() {}const ldh = new Person()// 构造函数Person 有prototype(原型)console.log(Person.prototype); console.log(Person.prototype.__proto__ === Object.prototype);  // true//【前提】:每一个构造函数都有原型,每一个对象都有__proto_属性// Person是我们定义的构造函数,构造函数Person 有prototype(原型)// 【Person.prototype】是一个对象,每个对象里面都有一个__PROTO__,// Person.prototype.__PROTO__指向 "构造出【Person.prototype】这个对象的构造函数 的prototype "  // 有一个最大构造函数 Objct,这个构造函数构造出 Person.prototype // 因此,Person.prototype.__PROTO__指向Object 的prototype原型对象(也就是一个对象实例),指向 构造出这个对象的构造函数(function) 的prototype
原型对象

在这里插入图片描述

查找规则

__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

查找规则如下:

① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)

③ 如果还没有就查找原型对象的原型(Object的原型对象)

④ 依此类推一直找到 Object 为止(null)

__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

javascript">const arr = [1,2,3] // arr是对象 相当于 const arr = new Array(1,2,3)
arr.map(function() {// 略
})1、当访问 arr 的方法 map 时,首先查找这个对象自身有没有该属性。
发现没有
2、查找 arr 的原型(也就是 arr.__proto__指向的 prototype 原型对象)
该prototype 原型对象 属于 构造函数 Array的原型,找到了
  • instance of
javascript">  const zxy = new Person()console.log(zxy instanceof Person); // zxy 属于 Person 吗 : trueconsole.log(zxy instanceof Object); // zxy 属于 Object 吗 : trueconsole.log(zxy instanceof Array);  // zxy 属于 Array 吗 :  falseconsole.log(Array instanceof Object); // true

小结 原型和原型链

1.原型:函数都有prototype属性,称之为原型,也称为原型对象
原型可以放一些属性和方法,共享给实例对象使用
原型可以做继承
2.原型链:查找一个对象的属性和方法的时候,先在自身找,找不到则沿着__proto__向上查找,我们把__proto__形成的链条关系称原型链

__proto__属性是每一个对象以及函数都有的一个属性。__proto__属性指向的是创建他的构造函数的prototype。原型链就是通过这个属性构件的。


http://www.ppmy.cn/server/95395.html

相关文章

网络基础命令配置复习 (基础华为设备)

目录 一.前言 二.Telnet远程登陆 2.1telnet介绍 2.2telnet的配置 三.交换机基础配置 四.致谢 一.前言 网络基础不仅是IT从业者的必备知识,也是日常生活中使用网络的人们应该了解的内容。通过学习和掌握这些基础知识,你将能更好地理解和利用现…

RocketMQ5.0消费者

RocketMQ 5.0 提供了三种主要的消费者类型:PushConsumer、SimpleConsumer 和 PullConsumer。每种类型的消费者都有其特定的使用场景和特点。以下是对这三种消费者的概念及其区别的详细阐述: PushConsumer 概念: PushConsumer 是一种主动推送…

Github 2024-08-03 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-08-03统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10HTML项目1Go项目1Meilisearch: 快速搜索API,提升工作效率 创建周期:2252 天开发语言:Rust协议类型:MIT LicenseStar数量:44442 …

北京汽车美容元宇宙:数字化浪潮下的车美服务新革命

随着社会的发展和科技的进步,元宇宙这一概念正逐步渗透到人们的生活之中,改变了传统行业的运作模式。北京,作为科技创新的前沿城市,正见证着汽车美容元宇宙的诞生与兴盛,为车主们带来了全新的服务体验和便利。 ### 正…

AI学习指南机器学习篇-Sarsa算法的数学基础

AI学习指南机器学习篇-Sarsa算法的数学基础 在机器学习领域,Sarsa算法是一种经典的强化学习算法,它以其良好的收敛性和最优性条件而闻名。然而,了解Sarsa算法的数学基础对于深入理解其内在原理至关重要。本篇博客将探讨Sarsa算法背后的数学理…

laravel项目配置

创建laravel项目 composer create-project --prefer-dist laravel/laravel 项目名称生成项目key php artisan key:generate.清理配置缓存 php artisan config:clearlaravel生成代码 官网链接 php artisan make:model Flight --all生成Flight类相关的文件,对应数…

麦田物语第十八天

系列文章目录 麦田物语第十八天 文章目录 系列文章目录一、(Editor)制作 [SceneName] Attribute 特性二、场景切换淡入淡出和动态 UI 显示一、(Editor)制作 [SceneName] Attribute 特性 在本节课我们编写Unity的特性Attribute来更好的完善我们项目,具体是什么呢,就是当…

cpp 转发和移动

std::forward 和 std::move 在内存上的区别 1. std::move std::move 是一个标准库函数模板&#xff0c;用于将其参数显式地转换为右值引用。这在需要将对象的资源移动而不是复制时非常有用&#xff0c;例如在移动构造函数或移动赋值操作中。 语法: template <class T>…