彻底深刻理解js原型链之prototype,__proto__以及constructor(二)

简介: 这篇教程主要目的对原型链概念进一步加深理解

前言

如果你能够啃下教程一并且吃透原型链的几个概念的话说明你在前端飞仙的路上又进了一小步···学习最怕的不是慢而是站!这篇教程主要目的对原型链概念进一步加深理解

巩固下教程一的知识

来看下面的例子:

var text=new String("我是文字");
function Persion(name,job){
    this.name=name;
    this.job=job;
}
Persion.myName="lxm";
Persion.prototype.sayName=function(){
    alert(this.name);
}
var perison1=new Persion("lxm","20")

思考:判断下列表达式返回的值:

(两分钟之内对八道的算及格,剩下的同学回头接着理解教程一,传送门在此 [http://0313.name/2017/01/13/prototype-proto-constructor.html]

perison1.__proto__===Persion.prototype;
perison1.name===Persion.name;
perison1.prototype.__proto__===Object.prototype;
Persion.prototype.__proto__===Object.prototype;
Persion.__proto__===Function.prototype;
Persion.constructor===perison1;
Function.__proto__===Object.prototype;
Function.prototype.__proto__===Object.prototype;
typeof Persion.prototype;
typeof Function.prototype;

原型链图

这个图绝对是网络上独一无二独一份,此乃小米飞升教程独家秘籍!因为博主在学习过程中发现对文字的理解和记忆远远不如一个图来的更深更直观,更加透彻,为了您更好的学习原型链,博主特意花了一上午的时间用mermaid绘制了这个原型链的关系图,而且通过这个图我们能够发现很多有意思的事情
为了关系图更加直观和清晰,隐去了一些引用线路,其中:

  • 圆形代表对象的名字
  • 方形代表属性名
  • 实线代表对象的分界
  • 虚线代表引用
  • 菱形代表基本值

git

  1. 原型链是单链,只往一个方向流向,没有回路
  2. 只有Function的__proto__指向自己的prototype,这也向我们解释了为什么Function.prototype类型是function
  3. 我们通过__proto__只能获取到原型对象中的方法和属性,所以persion1通过原型链是获取不到Persion的myName属性,但是我们可以通过原型对象的constructor来获取或者修改Persion的属性(这点太给力了)

请注意,有时候这个方法也不好使,因为原型对象的constructor是可以改变的,不一定指向原型对象所在的函数对象

继续上面的例子:

persion1.__proto__.constructor.myName="我变了耶!";
console.log(Persion.myName); //我变了耶
  1. 普通对象的_proto__一定指向创造它的函数对象的prototype
  2. 原型对象的__proto__一定指向Object.prototype!
  3. 通过图我们可以简单理解,拥有原型对象属性的对象是函数对象,否则为普通对象
  4. 原型链是有开始和尽头的,开始于null,结束于普通对象
  5. 所有的函数对象都是Function以new的方式创造出来了,包括Function自己且每个函数对象的__proto__都指向了Function.prototype
  6. Object是所有对象的父类,我们也可以称之为基类,不过不要纠结于叫什么,因为我们通过图可以看到每一个对象(不管是原型对象还是普通对象还是函数对象)的通过原型链都可以引向Object.prototype

以上九条我称为原型链之九句真言(不要太在意名字,我自己随便起的 ~)

意外收获:this.name和this.job难道不应该在Persion中也有一份吗?无数个日夜,愚笨的博主对this的用法都不甚了解,直到我画出了这种图,我tm彻底明白了this的含义,就是谁运行包含this的这个函数,this就把挂在它身上的包袱(属性)甩给谁!

看到了吗,persion1调用了Persion,那么自然多了2个属性,但是注意,name跟job并不是Persion的属性!!

思考:图中没有画出Object.__proto__的指向,请问他指向哪?(请只依据九句真言解答)

思考题解答

思考:判断下列表达式返回的值:

perison1.__proto__===Persion.prototype;

首先判断perison1是通过new方式被Persion创造出来的,依据九句真言第4条得出 :true

perison1.name===Persion.name;

通过关系图可以看到不相等,我已经在意外收获中解答了,答案为:false

perison1.prototype.__proto__===Object.prototype;

只看图可以看到perison1没有prototype,是普通对象所以答案为:js报错~~

Persion.prototype.__proto__===Object.prototype;

参考九句真言第5条:答案为:true

Persion.__proto__===Function.prototype;

Persion为函数对象,参考九句真言第8条,答案为:true

Persion.constructor===perison1;

Persion是由Function创造出来的所以Persion.constructor指向Function,答案为:false

Function.__proto__===Object.prototype;

Function我们已经反复强调是由自身创造所以Function.__proto__===Function.prototype;,答案为:false

Function.prototype.__proto__===Object.prototype;

根据九句真言第5条,答案为:true

typeof Persion.prototype;

答案为:object

typeof Function.prototype;

答案为:function,注意这个是比较特殊的原型对象

思考:图中没有画出Object.__proto__的指向,请问他指向哪?(请只依据九句真言解答)

下面来分步解答

  1. Object属于函数对象
  2. 依据九句真言第八条得出函数对象的__proto__都指向了Function.prototype
  3. 所以Object.__proto__===Function.prototype

这一点是不太好理解的,是Function创造了Object,然后Object创造了Function的原型对象prototype
所以就有了

Object.__proto__===Function.prototype
Function.prototype.__proto__===Object.prototype

不要太纠结于此,只要理解就好

结束语

好了,原型链的概念原理通过这2篇教程我相信大家已经滚瓜烂熟了!下面的教程,我们会着重研究下原型链在实际的应用!

作者:宜信技术学院 刘晓敏

相关文章
|
8天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
1月前
|
JavaScript 前端开发
JavaScript - 测试 Prototype
JavaScript - 测试 Prototype
11 0
|
2月前
|
JavaScript 前端开发
JavaScript prototype(原型对象)
JavaScript prototype(原型对象)
31 0
|
2月前
|
JavaScript 前端开发
JavaScript基础知识-原型(prototype)
关于JavaScript基础知识中原型(prototype)概念的介绍。
37 1
|
6月前
|
JavaScript 前端开发
在JavaScript中,函数原型(Function Prototype)是一个特殊的对象
【5月更文挑战第11天】JavaScript中的函数原型是一个特殊对象,它为所有函数实例提供共享的方法和属性。每个函数在创建时都有一个`prototype`属性,指向原型对象。利用原型,我们可以向所有实例添加方法和属性,实现继承。例如,我们定义一个`Person`函数,向其原型添加`greet`方法,然后创建实例`john`和`jane`,它们都能调用这个方法。尽管可以直接在原型上添加方法,但推荐在构造函数内部定义以封装数据和逻辑。
56 2
|
6月前
|
JavaScript 前端开发 开发者
【专栏】JavaScript 中的 prototype 和__proto__是关乎对象继承和属性查找的关键概念
【4月更文挑战第29天】JavaScript 中的 prototype 和__proto__是关乎对象继承和属性查找的关键概念。prototype 是函数属性,用于实现对象继承,方法和属性定义在其上可被所有实例共享。__proto__是对象属性,实现属性查找机制,当对象自身找不到属性时,会沿原型链向上查找。两者关系:__proto__指向构造函数的 prototype,构成对象与原型的桥梁。虽然 prototype 可直接访问,但__proto__由引擎内部维护,不可见。理解两者区别有助于深入学习 JavaScript。
94 1
|
3月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
97 0
|
3月前
|
JavaScript 前端开发 开发者
揭开JavaScript的神秘面纱:原型链背后隐藏的继承秘密
【8月更文挑战第23天】原型链是JavaScript面向对象编程的核心特性,它使对象能继承另一个对象的属性和方法。每个对象内部都有一个[[Prototype]]属性指向其原型对象,形成链式结构。访问对象属性时,若当前对象不存在该属性,则沿原型链向上查找。
32 0
|
5月前
|
JavaScript 前端开发
JavaScript进阶-原型链与继承
【6月更文挑战第18天】JavaScript的原型链和继承是其面向对象编程的核心。每个对象都有一个指向原型的对象链,当查找属性时会沿着此链搜索。原型链可能导致污染、效率下降及构造函数与原型混淆的问题,应谨慎扩展原生原型、保持原型结构简洁并使用`Object.create`或ES6的`class`。继承方式包括原型链、构造函数、组合继承和ES6的Class继承,需避免循环引用、方法覆盖和不当的构造函数使用。通过代码示例展示了这两种继承形式,理解并有效利用这些机制能提升代码质量。
85 5
|
6月前
|
JavaScript 前端开发
深入探讨JavaScript中的原型链与继承机制
JavaScript作为一种灵活而强大的编程语言,其独特的原型链与继承机制是其核心特性之一。本文将深入探讨JavaScript中的原型链与继承机制,从基础概念到实际应用,帮助读者更好地理解和利用JavaScript的继承特性。