资讯专栏INFORMATION COLUMN

JS 原型的解释

silvertheo / 3087人阅读

首先明确两个概念: 构造函数和 instance 分别是什么

构造函数
JS 中并没有在语法层面上面区分构造函数和普通函数, 唯一的区别是调用方式
使用 new 调用的函数就是构造函数, 没有则是普通函数.

实例
new Constructor() 返回的对象称为 Constructor 的一个实例

然后提出一个规则:
在构造函数的原型上面附加的属性或者方法, 可以被其所有的实例共用.

可以推导出:

构造函数可以访问到它的原型, 并且向其上面添加方法和属性

构造函数的原型应该是一个对象, 这样才能向其上添加方法和属性

实例也拥有其构造函数的原型的一个引用, 要不然无法共用.

解释:
1 构造函数的确有一个属性, 可以访问到它的原型, 属性名为 prototype.
规范下称呼:
a 函数的 prototype 属性, 称为 "原型属性"
b 函数的 原型属性指向的 对象, 称为 "原型对象"

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;

说明到底了.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88289.html

相关文章

  • JS 进阶 (一)作用域深入和面向对象

    摘要:进阶第一章作用域深入和面向对象预解释全局作用域当浏览器加载页面的时候,提供了一个全局代码执行的环境预解释变量提升在当前的作用域中,代码执行之前,浏览器首先会默认的吧所有带有和的进行提前声明或定义理解声明和定义声明告诉浏览器在全局作用域中有 JS进阶 第一章作用域深入和面向对象 预解释 1、全局作用域:当浏览器加载HTML页面的时候,提供了一个全局js代码执行的环境 2、预解释(变量提升...

    chengtao1633 评论0 收藏0
  • javascript基础学习

    摘要:预解释变量和函数的预解释只发生在当前的作用于中中内存的分类栈内存用来提供一个代码指定的环境作用域全局作用域和局部作用域堆内存用来存储引用类型的值对象存储的是键值对,函数储存的是字符串函数执行的时候形成一个私有作用域有形参给形参赋值,形参也 预解释 变量和函数的预解释只发生在当前的作用于中 js中内存的分类 栈内存:用来提供一个js代码指定的环境 —>作用域(全局作用域和局部作用域...

    魏明 评论0 收藏0
  • 用小猪佩奇说明Javascript原型原型

    摘要:它指向构造函数的原型对象这是原型对象上的一个指向构造函数的属性。先看代码的构造函数创建一个的实例,小猪佩奇敲黑板,划重点,理解这一句整个问题的关键,请多重复几遍。也就是说小猪佩奇的原型,就是从继承来的写成代码就是这个样子。   没错,我就是标题党!你已经成功被我骗进来了。来都来了,那就聊聊再走呗!接下来就听我一本正经地跟你说道说道。   Javascript的原型是这门语言的一个重点和...

    vibiu 评论0 收藏0
  • 前端面试笔记 - js相关

    摘要:将单个事件绑定在父对象上,利用冒泡机制监听来自子元素的事件。事件目标当到达目标元素之后,执行目标元素该事件相应的处理函数。函数对象当使用去调用构造函数时,相当于执行了原型对象上都有个预定义的属性,用来引用它的函数对象。 请解释事件代理 (event delegation)。 将单个事件绑定在父对象上,利用冒泡机制,监听来自子元素的事件。 优点:解决子元素增加删除时候的事件处理,防止内存...

    Dogee 评论0 收藏0
  • 前端面试题收集,持续更新中

    摘要:对于所访问的每个元素,函数应该将该元素传递给所提供的回调函数。 HTML 在线阅读Github地址 题目列表 HTML HTML和XHTML的区别 Html的语义化 Doctype的文档类型 cookie、sessionSttorage、localStory区别 HTML全局属性(global attribute)有哪些? 常见的浏览器内核有哪些? 介绍一下你对浏览器内核的理解?...

    kgbook 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<