javaScript原型与原型链

JavaScript原型与原型链

此处先说明原型与原型链的作用:JavaScript的原型与原型链就是该编程语言为了实现面对对象编程的一种设计,基于原型链,可以让JavaScript对象拥有封装、继承和多态等众多面向对象的特性。

下面我们一步一步来认识它。

JavaScript的面向对象

使用过Vue的小伙伴应该会很熟悉下面这段代码,通过vue-cli创建的Vue项目,在其如口main.js文件中,一般会有如下代码:

image-20210831184437252.png

我们打开Vue的源码,可以看到Vue这个对象的定义,与其它语言有很大的不同,Vue这个对象就是一个function(函数):

image-20210831185237224.png

JavaScript是一门弱类型语言,但它也有其它高级语言(如JavaC#等)所拥有的的特征——面向对象,上面通过newfunction关键字,便是创建了一个Vue对象。

function用来定义一个类,new关键字则用来创建一个类的实例对象。 实例化对象之后, 实例便继承了类的属性和方法。 例如:

function Person(name, age){
  this.name = name;
  this.age = age;
}

Person.prototype.getName = function(){
  return this.name;
};

var person = new Person('james', 18);
console.log(person.name); // putput: james
console.log(person.age); // putput: 18
console.log(person.getName()); // putput: james

JavaScript创建对象的过程

在介绍原型与原型链之前,我们还需要先了解一下JavaScript是如何创建一个对象的

当我们通过new创建一个对象时(如:var person = new Person('james', 18))到底经历了什么呢?

  1. 首先会创建一个空对象Object

    // 在栈内新建了一个obj,这个obj实际上是指的堆中对应的一个地址
    
    let obj = new Object(); 
    
  1. 设置原型链---这里所说原型链,就是设置新建对象obj的隐式原型即_proto_属性指向构造函数Person的显示原型prototype对象,即:

    obj.__proto__ = Person.prototype;
    
  1. 改变构造函数Person的this绑定到新对象obj,并且利用call()或者是apply()来执行构造函数Person,如下:

    let result = Person.call(obj);
    
  1. 将第三步中初始化完成后的对象地址,保存到新对象中,同时要判断构造函数Person的返回值类型,为什么要判断值类型呢?因为如果构造函数中返回this或者是基本数据类型(number数值,string字符串,Boolean布尔,null,undefined)的值时,这个时候则返回新的实例对象,如果构造函数返回的值是引用类型的,则返回的值是引用类型,如下:

    if (typeof (result) === "object") { 
     func = result;
    } else { 
     func = obj; // 默认返回
    }
    

整个过程使用伪代码来模拟其执行的过程:

new Person('james', 18)  = {
  var obj = {};
  obj.__proto__ = Person.prototype;
  var res = Person.call(obj, 'james', 18);
  return typeof res === 'object' ? res : obj;
}

JavaScript的原型与原型链

在通过new关键字创建对象的过程中,在其第二步:obj.__proto__ = Person.prototype,在这一步,就涉及到了原型的概念。

  • prototype: 每一个函数都有一个特殊的属性,叫做原型(prototype)
  • constructor: 相比于普通对象的属性,prototype属性本身会有一个属性constructor,该属性的值为prototype所在的函数
  • __proto__: 每一个对象都有一个__proto__属性,该属性指向对象(实例)所属构造函数(类)的原型prototype

原型与对象的关系图如下:

image-20210901091846381.png

每个实例的的__proto__指向对象的prototype,同时对象prototype__proto__又指向上层对象的prototype。也就是原型链(下面蓝色的这条链)。

image-20210901091945456.png

JavaScript对象的prototype内置属性, 其实就是对于其他对象的引用, 几乎所有的对象在创建时, prototype的属性都会被赋予一个非空的值(除了Object.create(null))。 所有普通的prototype链最终都会指向内置的Object.prototype。在创建一个新对象成功之后, 如果调用一个新对象没有的属性或方法的时候, JavaScript会沿着原型链向上逐层查找对应的属性或方法。 这就类似于类继承

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容