昨天晚上接到了蚂蚁金服的电面其中有一道题, 让我印象深刻, 结束之后, 我就去查了资料, 写了一篇拙劣的文章来总结
问题
- var a = {}; a.__proto__ === ?
- var a = 1; a.__proto__ === ?
当时模棱两可, 我知道他们的顶端都是 Object.prototype 就直接回答这个选项, 因为当时心里想着一切不是皆对象吗, 那对象的原型链顶端不就是 Object.prototype 吗? 还有为什么数字有原型链? 脑子浮现出 Functin,Array 各种数据类型, 但是还是非常的模糊, 回答了之后面试官也没有继续追问(可能觉得我不清楚吧), 但是这个问题始终是我心里的一个结, 查了一些资料后, 并对其进行了整理
大家都知道, JavaScript 的数据类型分为两种, 一种是基础数据类型, 另一种是引用数据类型
什么是基础类型(primitive )?
[A primitive (primitive value, primitive data type) is data that is not an object and has no methods.]没有属性和方法的数据
类型转化
首先我们看第二个问题, 从第二个问题着手来讲解,
var a = 1; a.__proto__=== ?
去浏览器运行下可以知道,
a.__proto__=== Number.prototype
, 然后我们再这样运行
a.__proto__.__proto__=== Object.prototype
得到的结果竟然是 true
在前端我们说了, js 分两种类型, 那为什么一个数字 (a) 的原型链顶端是 Object 的原型? 两者是怎么联系的? primitive 不是没有属性和方法吗? 哪里来的原型链?
原来是这样的, js 是弱语言, 如果他发现类型不匹配的时候, 他会干嘛? 他会类型转化 (Auto Convert) 啊
所以以上的问题变形一下就变成了
var a = 1; new Number(a).__proto__=== ?
这样问题就变得很明了了, 一个 Number 方法, 构造了一个 Number 的实例, 那么原型链肯定是 Number 的原型啊 (即 Number.prototype) 再者, 一个 Number 方法构造出的实例, 必然有原型链既然已经是一个实例, 就是一个对象, 再往上, 必然是 Object.prtotype
再看一下栗子
- var a = "abc";
- console.info(a.length);
- var b = 1;
- console.info(b.toString());
这就是我们平常一直在使用的, 理解上面的问题, 你心中肯定知道了原因, 为什么 a,b 是 primitive , 但是为什么还有其他的属性也是因为类型的转化, 等同于
- var a = "abc";
- console.info(new String(a).length);
- var b = 1;
- console.info(new Number(b).toString());
小结
总结以上, 所以, js 基础类型确实和引用类型没有关系! 没有关系! 让他们发生关系的是! 类型转化 (因为 js 自身原因, 强行让他们发生了关系) 并且基础类型没有方法, 没有属性
所以我觉得那句, js 万物皆对象, 真的有点坑人
原型链
但是后来我又想, 不是还有一些 function,array,date 之类的吗, 那些又是什么, 属于什么这次我一并将他们理清楚还有那些强行发生关系的构造函数, 例如 Number,String,Boolean,Date?
以上就是我整理的关系以及引用类型的原型链走向
提示(有些不太明白同学可能会误会):
(我把 Date,Number,Boolean,String 归类到了 Function 而刚才不是说原型链上是 Objec.prototype 么, 那是你要搞清楚方法和 new 方法(), 方法通过 new 对象就变成了 Object 下面也进行一些证明)
小结
Object 只是在 js 中充当了一个复杂的类型, 包含了许多的子集, 但是 Object 和基础类型还是属于平行关系了
延伸
通过以上的理解, 还自己创建了一个用原型链对类型判断的方法 (因为据说用 Object.prototype.toString.call() 这样的实现方式有点丑陋而且奇怪的方法, 别人会不明白你写的是什么东西)
- var a = null;
- var b = 1;
- var c = '1';
- var d = undefined;
- var g = true;
- var e = function() {};
- var f = [];
- var h = new Date();
- var i = {}
- function type(a) {
- if (a === null) {
- return 'null';
- }
- if (typeof a === 'number') {
- return 'number';
- }
- if (typeof a === 'string') {
- return 'string'
- }
- if (typeof a === 'undefined') {
- return 'undefined';
- }
- if (typeof a === 'boolean') {
- return 'boolean';
- }
- if (a instanceof Array) {
- return 'array';
- }
- if (a instanceof Date) {
- return 'date';
- }
- if (a instanceof Function) {
- return 'function';
- }
- if (a instanceof Object) {
- return 'object';
- }
- }
- console.log(type(a)); // null
- console.log(type(b)); // number
- console.log(type(c)); // string
- console.log(type(d)); // undefined
- console.log(type(f)); // array
- console.log(type(e)); // function
- console.log(type(g)); // boolean
- console.log(type(h)); // date
- console.log(type(i)); // object
总结
通过以上无非就想说明基础类型和引用类型的关系, 以及各个类型的原型链说的有点乱, 如果有不对的地方请提出, 我及时更正, 以免带来误导 留下一个问题, 如果以上说的你都理解了, 那么你必然知道这个答案
- var a = 1;
- a.a = 1;
- console.log(a.a);
来源: https://juejin.im/post/5aa5d9f46fb9a028cf321a8c