一. js数据类型

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

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

  1. 基本数据类型:按值访问,值保存在栈内存中,占固定大小的内存空间
  2. 引用数据类型:按引用访问,变量存储在堆内存和栈内存中,栈内存中存储变量的标识符和指向堆内存中该对象的指针即堆内存中该对象的地址
null 指代空对象指针
使用场景:
(1)释放内存
(2)空值判断

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

初始化变量时可根据希望存放类型指定
let a = null;  // 存放对象
let b = undefined;   //存放数值
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
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
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]'

特别的,实际项目开发中,经常用于判断对象和数组的几种方式:

  • instanceof
  • isPrototypeOf: Array.isPrototypeOf({} | []), 基于原型链的概念
  • constructor: [] | {}.constructor = Array
  • isArray
  • Object.prototype.toString.call({} | [])
03-05 23:46