前言
开篇先记住以下两点,再慢慢通过实例了解
__proto__
和constructor
属性是对象所独有的;prototype
属性是函数所独有的。
然而因为 JS
中函数也是一种对象,所以函数也领有 __proto__
和 constructor
属性
一、函数的原型对象
咱们创立函数 A
的同时, 浏览器会在内存中创立一个对象 B
,A
函数默认会有一个 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
起源:掘金