前言

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

  1. __proto__constructor属性是对象所独有的;
  2. prototype属性是函数所独有的。

然而因为 JS 中函数也是一种对象,所以函数也领有 __proto__constructor 属性

一、函数的原型对象

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

正式开始: 举栗子探讨

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

二、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 = "张三";//创立一个实例 p1var 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
起源:掘金