js 数据类型总结

SegmentFault

共 5180字,需浏览 11分钟

 · 2021-05-30

作者:小白逆袭

来源:SegmentFault 思否社区


一. js数据类型

  • String
  • Number
  • Boolean
  • null
  • Undefined
  • Object(包括派生类:Array, Function, Set, Map, Date, RegExp, WeakMap, WeakSet)
  • Symbol
  • BigInt(ES2020, 用来表示大于 js中最大整数2^53 - 1 的整数)

分为基本类型(除Obejct类型外的类型)和引用类型(复合类型)

  1. 基本数据类型:值类型, 变量存储在栈内存中
  2. 引用数据类型:变量存储在堆内存和栈内存中,栈内存中存储变量的标识符和指向堆内存中该对象的指针即堆内存中该对象的地址),引用类型的值是按引用访问

undefined与null区别以及使用场景

null 指代空对象指针
使用场景:
(1)释放内存
(2)空值判断

undefined 表示此处应该有一个值,但是还没有定义
使用场景:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时或者return后面什么也没有,返回undefined

初始化变量时可根据希望存放类型指定
let a = null;  // 存放对象
let b = undefined;   //存放数值

symbol类型

symbol用于模拟私有方法或属性, 任意一个symbol数据是一个独一无二的值

symbol属性名以及对象各类属性的属性名遍历:

let obj = Object.create({}, {
  getFoo: {
    value: function() { return this.a; },
    enumerable: false,
  }
})
obj.a = 1,
obj.b = function() {},
obj[Symbol('a')] = 2,

Object.getOwnPropertySymbols(obj); //[Symbol(a)]  遍历自身symbol类型属性
Object.getOwnPropertyNames(obj); //['a''b''getFoo']  遍历自身非symbol类型属性(包括不可枚举属性)
Reflect.ownKeys(obj);  //[Symbol(a), 'a''b''getFoo']  遍历自身所有类型属性,包括不可枚举和symbol类型
Object.keys(obj); //['a''b'] 遍历自身可枚举属性, 
// for...in遍历可枚举属性(包括继承而来的), 搭配hasOwnProperty使用过滤出自身可枚举属性


二. 数据类型的判断方式

  • typeof
  • instanceof
  • constructor
  • Object.prototype.toString.call()
  1. typeof
    判断结果: 'string'、'number'、'boolean'、'undefined'、'function' 、'symbol'、'bigInt'、'object'

特殊情形

// 数据类型与typeof结果表现形式不同:
console.log(typeof function(){});  // 'function'
console.log(typeof null);          // 'object'

// 对于null, Object及其派生类型(Array, Date, RegExp等),无法使用typeof进行类型的判断,需要使用instanceof
console.log(typeof new Date());    // 'object'
console.log(typeof new RegExp());  // 'object'
  1. instanceof

语法:A instanceof B , 即判断A是否为B类型的实例,也可以理解为B的prototype是否在A的原型链上

console.log([] instanceof Array);                  // true
console.log({a: 1} instanceof Object);             // true
console.log(new Date() instanceof Date);           // true

// 注意:对于基本类型,使用字面量声明的方式可以正确判断类型
console.log(new String('dafdsf') instanceof String) // true
console.log('csafcdf' instanceof String) // false, 原型链不存在
  1. constructor

当一个函数F被定义时,JS引擎会为F添加prototype原型,然后在prototype上添加一个constructor属性,并让其指向F的引用,F利用原型对象的constructor属性引用了自身,当F作为构造函数创建对象时,原型上的constructor属性被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让对象诞生以后,就具有可追溯的数据类型

console.log([].constructor === Array)                // true
console.log(new Date().constructor === Date)         // true
console.log(new RegExp().constructor === RegExp)     // true

// 特殊的, null和undefined无法使用这种方式判断,因为他们不是通过构造函数方式声明

在js中,一般会使用修改原型的方式实现js的继承,这种情况下一般要同步修改constructor 属性, 防止引用的时候出错, 例如:

function Aoo(){}
function Foo(){} 
Foo.prototype = new Aoo();
Foo.prototype.constructor = Foo;
var foo = new Foo(); 
console.log(foo instanceof Foo)//true 
console.log(foo instanceof Aoo)//true
  1. Object.prototype.toString.call()
console.log(Object.prototype.toString.call(1))          // '[object Number]'
console.log(Object.prototype.toString.call(1n))         // '[object BigInt]'
console.log(Object.prototype.toString.call('123'))      // '[object String]'
console.log(Object.prototype.toString.call(null))       // '[object Null]'
console.log({}.toString())         // '[object Object]'
console.log(Object.prototype.toString.call([]))         // '[object Array]'
console.log(Object.prototype.toString.call(function a() {}))  // '[object Function]'
综上可得,最能准确判断数据类型的方式为Object.prototype.toString.call()
特别的,实际项目开发中,经常用于判断对象和数组的几种方式:
  • instanceof
  • isPrototypeOf: Array.isPrototypeOf({} | []), 基于原型链的概念
  • constructor: [] | {}.constructor = Array
  • isArray
  • Object.prototype.toString.call({} | [])


点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流,扫描下方”二维码“或在“公众号后台回复“ 入群 ”即可加入我们的技术交流群,收获更多的技术文章~

- END -


浏览 9
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报