LaughingZhu's Blog
LaughingZhu
LaughingZhu
Make or miss win or lose I put my name on it

JavaScript 基础类型

JavaScript 基础类型介绍

JavaScript 共有八种数据类型,分别是 Undefined、Null、Boolean、 Number、String、Object、Symbol、BigInt。

其中 Symbol 和 BigInt 是 ES6 中新增的数据类型:

  • Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了 解决可能出现的全局变量冲突的问题。

  • BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数, 使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

这些数据可以分为 基础数据类型 引用数据类型 :

  • 栈: 原始数据类型(Undefined、Null、Boolean、Number、String)
  • 堆: 引用数据类型(对象、数组和函数) 两种类型的区别在于存储位置的不同:

在内存中存储的不同:

基础数据类型: 直接存储在栈(stack)中的简单数据段,占据空间 小、大小固定,属于被频繁使用数据,所以放入栈中存储;

引用数据类型: 存储在堆(heap)中的对象,占据空间大、大小不固 定。如果存储在栈中,将会影响程序运行的性能; 引用数据类型在栈 中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引 用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。 堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

数据类型检测的方式有哪些

  1. typeof
console.log(typeof 2); // number console.log(typeof true); // boolean console.log(typeof 'str'); // string console.log(typeof []); // object console.log(typeof function () {}); // function console.log(typeof {}); // object console.log(typeof undefined); // undefined console.log(typeof null); // object

其中数组、对象、null都会被判断为object,其他判断正确

  1. instanceof
console.log(2 instanceof Number); // false console.log(true instanceof Boolean); // false console.log('str' instanceof String); // false console.log([] instanceof Array); // true console.log(function () {} instanceof Function); // true console.log({} instanceof Object); // true

instanceof 可以正确判断对 象的类型 , 不能正确判断基础数据类型;其内部运行机制是判断其原型链中能否找到该类型的原型 prototype 属性。

  1. constructor
console.log((2).constructor === Number); // true console.log(true.constructor === Boolean); // true console.log('str'.constructor === String); // true console.log([].constructor === Array); // true console.log(function () {}.constructor === Function); // true console.log({}.constructor === Object); // true

constructor 有两个作用,一是判断数据的类型,二是对象实例通过 constructor 对象访问它的构造函数。

需要注意:如果创建一个对象来改变它的原型后,constructor 就不能用来判断数据类型了。

function Fn() {} Fn.prototype = new Array(); var f = new Fn(); console.log(f.constructor === Fn); // false console.log(f.constructor === Array); // true
  1. Object.prototype.toString.call()
const a = Object.prototype.toString; console.log(a.call(2)); // [object Number] console.log(a.call(true)); // [object Boolean] console.log(a.call('str')); // [object String] console.log(a.call([])); // [object Array] console.log(a.call(function () {})); // [object Function] console.log(a.call({})); // [object Object] console.log(a.call(undefined)); // [object Undefined] console.log(a.call(null)); // [object Null]

同样是检测对象 obj 调用 toString 方法,obj.toString()的结果和 Object.prototype.toString.call(obj) 的 结 果 不 一 样 , 这 是 为 什 么?

这是因为 toString 是 Object 的原型方法,而 Array、function 等类 型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调 用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array 类型返回元素组成的字符串...),而不会去调用 Object 上原型 toString 方法(返回对象的具体类型),所以采用 obj.toString() 不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要 得到对象的具体类型时,应该调用 Object 原型上的 toString 方法

instanceof 操作符的实现原理及实现

instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。

function muInstanceof(left, right) { // 获取对象的原型 let leftProto = Object.getPrototypeOf(left); // 获取构造函数的 prototype 对象 let rightProto = right.prototype; // 判断构造函数的 prototype 对象是否在对象的原型链上 while (true) { if (!leftProto) return false; if (leftProto === rightProto) return true; // 如果没有找到,就继续从原型上找,Object.getPrototypeOf 方法用来获取指定对象的原型 } }