JavaScirpt中的原型,原型对象和原型链

Posted IT-Dashen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScirpt中的原型,原型对象和原型链相关的知识,希望对你有一定的参考价值。

一.什么是原型呢? 

我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.(即prototype即为函数的原型该原型指向的是一个原型对象)

二.什么是原型对象呢?

  • 我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象(即原型对象).而这个对象的用途是包含
   可以由特定类型的所有 实例 共享的属性和方法.(字面意思prototype就是通过调用构造函数而创建的实例对象的原型对象)
  • 使用原型对象的好处是可以让所有的对象实例(实例对象)共享他包含的所有的属性和方法
  • 需要特别注意的是原型对象的理解,只要创建一个函数,该函数就会创建一个prototype(原型)属性,这个属性指向函数的原型对象

三.原型对象和原型的关系?

 

       __proto__是什么呢?

 

  • 这是每一个javascript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。
  • 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性即__proto__),指向构造函数的原型对象

  constructor是什么呢?

  • 在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针即(Person.prototype.constructor指向Person),而通过这个构造函数,我们可以继续为原型对象添加起他属性和方法

  通过一张图片展示他们之间的关系

  

 代码示例:

//创建一个构造函数,并在构造函数的原型上添加一个name属性
function Person(){
}
Person.prototype.name = "kebi"
var person1 = new Person();
console.log(person1.name) //kebi
var perso2 = new Person();
console.log(person2.name) //kebi
console.log(person.__proto__ === Person.prototype); // true 他两个的关系也是完全相等的

console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
//b.isPrototypeOf(a) 这个方法的意思是,a对象是否指向b对象
Person.prototype.isPrototypeOf(person1) //true 因为person1中有一个__proto__属相指向原型对象(
Person.prototype)
Person.prototype.isPrototypeOf(person2)  //true   同理
 

总结一下prototype和__proto__到底是什么关系呢?

  • 函数对象的prototype属性, 可以称之为显式原型属性(简称: 显式原型)
  • 实例对象的__proto__属性, 可以称之为隐式原型属性(简称: 隐式原型)
  • 原型对象: 也就是prototype属性和_proto__属性指向的对象

四.什么是原型链? 

  1.原型的搜索机制

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

   代码例子: 

function Person() {

}

Person.prototype.name = \'heyushuo\';

var person = new Person();

person.name = \'kebi\';
console.log(person.name) // kebi

delete person.name;
console.log(person.name) //heyushuo

在这个例子中,我们给实例对象 person 添加了 name 属性,当我们打印 person.name 的时候,结果自然为 kebi。

但是当我们删除了 person 的 name 属性时,读取 person.name,从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找 (原型对象中),幸运的是我们找到了 name 属性,结果为 heyushuo。

但是万一还没有找到呢?原型的原型又是什么呢? ( 肯定需要一环一环地前行到原型链的末端才会停下来)

  最顶层为默认的原型

  所有的函数的默认原型都是Object的实例,所以默认原型都会包含一个内部指针,指向Object.prototype(默认原型的原型对象),这也真是所有自定义类型都会继承toString()/valueOf等默认的方法的根本原因.一直查到最顶层才算一个完整的原型链

如图所示: 蓝色线为完整的原型链

参考:Javascript:高级程序设计

 javascript深入之从原型到原型链(感觉原型和原型对象未分清楚)

 

以上是关于JavaScirpt中的原型,原型对象和原型链的主要内容,如果未能解决你的问题,请参考以下文章

如何更加简单的理解JS中的原型原型链概念

JavaScript中的原型和原型链

js 继承与原型链

JS高级---原型和原型链

javascript中的原型和原型链

面试:原型链