一. js 数据类型
- String
- Number
- Boolean
- null
- Undefined
- Object(包含 js 派生类:Array, Function, Set, Map, Date, RegExp, WeakMap, WeakSet)
- Symbol
- BigInt(ES2020, 用来示意大于 js 中最大整数 2^53 – 1 的整数)
分为根本类型(除 Obejct 类型外的类型)和援用类型(复合类型,Object 类型)
- 根本数据类型:值类型, 变量存储在栈内存中
- 援用数据类型:变量存储在堆内存和栈内存中,栈内存中 存储变量的标识符和 指向堆内存中该对象的指针即 堆内存中该对象的地址 ),援用类型的值是 按援用拜访 的
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()
- 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'
- 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, 原型链不存在
- 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
- 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(Object.prototype.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({} | [])