JavaScript的原型与原型链

在讲原型之前,我们先说说js的数据类型,有一下几种

原始数据类型:String、Number、Boolean、Null、undefined、Symbol(ES6)、BigInt(ES10) 

引用类型:Object

JS 中 typeof 输出分别是什么呢?

  1)基础数据类型

typeof 'a' // 'string'
 
typeof 12  // 'number'

typeof false // 'boolean'

typeof null  // 'object'

typeof NaN  // 'number'

 2)引用数据类型

typeof Object   //'function' 

typeof Number   //'function'
 
typeof String   //'function'

typeof Boolean  //'function'

typeof Function //'function'

这个时候有人肯定会有疑问,为啥引用类型这里输出的function,我们知道任何几个结果的输出都是有原因的,我们先在这里埋下一个伏笔。接下来我们进入主题,讲讲原型

一、构造函数创建对象

我们先使用构造函数创建一个对象

function Person (name, age) {

      this.name = name
      this.age = age
}

var person = new Person('zbq', 28)

我们创建了一个Person构造函数,然后通过new来创建来一个实例person,接下来我们开始进入主题

prototype属性

每个函数都有一个prototype属性,指向实例原型,构造函数与实例原型的关系如下图所示:

__proto__属性

每个对象都有一个__proto__属性,指向实例原型,该实例与实例原型的关系如下入所示

 

因此person的__proto__属性与Person构造函数的prototype的属性指向的是同一个实例原型 Person.prototype,我们来验证一下

person.__proto__ === Person.prototype // true

补充说明:绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)。

 

constructor属性

我刚说了构造函数与实例原型的关联,以及实例与实例原型的关联,那实例原型与构造函数有啥关联呢?这就是我们接下来要说的

实例原型的constructor属性,它是指向构造函数的,我们用代码验证一下

Person.prototype.constructor === Person //true

它的关系图如下所示:

接下来有人肯定要问了,那Person.prototype它有指向的是谁呢?这就是我们接下来要讲的原型与原型之前的关联了

 

二、原型与原型

前面我们说过每个对象都有一个__proto__属性,而实例原型也不例外,它也有一个__proto__指向上一个实例原型对象,因此就有如下的Person.prototype.__proto__指向Object.prototype。

三、原型链

原型与原型之间通过__proto__建立的的关联就是原型链(下图的蓝色线条),这里再补充一下Object.prototype指向的原型是null

我们可以用代码验证一下

Person.prototype.__proto__ === Object.prototype // true

Object.prototype.__proto__ === null             // true

 

四、拓展

我们先记住一个知识点,instanceof 它表示是一种继承关系。然后我们再看看以下的一个例子

Object instanceof Function    // true

Function instanceof Object    // true

Function instanceof Function  // true 

肯定很多人一脸的疑惑,在想为什么?疑惑是正常的。不过我们先来一步步分析吧!

1、首先我们先看一个函数的创建

// 方式一:传统方式来新建一个函数
function add1 (a, b) {

   return a + b

}
// 方式二:通过new的方式来创建(平时不推荐使用)
var add2 = new Function ('a', 'b', 'return a + b')

根据此可以得出一个结论:

1) 函数也是对象,所以也有__prototype__属性

2) Function是一个构造函数  function Function () {....}

关系图如下:

2、创建对象

// 方式一:对象字面量的形式
var obj1 = {}

// 方式二:new方式来创建
var obj2 = new Object()

obj1.__proto__ === Object.prototype // true

obj2.__proto__ === Object.prototype // true

根据以上可以得出一个结论:

1)  对象字面量的创建方式只是new方式的一种快捷创建方式

2) Object也是一个构造函数  function Object () {...}

3) Object也是Function的一个实例 

Object.__proto__  === Function.prototype  // true

以上实例的关系图如下:

 

所以你现在是不是能懂的为啥以下的例子的结果都是返回true,以及开篇文章中 typeof Object === 'function'

Object instanceof Function    // true

Function instanceof Object    // true

Function instanceof Function  // true

小结:

1、每个函数都有一个prototype属性

2、每个对象都有一个__proto__属性

3、任何函数皆对象

 

以上文章是参考至:

https://segmentfault.com/a/1190000008959943

https://www.cnblogs.com/wangfupeng1988/tag/%E5%8E%9F%E5%9E%8B

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章