原型与原型链详解

前言

与大部分面向对象语言不同,ES6之前中没有引入类 (Class) 的概念,JavaScript并非通过类而是直接通过构造函数来创建实例的。在介绍原型和原型链之前,我们有必要先复习一下构造函数的知识。
原型与原型链详解_第1张图片

一、构造函数

构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立的,即实例识别。

构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。另外就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用

原型与原型链详解_第2张图片
原型与原型链详解_第3张图片

每创建一个Person构造函数,在Person构造函数中,为每一个对象都添加了一个sayName方法,也就是说构造函数每执行一次就会创建一个新的sayName方法。这样就导致了构造函数执行一次就会创建一个新的方法,执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的,为什么不把这个方法单独放到一个地方,并让所有的实例都可以访问到呢?这就需要原型(prototype),就像添加add方法那样。

二、原型

①所有引用类型都有一个_proto_(隐式原型)属性,属性值是一个普通的对象 (__proto__指向prototype,所以也可以说值直接是 prototype)
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype

var a = [1,2,3];
a.__proto__ === Array.prototype; // true
数组的构造函数是 Array; js中内置的;

二、原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的_proto_ 隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype_proto_中查找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。这样一层一层向上查找就会形成一个链式结构,我们称为原型链

举例,有以下代码:

function Parent(month){
     
    this.month = month;
}

var child = new Parent('Ann');

console.log(child.month); // Ann

console.log(child.father); // undefined

在child中查找某个属性时,会执行下面步骤
原型与原型链详解_第4张图片
访问链路为:
原型与原型链详解_第5张图片

①一直往上层查找,直到到null还没有找到,则返回 undefined
Object.prototype._proto_ === null
③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象

自己总结几点:

  • 1、构造函数就是 类
  • 2、实例就是构造函数 new 出来的,也就是我们通常说的实例对象,这里的 person1 就是Person的实例。
  • 3、对象数据类型(普通对象、实例、prototype,也就是所有引用类型的数据) 都有一个__proto__隐式原型,其值就是构造函数的prototype
  • 4、原型对象中有一个属性,constructor,它指向构造函数本身;
  • 5、构造函数中有一个 prototype 属性,指向实例原型,实例原型中又有一个constructor属性指向构造函数, 通过构造函数new出来的实例中有一个__proto__也指向实例原型(prototype);
    function Person() {
     }
    var person = new Person()
    console.log(person.__proto__ === Person.prototype)//true
    console.log(Person.prototype.constructor===Person)//true
    //顺便学习一个ES5的方法,可以获得对象的原型
    console.log(Object.getPrototypeOf(person) === Person.prototype) // true

原型与原型链详解_第6张图片

我们可以使用对象的 hasOwnProperty()来检查对象自身中是否含有该属性;使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回 true

 function Person() {
     }
    Person.prototype.a = 123;
    Person.prototype.sayHello = function () {
     
      alert("hello");
    };
    var person = new Person()
    console.log(person.a)//123
    console.log(person.hasOwnProperty('a'));//false
    console.log('a'in person)//true

person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.proto ,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__中也没有该属性,又该如何查找?

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有_proto_这个属性。

console.log(Object.prototype.__proto__ === null) // true

原型与原型链详解_第7张图片

你可能感兴趣的:(JavaScript,javascript,前端)