likes
comments
collection
share

JS基础-1|原生数据类型和ES6数据类型以及数据类型检测

作者站长头像
站长
· 阅读数 22

数据类型是实际开发中经常使用的知识,本篇沉淀一下数据类型的相关知识。

关于ECMAScript历史

在博客开始之前先了解一下JS和ECMAScript的历史和版本。

现在2021年了,每年一个版本,现在ECMAScript也更新到了ECMAScript2021了。其中变动比较大的属于ES5和ES6版本。

ECMAScript5: 也称为ES5,于2009年发布(并非2015年)。

ECMAScript2015:也称为ES6,于2015年发布(并非2016年)。

后续版本均已年份命名了,也可称为ES7、ES8、ES9...

关于ES的发展史可以参考以下文章:

原生数据类型

数据类型是js基础中的基础,在实际工作中经常使用,如果面试被问到,你会怎么回答?

在这里,我们将数据类型分为三类进行回答:基础数据类型和复杂数据类型和ES6新增数据类型。

分别对三种类型详细说明,可以给面试官留下基础扎实、表达清晰的印象。

基础数据类型

最基本的数据类型:

null: 不存在的事物(万物从不存在开始)

undefined: 未定义(有变量没有值)

string:字符串,被引号包裹的值(值从字符开始)

number:数值,整数、小数、科学计数法的数字(123e5)(想想你口袋中的money)

boolean:布尔值,true和false(代码世界只有对错)

复杂数据类型

复杂的对象数据类型,包含:

object:对象,用花括号包裹的(一个人有很多属性)

array:数组,用中括号包裹的(类似一群人~)

ES6新增数据类型

Symbol:独一无二的值,属于基础数据类型

Set:类似于数组,但是值都是唯一的,属于数据结构

WeakSet:与Set类似,但WeakSet的值只能是对象,WeakSet 中的对象都是弱引用,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存

Map:类似于对象,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。属于数据结构

WeakMap:与Map结构类似,但WeakMap只接受对象作为键名(null除外),WeakMap的键名所指向的对象,不计入垃圾回收机制

数据类型检测

以下是以往开发中常用的数据类型检测方法,并配置测试案例进行检测,归纳总结各个方法的特点。

解决方案一:typeof

typeof返回变量或表达式的类型,值有string、number、boolean、undefined、object、function

typeof '';             // 'string'
typeof 1;              // 'number'
typeof false;          // 'boolean'
typeof undefined;      // 'undefined'
typeof {};             // 'object'
typeof function () {}; // 'function' 
typeof Symbol();       // 'symbol'

// 以下检测失败
typeof [];             // 'object'
typeof null;           // 'object'
typeof new Set();      // 'object'
typeof new Map();      // 'object'

结论:只支持string、numbe、boolean、undefined、function、symbol等类型检测

解决方案二:instanceof

instanceof用于检测实例是否属于某个构造函数,返回true和false

(null) instanceof Null;              // 报错
(undefined) instanceof Undefined;    // 报错
('1') instanceof String;             // false
(1) instanceof Number;               // false
(Symbol()) instanceof Symbol         // false
([]) instanceof Array;               // true
({}) instanceof Object;              // true
(function () {}) instanceof Function // true

// 拓展自定义构造函数
function App() {}
(new App()) instanceof App;      // true

结论:支持Object、Array和自定义构造函数检测

解决方案三: constructor

constructor用于返回对象的构造函数。

(null).constructor.toString().indexOf('Null') > -1; // 报错
(undefined).constructor.toString().indexOf('Undefined') > -1; // 报错
('1').constructor.toString().indexOf('String') > -1;
(1).constructor.toString().indexOf('Number') > -1;
(true).constructor.toString().indexOf('Boolean')> -1;
(new Symbol()).constructor.toString().indexOf('Symbol') > -1; // 报错
({}).constructor.toString().indexOf('Object') > -1;
([]).constructor.toString().indexOf('Array') > -1;
(function(){}).constructor.toString().indexOf('Function') > -1;

// 拓展自定义构造函数
function App () {}
new App().constructor.toString().indexOf('App') > -1; // true

结论:null、undefined和Symbol无法检测,支持自定义构造函数检测

解决方案四:Object.prototype.toString.call()

该方法可以判断对象的类型

Object.prototype.toString.call(null) === '[object Null]';
Object.prototype.toString.call(undefined) === '[object Undefined]';
Object.prototype.toString.call('1') === '[object String]';
Object.prototype.toString.call(1) === '[object Number]';
Object.prototype.toString.call(true) === '[object Boolean]';
Object.prototype.toString.call(new Symbol()) === '[object Symbol]'; // 报错
Object.prototype.toString.call({}) === '[object Object]';
Object.prototype.toString.call([]) === '[object Array]';
Object.prototype.toString.call(function(){}) === '[object Function]';

// 拓展自定义构造函数
function App () {}
Object.prototype.toString.call(new App()) === '[object App]'; // false

结论:支持null和undefined,但不支持自定义构造函数检测

总结沉淀

对比以上四个检测方法,不难看出:

  1. typeof支持基础的字符串、数值、布尔值、undefined等检测,但不支持null、array、构造函数等。
  2. instanceof支持Object、Array和自定义构造函数检测,但对基础类型不支持。
  3. constructor支持基础类型和自定义构造函数,但是不支持null、undefined和Symbol
  4. Object.prototype.toString.call()支持除Symbol外的所有类型,但是不支持自定义构造函数
  5. ES5新增了Array.isArray用于检测数组的方法

因此:

  • 若检测js数据类型Object.prototype.toString.call()是最强大的\
  • 若检测ES6的Symbol使用typeof
  • 若检测自定义构造函数需要用instanceofconstructor

Symbol

Symbol是ES6新增的数据类型,用于表示唯一值。

var name1 = Symbol()
console.log(name) // Symbol()
var name2 = Symbol()
console.log(name1 === name2) // false

只打印了Symbol(),而且两个变量值不相等,并没有实际的值。可以理解为程序内部唯一值。继续深入

const name = Symbol()
const obj = { [name]: '张三', age: 1 }
console.log(obj) // {age: 1, Symbol(): '张三'}
console.log(obj[name]) // '张三'
console.log(Object.keys(obj)) // ['age']

直接打印obj时key为Symbol(),但是通过变量可以获取到obj的值,获取对象的key集合也没有Symbol,可以理解Symbol为Obj对象添加了私有变量。

Symbol的用法在Vue3中会有实战,在这里不在赘述,仅了解Symbol的特性即可,后续基于Symbol的特性进行实际场景应用。

相关试题

  1. JS中数据类型有哪些
  2. ES6新增的数据类型有哪些
  3. 如何判定数组的数据类型
  4. 通过构造函数创建的对象怎么检测类型
  5. Symbol数据类型的特点,实际应用有哪些?