首先明确两个概念: 构造函数和 instance 分别是什么浏览器
构造函数
JS 中并无在语法层面上面区分构造函数和普通函数, 惟一的区别是调用方式
使用 new 调用的函数就是构造函数, 没有则是普通函数.函数
实例
new Constructor() 返回的对象称为 Constructor 的一个实例prototype
而后提出一个规则:
在构造函数的原型上面附加的属性或者方法, 能够被其全部的实例共用.code
能够推导出:对象
构造函数能够访问到它的原型, 而且向其上面添加方法和属性原型链
构造函数的原型应该是一个对象, 这样才能向其上添加方法和属性原型
实例也拥有其构造函数的原型的一个引用, 要否则没法共用.io
解释:
1 构造函数的确有一个属性, 能够访问到它的原型, 属性名为 prototype.
规范下称呼:
a 函数的 prototype 属性, 称为 '原型属性'
b 函数的 原型属性指向的 对象, 称为 '原型对象'function
2 实例也的确拥有一个对其构造函数的原型的引用
这个引用是一个内部属性, 使用 [[prototype]] 表示, 称为 '实例的内部属性 prototype'
a 内部属性意味着这个玩意不可读, 你没有办法访问到的
b 部分浏览器为实例提供了一个属性 '__proto__', 一样指向 实例的构造函数的原型对象.构造函数
从实例的角度来看:
1 实例但愿知道本身的构造函数是谁
2 实例但愿知道本身可使用的方法到底有多少, 但愿知道它的构造函数的原型里面到底有多少方法和属性
实例何从知道本身的构造函数是谁
经过 constructor 属性
每个 instance, 能够经过 constructor 属性, 访问到它的构造函数
instance 并不拥有 constructor 属性 当访问 instance.constructor 的时候 instance 自己不持有 从它构造函数的原型对象中查找 发现存在 constructor 属性 返回 constructor 的值.
而且存在有:
构造函数原型对象的 constructor 属性 始终指向构造函数自己。 fn.prototype.constructor === fn;
实例想要知道它的构造函数的原型对象拥有多少方法和属性
根据上面的 constructor 属性, 能够获得 instance.constructor.prototype 便可访问 或者 __proto__
应用到具体的场景里面, JS 的全部数据类型的构造函数是谁, 它们的构造函数的原型对象是什么样子的
原始值类型有:
String
Number
Null
Undefined
Boolean
构造函数分别有:
(1).__proto__ // Number
'a'.__proto__ // String
true.__proto__ // Boolean
引用值类型
Array
Function
Object
构造函数分别有:
[].__proto__ // Array
{}.__proto__ // Object
(function (){}).__proto__ // Function
更近一步的思考:
构造函数是否拥有构造函数
构造函数的原型对象是否拥有构造函数
根据上面的信息, 能够尝试一下
'a'.constructor.constructor
最终发现:
不论原始值类型, 仍是引用类型, 它们的构造函数的构造函数, 都是 Function
更近一步, Function 的构造函数是谁
通过验证, Function 的构造函数是它自己.
Function.constructor = Function;
说明构造函数到这里到底了.
构造函数的原型对象是否拥有构造函数
拥有, 你糊了, 原型对象自己就拥有一个 constructor 属性, 指向构造函数自己.
补充:
下面说的是一个规则, 不是一个推导
原型对象自己一样拥有一个内部属性 [[prototype]], 指向当前构造函数的构造函数的原型对象. 这种由原型对象构建而成的链表, 就是原型链. 原型链存在的意义, 在于尽量的共用方法和属性. 或者其余更多的我不知道的意义.
原型链长什么样子
值
'hello'
它的原型链条的
第一个原型对象
'hello'.constructor.prototype // = String.prototype
第二个原型对象
'hello'.constructor.prototype.__proto__ // = Object.prototype
这里不能再用
'hello'.constructor.prototype.constructor.prototype 来间接访问原型对象的构造函数的原型对象了.
说明 constructor.prototype 这个玩意并不靠谱, 在碰见原型对象的时候就很差用了。
第三个原型对象
'hello'.constructor.prototype.__proto__.__proto__ == null;
说明到底了.