这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

原型和原型链

1. 原型

每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法

1.1 __proto__

对象__proto__属性值就是对象的原型对象

此属性是过时的语法,现在建议使用Object.getPrototypeof(obj)

函数也是对象,因此也有__proto__属性

1.2 Prototype

函数的prototype属性值就是函数的原型对象

定义:给其他对象提供共享属性的对象,prototype 本身也是对象,只是被用以承担某个职能

当说 prototype 对象时,实际上说的是 “xxx 函数对象的 prototype 对象”

1.3 constructor

每个原型都有一个 constructor 属性指向关联的构造函数

实例访问 constructor 属性是获取的原型对象的构造函数

function Person(age) {
this.age = age;
}
let p = new Person(50);
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor === Person); // true 会查找原型对象

对于引用类型来说 constructor 属性值是可以修改的,但是对于基本类型来说是只读的,因为创建他们的是只读的原生构造函数(native constructors

2. 原型链

每个对象拥有一个原型对象,通过 __proto__ 指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null。这种关系被称为原型链 (prototype chain),通过原型链一个对象会拥有定义在其他对象中的属性和方法。

因此,当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。

2.1 原型链知识点

  • 原型链的尽头(root)是Object.prototype所有对象(除null)均从Object.prototype继承属性

  • Object.prototype.__proto__值是null,原型链终止

  • Function.prototypeFunction.__proto__为同一对象

    意味着: Object/Array/String等等构造函数本质上和Function一样,均继承于Function.prototype

  • Function.prototype直接继承root(Object.prototype

  • 继承的原型链:Object.prototype(root)<---Function.prototype<---Function|Object|Array...

  • 对象的__proto__指向自己构造函数的prototype

  • ES规范定义对象字面量({})的原型就是Object.prototype

2.2 ObjectFunction的鸡和蛋的问题

  • Function.prototype是个不同于一般函数(对象)的函数(对象)

    • Function.prototype像普通函数一样可以调用,但总是返回undefined
    • 普通函数实际上是Function的实例,即普通函数继承于Function.prototypefunc.__proto__ === Function.prototype
    • Function.prototype继承于Object.prototype,并且没有prototype这个属性。func.prototype是普通对象,Function.prototype.prototypenull
    • 总结Function.prototype其实是个另类的函数,可以独立于/先于Function产生。
  • Object本身是个(构造)函数,是Function的实例,即Object.__proto__就是Function.prototype

问题总结:

先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生

2.3 原型链图解

原型和原型链经典关系图

自己画的原型图

图解描述:

Person、Object、Function是函数对象,具备prototype属性,其他对象是只有__proro__

获取原型对象

Person.__proto__及Object.__proto__与Function.__proto__相等,是ƒ () { [native code] }

Person.__proto__及Object.__proto__与Function.__proto__的原型对象为Object.prototype

Function.__proto__和Function.prototype值相等,为空函数: ƒ () { [native code] }

Person.constructor、Object.constructor与Function值相等,为: ƒ Function() { [native code] }

原型链代码输出结果

function Person(name) {
this.name = name
}
var p2 = new Person('king');
console.log(p2.__proto__) //Person.prototype
console.log(p2.__proto__.__proto__) //Object.prototype
console.log(p2.__proto__.__proto__.__proto__) // null
console.log(p2.__proto__.__proto__.__proto__.__proto__)
//null后面没有了,报错
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)
//null后面没有了,报错
console.log(p2.constructor)//Person
console.log(p2.prototype)//undefined p2是实例,没有prototype属性 console.log(Person.constructor)//Function 一个空函数
console.log(Person.prototype)
//打印出Person.prototype这个对象里所有的方法和属性
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)// Object.prototype
console.log(Person.__proto__) //Function.prototype
console.log(Function.prototype.__proto__)//Object.prototype
console.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null console.log(Function); // ƒ Function() { [native code] } 空函数,名为Function
console.log(Object.constructor); // ƒ Function() { [native code] }
console.log(Person.constructor); // ƒ Function() { [native code] }
console.log(Function === Object.constructor); // true
console.log(Function === Person.constructor); // true console.log(Function.__proto__); // ƒ () { [native code] }
console.log(Function.prototype); // ƒ () { [native code] }
console.log(Function.__proto__ == Function.prototype); // true
console.log(Function.__proto__.__proto__ === Object.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true

本文转载于:

https://juejin.cn/post/7086376102238617614

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--JavaScript原型和原型链复习笔记的更多相关文章

  1. JavaScript原型(链)学习笔记

    javascript是基于原型的一门脚本语言,那究竟原型是什么? 本文将从以下几个方面重点阐述原型 构造函数是什么? 构造函数和我们常见的Array String有什么关系? 原型的使用? __pro ...

  2. 原型及原型链,以及prototype和__proto__属性(笔记便于以后复习)

    首先,js的数据结构有 原始类型(5种):Boolean.Number.String.Null.Underfined, 然后是引用类型:Array.Date.Error.RegExp.Function ...

  3. <深入理解JavaScript>学习笔记(5)_强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. (prototypal :原型.学好英语还是很重要的) 虽然这经常被当作是 JavaScript 的缺点 ...

  4. javaScript 原型与原型链学习笔记

    javaScript中,原型是常用到一种方式,它能降低储存占用,写出更高效的代码 原型常用到的则是prototype属性 JavaScript prototype 属性 定义和用法 prototype ...

  5. JavaScript原型与原型链学习笔记

    一.什么是原型?原型是一个对象,其他对象可以通过它实现属性继承.简单的说就是任何一个对象都可以成为原型 prototype属性: 我们创建的每个函数都有一个prototype属性,这个属性是一个指针, ...

  6. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

  7. javascript进阶-《原型对象和原型链》

    原创发布 by @一像素 2015.12 在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象Object 和 函数对象Function. 一般而言,通过new Fun ...

  8. javascript原型与原型链个人理解

    想了解原型和原型链,我觉得首先我们得知道javascript里有一个Object 与 Function,它俩都是构造函数,当然函数也是一个对象.我们打印Object 与 Function看一下, co ...

  9. JavaScript 类型、原型与继承学习笔记

    目录 一.概览 二.数据类型 1. JavaScript中的数据类型 2. 什么是基本类型(Primitive Data Type) 2.1 概念 2.2 七个基本类型 2.3 基本类型封装对象 3. ...

  10. JavaScript继承与原型链

    对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念( ES6 新增了c ...

随机推荐

  1. Java线上代码热修复的一些积累

    工具:Arthas 参考文章: https://blog.csdn.net/Admire_an/article/details/99768393 https://www.cnkirito.moe/ar ...

  2. Linux进程通信 | 消息队列

    什么是消息队列? 假设你是一个快递员,你需要将货物从一个仓库运到另一个仓库.但是你发现自己的时间不够用,需要另外请一个人来帮忙.那么,你们之间如何进行协作呢? 一种方式是直接将货物全部交给对方,但这样 ...

  3. Oracle 分析函数详解(Analytic Functions)--概念部分

    一.概念介绍: Analytic functions compute an aggregate value based on a group of rows. They differ from agg ...

  4. Java序列化(Serializable)与反序列化详解

    什么是序列化? Java序列化是在JDK 1.1中引入的,是Java内核的重要特性之一. Java序列化API允许我们将一个对象转换为流,并通过网络发送,或将其存入文件或数据库以便未来使用, 反序列化 ...

  5. Java并发编程实例--1.创建和运行一个线程

    从这一篇开始写Java并发编程实例,内容都翻译整理自书籍:<Java 7 Concurrency Cookbook> 谈到线程,无法逃避的一个问题就是: 并发(concurrency)和并 ...

  6. k8s(Kubernetes) 常用命令配置

    一.基础命令 $ kubectl create -f ./my-manifest.yaml # 创建资源 $ kubectl create -f ./my1.yaml -f ./my2.yaml # ...

  7. python中如何使两个序列相加不改变内存地址的几种方式

    # 方式1 a = [1,2,3] print(a) # 4551311680 a.extend([4,5]) print(a) # 4551311680 # 方式2 b = [1,2,3] prin ...

  8. pinject依赖注入模块

    pinject 是一个基于 Python 的轻量级依赖注入库,可以方便地实现依赖注入的功能. 下面我们将通过一个简单的示例来演示如何使用 pinject 实现依赖注入. 首先,我们需要安装 pinje ...

  9. Emqx高可用架构

    目录 优化前架构 主要问题 haproxy问题 优化后架构 优化功能点 emq版本升级 linux系统调优 haproxy调优 测试工具 依赖安装 配置erl环境变量 安装压测软件 测试指令与结果展示 ...

  10. C++之指针变量的定义和使用

    从b站上黑马程序员的c++课里学到的C++之指针变量的定义和使用 指针变量的定义和使用 简单理解指针就是地址. 内存编号是从0开始记录的,一般用16进制数字表示 1 #include <iost ...