1. 首页

JavaScript的原型对象的彻底理解

前言

开篇先记住以下两点,再渐渐通过实例理解

  1. __proto__constructor属性是对象所独有的;

  2. prototype属性是函数所独有的。

但是由于 JS 中函数也是一种对象,所以函数也拥有 __proto__constructor 属性

一、函数的原型对象

我们创建函数 A 的同时, 浏览器会在内存中创建一个对象 BA 函数默认会有一个 prototype 属性。指向了对象 B( 即:prototype 的属性的值是对象 B )。 ​ 这个对象 B 就是函数 A 的原型对象,简称函数的原型。 ​ 原型对象 B 默认会有一个属性 constructor 指向了函数 A (即 constructor属性的值是函数 A )。 ​ 原型对象默认只有属性constructor 。其他都是从 Object 继承而来。

Javascript中文网是以前端进阶资源教程分享为主的专业网站

正式开始: 举栗子讨论


//创建一个构造函数 Foo(),并用 new 关键字实例化该构造函数得到一个实例化对象 f1。 function Foo() {...}; let f1 = new Foo();

Javascript中文网是以前端进阶资源教程分享为主的专业网站

二、proto 属性

__proto__属性,它是对象所独有的,可以看到__proto__属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?

它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找….直到原型链顶端null

此时若还没找到,则返回undefined。以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链

三、prototype 属性

prototype函数所独有的,它是从一个函数指向一个对象

它的含义是函数的原型对象,也就是这个函数所创建的实例的原型对象,由此可知:

f1.__proto__ === Foo.prototype

prototype属性的作用

  它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。

四、constructor属性

constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数,从图中可以看出**Function** 这个对象比较特殊,它的构造函数就是它自己(因为 Function 可以看成是一个函数,也可以是一个对象),所有函数最终都是由 Function() 构造函数得来,所以constructor属性的终点就是Function()

举例子


//创建构造函数 function Person () { } //使用Person.prototype 直接访问到原型对象 //给Person函数的原型对象中添加一个属性name,值是 "张三" Person.prototype.name = "张三"; //创建一个实例 p1 var p1 = new Person(); //访问p1对象的属性name,虽然在p1对象中我们并没有明确的添加属性name,但是p1的 prototype 属性指向的原型中有name属性,所以这个地方可以访问到属性name值。 alert(p1.name); // 张三 var p2 = new Person(); alert(p2.name); // 张三 都是从原型中找到的,所以一样。 alert(p1.name === p2.name); // true // 由于不能修改原型中的值,下面这种方法就直接在p1中添加了一个新的属性name,然后在p1中无法再访问到原型中的属性。 p1.name = "李四"; alert("p1:" + p1.name); // 对p2来说仍然是访问的原型中的属性。 alert("p2:" + p2.name); // 张三 //如何证明证明p1.__proto__ 与 Person.prototype是相同的 alert(p1.__proto__ === Person.prototype); //true

五、常用方法

hasOwnProperty()in操作符

作用:判断函数的原型所在位置


function Person () { }; Person.prototype.name = "志玲"; var p1 = new Person(); p1.sex = "女"; //定义一个函数去判断原型所在的位置 function propertyLocation(obj, prop){ if(!(prop in obj)){ alert(prop + "属性不存在"); }else if(obj.hasOwnProperty(prop)){ alert(prop + "属性存在于对象中"); }else { alert(prop + "对象存在于原型中"); } } propertyLocation(p1, "age"); //age属性不存在 propertyLocation(p1, "name"); //name对象存在于原型中 propertyLocation(p1, "sex"); //sex属性存在于对象中

六、动态原型模式创建对象


//构造方法内部封装属性 function Person(name, age) { //每个对象都添加自己的属性 this.name = name; this.age = age; /* 判断this.eat这个属性是不是function,如果不是function则证明是第一次创建对象, 则把这个funcion添加到原型中。 如果是function,则代表原型中已经有了这个方法,则不需要再添加。 perfect!完美解决了性能和代码的封装问题。 */ if(typeof this.eat !== "function"){ Person.prototype.eat = function () { alert(this.name + " 在吃"); } } } var p1 = new Person("志玲", 40); p1.eat(); //志玲 在吃

作者:炒面熊
链接:https://juejin.im/post/6894157108904722439

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:JavaScript的原型对象的彻底理解

链接:https://www.javascriptc.com/4622.html

« JavaScript预解析处理过程原来是这回事
JS中的经典继承实现方法与原型的深入探讨»
Flutter 中文教程资源

相关推荐

QR code