博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS 原型的解释
阅读量:5894 次
发布时间:2019-06-19

本文共 2172 字,大约阅读时间需要 7 分钟。

首先明确两个概念: 构造函数和 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;

说明到底了.

转载地址:http://sxisx.baihongyu.com/

你可能感兴趣的文章
Oracle数据库备份与恢复的三种方法
查看>>
提升SQLite数据插入效率低、速度慢的方法(转)
查看>>
Spring容器AOP的理解
查看>>
启动Tomcat的小细节--MyEclipse
查看>>
Java线程池的使用以及原理
查看>>
Javascript中call,apply,bind方法的详解与总结
查看>>
mac 下apache服务的根目录
查看>>
iOS图像处理之Core Graphics和OpenGL ES初见
查看>>
是什么让C#成为最值得学习的编程语言
查看>>
Linux命令学习总结:ls
查看>>
python入门(2)python的安装
查看>>
NYOJ 49 开心的小明(01背包问题)
查看>>
Android驱动之 Linux Input子系统之TP——A/B(Slot)协议【转】
查看>>
Oracle 12c 多租户 CDB 与 PDB之 shared undo 与 Local undo 切换
查看>>
获取Android运行apk的packagename 和activityname
查看>>
自己动手写编译器
查看>>
Intent 使用方法全面总结
查看>>
leetcode dfs Palindrome Partitioning
查看>>
正确理解线程和进程
查看>>
[技术讨论][全程建模]一个类应该有多少方法?多大就须要拆分?
查看>>