阿里云优惠活动,点击链接进行购买: 一年仅需96.9元即可以购买服务器~

腾讯云优惠活动, 点击链接进行购买一年仅需99元

腾讯云限时开团活动, 点击链接进行购买一年仅需95元

各大服务器厂商对比选购

# 你不知道的 js 类型转化和原型链

昨天晚上接到了蚂蚁金服的电面。其中有一道题,让我印象深刻,结束之后,我就去查了资料,写了一篇拙劣的文章来总结。

# 问题

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 (opens new window) and has no methods (opens new window).]没有属性和方法的数据。

# 类型转化

首先我们看第二个问题,从第二个问题着手来讲解,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);
Last Updated: 9/12/2022, 3:03:48 PM