问题

初学js的同学,总是搞不清楚js中的原型是什么东西,看着控制台打印出来的一串串__proto__,迷惑不已。

例如我定义一个Person,创建一个实例p,并打印实例。

function Person(){}
var p = new Person();
console.log(p)



图中,打印出来一个Person的实例对象p,

这个对象有个__proto__ 属性,这个是什么东西?

__proto__属性下又有constructor属性和__proto__属性。

constructor是什么,为什么打印结果是 Person()?

另外一个__proto__是什么?

为了解答上边的问题,我们需要了解一些相关概念。

一、原型

prototype

首先,说明一下,JS中,万物皆对象。

每个函数对象都有一个属性prototype(函数对象特有属性),这个属性是一个引用,指向一个对象,这个对象的作用就是包含所有实例共享的属性和方法。我们把这个对象就叫做原型对象,也叫显式原型

__proto__

每个对象都有一个属性__proto__,也可称为隐式原型,对象的隐式原型指向创建该对象的构造函数的原型(prototype)。

constructor

函数的原型对象有一个constructor属性,这个属性是一个引用,用于指向原构造函数。

关系

我们怎么理解上边的概念,而它们之间又有什么联系呢?

我们不妨打印出来p.__proto__属性:



可以看到,打印出来是一个对象,对象里边有个属性constructor。

constructor是什么呢,打印如下:



可以看到,打印出来是函数,代表的就是Person构造函数本身.

再依次打印出来Person构造函数的原型Person.prototype,

和其原型的属性constructor:



从上图我们就可以得出:

1.实例对象p有属性__proto__ 指向的就是创建它的构造函数的原型对象Person.prototype。

2.构造函数的原型对象Person.prototype的属性constructor指向Person构造函数本身。

我们可以验证一下:

但是,可能又有些同学有疑惑了,那既然所有对象都有__proto__属性,

那构造函数Person()的属性__proto__指向谁呢?

当然是指向它的构造函数的原型对象了。

函数的构造函数就是Function(),因此这里的__proto__指向Function.prototype。

那原型对象也是对象,它的__proto__属性指向谁呢?

同理,指向它的构造函数的原型对象,即Object.prototype。

这里,我们就不得不提一下,原型链的概念了。

原型链

原型链是一种机制,指的是js中,每个对象都有一个属性__proto__,指向它的构造函数的原型对象。原型对象也是一个对象,因此也有__proto__属性指向原型对象的原型对象,这样一层层向上直到对象的原型对象为空(Object的原型对象Object.prototpye的属性__proto__为null)。

因此,例子中原型链的关系如下:

p.__proto__ 指向 Person.prototype,

Person.prototype.__proto__指向的就是Object.prototype,

Object.prototpye.__proto__ 指向null

为了理解上边例子的原型链关系,我们画一张图来增加理解:



至此,上边的问题是不是心里已经有答案了呢。

总结

1.每个对象都有一个__proto__属性,指向创建它的构造函数的原型对象。

作用:构成原型链,用于实现基于原型的继承。

2.函数除了有__proto__属性,还有一个prototype属性,用来指向函数的原型对象。

作用:用于实现基于原型的继承和属性共享。

因此,你会在很多地方见到有类似这样的写法:

function Person(){}
Person.prototype.hello = function(){
console.log("hello")
}

上边代码表示,所有Person创建的实例对象都可以共享hello方法。

3.构造函数的原型对象有属性constructor,指向构造函数本身。

PS:欢迎关注公众号:「如若清风」,一起交流学习。

最新文章

  1. PhpStorm PHP开发神器
  2. iframeWin For Easy UI. 为 Easy UI 扩展的支持IFrame插件
  3. Leetcode: Insert Delete GetRandom O(1) - Duplicates allowed
  4. NUnit - 使用感受
  5. 使用WinAPI全局热键注册和全局模拟按键
  6. HDU 2023题解分析
  7. Java中Properties类
  8. js自执行函数写法
  9. 【Java核心】ClassLoader原理及其使用
  10. amd屏幕亮度无法调整,无法调节亮度
  11. [LeetCode] Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和
  12. Lucene 自动补全
  13. 读 Spring实战 遇到的问题记录(一)
  14. 解决 warning I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
  15. debian9 开启rc.local服务
  16. win2012R2打Windows8.1-KB2919355 问题
  17. vue axios全攻略
  18. 专题--XOR之线性基
  19. 使用Redis数据库(String类型)
  20. 10.9h5日记

热门文章

  1. cyyz: Day 4 网络流整理
  2. cyyz: Day 6 平衡树整理
  3. C Primer Plus--位操作
  4. EasyEarth三维可视化解决方案——智慧园区
  5. 3ds Max学习日记(十一)——如何给模型上贴图
  6. PostgreSQL中的partition-wise aggregation
  7. IDS,IPS,IPD
  8. k8s记录-kube-dns(core-dns)配置(七)
  9. [LeetCode] 750. Number Of Corner Rectangles 边角矩形的数量
  10. Java之整数运算