📖
blog
  • README
  • JavaScript
    • 元素的宽高位置信息梳理
    • dom-align 源码浅析
    • Event Loop
    • 函数实参为对象时的陷阱
    • export 与 utils 方法书写规范
    • 手写 Promise 及相关代码理解
    • call,apply,bind 等函数的模拟实现
    • JavaScript继承
    • JavaScript 数据类型与类型判断
    • for..of 和 for..in 的区别
    • 写给自己看的 next 函数
    • JS 可选链与双问号
    • mouseenter 与 mouseover 事件的区别
    • Immutable相关知识
  • CSS
    • 不简单的 z-index
    • 两列布局,三列布局
    • CSS 居中方案整理
    • CSS 像素,设备像素,2倍图梳理
    • iconfont 的使用
  • Node JS
    • 实现简易的 express
  • React 核心知识点整理
    • 高阶组件
    • React 事件处理
    • React Hooks
    • React Context
  • React 状态管理
    • Redux 基础概念
    • Redux 中间件和异步操作
    • Redux Saga
    • Redux 只能有一个 store 对象嘛
  • React 开发实践
    • Ant Design Menu 组件的使用与深入
    • 讲讲吸顶效果与 react sticky
    • 基于 express,搭建 react 的开发环境
    • 通过 antd input 组件分析受控与非受控组件
    • DebounceClick 组件
    • react component Align 组件分析
    • React Portal 之事件冒泡
    • React Transition Group 源码浅析
    • React.cloneElement 父组件向子组件注入 props
    • 一次 Align 组件的问题记录
    • 如何知道子组件的类型
    • React Router 源码简单分析
    • React Redux 源码简单分析
  • Vue.js
    • Vue.js 概览
    • scoped 样式中的 deep
  • TypeScript 语法
    • 基础类型
    • 变量声明
    • 接口
    • 类
    • 函数
    • 泛型
    • 枚举
    • 类型推论
    • 类型兼容性
    • 高级类型
    • Symbol
    • 迭代器和生成器
    • 模块
    • 命名空间
    • JSX
  • 玩转 webpack
    • 第一章: webpack 与构建发展简史
    • 第二章:webpack基础用法
    • 第三章:webpack进阶用法
    • 第四章:编写可维护的 webpack 构建配置
    • 第五章:webpack构建速度和体积优化策略
    • 第六章:通过源代码掌握webpack打包原理
    • 第七章:编写Loader和插件
  • webpack 实践
    • 如何配置 output.library
  • 测试
    • 初识代码测试
    • Jest 中 如何测试 setTimeout
    • Jest Enzyme React 测试实践记录
  • WEB 开发,过往工作沉淀
    • Web安全(DVWA)
    • 内存泄露与事件移除的必要性
    • url to pdf api 与 服务部署踩坑记录
    • 前端调试指南
    • Markdown 转 email
    • github travis ci 自动部署
    • 浏览器缓存知识梳理
    • WEB 系统登录相关知识梳理
    • 将-Axios-请求参数和返回值进行格式化
    • source-map与源码调试
    • HTTPS
    • 使用 rollup 打造自己的 npm 包 (全流程)
    • father-build 是如何工作的
  • 书籍
    • 图解 HTTP 协议
    • 编写可维护的 JavaScript
    • 鸟哥的 Linux 私房菜
    • JavaScript Promise迷你书
  • Linux
    • vimtutor
    • CURL 使用指南
  • Nginx
    • 一次 nginx 分享
  • Git
    • Git Commit Message 须知
    • .gitignore 模板
    • git tag标签
  • 摄影
    • 摄影基础知识
    • 手机摄影从小白到大师
  • 翻译
    • log4js
    • log4js-node
    • 介绍GitLab上的CI/CD
    • 为GitLab Pages创建并调整GitLab CI/CD
    • 关于 rel=noopener
    • AngularJS 团队 Git 提交信息约定
    • JSON Schema
  • Lifehack
    • 20 个 Google 搜索 Tips 来高效使用 Google
    • 37 个高级 Google 搜索 Tips
Powered by GitBook
On this page
  • 前言
  • 1. 数据类型
  • 2. 数据类型
  • 3. 额外的 Utils 方法
  • 3.1 isWindow
  • 3.2 isEmptyObject
  • 3.3 isElement
  • 3.4 isValidDate (是否为有效的日期对象)
  • 4. 数据类型与内存
  • 参考资料

Was this helpful?

  1. JavaScript

JavaScript 数据类型与类型判断

PreviousJavaScript继承Nextfor..of 和 for..in 的区别

Last updated 4 years ago

Was this helpful?

前言

JS 中的数据经常打交道,与之相关的数据类型,在平常开发中却不是很在意,只有在开发中遇到问题才会去搜索相关知识,而本身没有相关的知识储备。

上周面试中,面试官问了几个问题,慢慢意识到自己基础并不扎实。

Q1: JS 有哪些数据类型? A: number,boolean,string,null,undefined,symbol, object

Q2: 有哪些方法判断数据类型? A: typeof, instanceof

Q3: 还有别的方法? A: ??? 还有嘛(疑问: Array.isArray 对,这个方法可以判断数组,那还有别的方法可以判断别的数据类型嘛?)

Q4: 哪些是原始类型? A: number,boolean,string,undefined,symbol。object 不是原始类型。(疑问:那 null 呢? typeof null 也是 object, 函数呢,Date呢,正则呢, 那怎么判断某个类型是不是原始类型?)

同时,最后面试官举了个数据类型的使用场景,在写组件的时候,写公共函数的时候,需要去校验参数的类型,如果参数不对,需要抛出对应的错误。

的确,健壮性足够强的代码,应该要考虑到很多的情况,而这些的基础都要明确数据类型。

1. 数据类型

解决 Q1, 即以下八种数据类型,其中对象类型又包含函数对象,日期对象等

中已经说明了,JS 中有 8 种数据类型(七种原始类型和对象类型):

解决 Q4, 即以下七种类型是原始类型,其他对象类型都不是原始类型

七种原始类型: 1. number 2. string 3. boolean 4. null 5. undefined 6. bigint 7. symbol

原始类型存储的都是值,是没有属性或者方法的。 如 1.toString() 会报错,因为 1 这个基础类型没有 toString 方法。

注意: '1'.toString() 是可以的, 是因为在调用 toString 方法的时候,字符串 '1' 已经转为 字符串对象 了,而对象是有方法的。

对象类型: 除了原始类型,都是对象类型

  1. 标准对象,键值对 {}

  2. 函数对象

  3. 日期,Date 对象

  4. 数组,Array 对象

  5. 正则, RegExp 对象

  6. 错误,Error 对象

2. 数据类型

typeof 表达式

结果

typeof 1

number

typeof '1'

string

typeof true

boolean

typeof undefined

undefined

typeof function() {}

function

typeof Symbol('a')

symbol

typeof null

object

typeof {}

object

typeof new Date()

object

typeof /1/

object

typeof []

object

typeof new Error()

object

也就是说,typeof 可以检验出, number,string,boolean,undefined,function, symbol 类型,而对于 null 和 其他的对象类型数据,返回值都是 object,不能区分。

那如何区分, null, 标准对象,函数对象,日期对象,数组对象,错误对象和正则对象呢?

解决 Q2,Q3, 即还可以使用 Object.prototype.toString() 方法来判断类型

答案是 Object.prototype.toString()

Object.prototype.toString.call()

结果

Object.prototype.toString.call(1)

[object Number]

Object.prototype.toString.call('1')

[object String]

Object.prototype.toString.call(true)

[object Boolean]

Object.prototype.toString.call(undefined)

[object Undefined]

Object.prototype.toString.call(function() {})

[object Function]

Object.prototype.toString.call(Symbol(1))

[object Symbol]

Object.prototype.toString.call(null)

[object Null]

Object.prototype.toString.call({})

[object Object]

Object.prototype.toString.call(new Date())

[object Date]

Object.prototype.toString.call(/1/)

[object RegExp]

Object.prototype.toString.call([])

[object Array]

Object.prototype.toString.call(new Error())

[object Error]

接下来写一个 type 函数,该函数返回任意数据的数据类型。

var class2type = {};
// 生成class2type映射
"Number String Boolean Undefined Function Symbol Null Object Date RegExp Array Error".split(" ").map(function(item, index) {
    class2type["[object " + item + "]"] = item.toLowerCase();
})
function type(){
    return class2type[Object.prototype.toString.call(obj)]
}

至此,我们能判断原始类型以及一些对象类型。

3. 额外的 Utils 方法

3.1 isWindow

依据: window 对象有 window 属性指向自身。

function isWindow(obj) {
    return obj !== null && obj === obj.window;
}

3.2 isEmptyObject

依据: 空对象上没有属性

function isEmptyObject( obj ) {
  return typeof obj === 'object' && obj !== null && !Object.keys(obj).length
}

3.3 isElement

依据: DOM 元素的 nodeType 为 1

 function isElement(obj) {
    return !!(obj && obj.nodeType === 1);
};

3.4 isValidDate (是否为有效的日期对象)

依据: isNaN(new Date('foo')) === true

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

此外,我们可以再关注一下 Date 的一下奇怪行为:

new Date('a')   // Invalid Date  此时,返回值是个"不合法日期"对象
new Date('a') === 'Invalid Date'   // false
new Date('a').toString() === 'Invalid Date'   // true

new Date('a').valueOf()  // NaN  即,这个 "不合法日期对象" 转换为数字是为 NaN  

isNaN(new Date('a'))     // true  "不合法日期对象" 为 NaN
new Date('a') instanceof Date    // true,即 "不合法日期对象" 依然是 Date 的实例


const date = new Date('a')
date.getFullYear()   // NaN  // 即 "不合法日期对象" 上调用方法一律返回 NaN
date.getMonth()      // NaN
date.getDate()       // NaN

new Date(NaN,NaN,NaN);   // Invalid Date,即返回 "不合法日期对象"

4. 数据类型与内存

在 JS 中,每一个数据都需要一个内存空间,而内存空间又被分为: 栈内存(stack)与堆内存(heap)。

number, boolean, string, null, undefined, symbol 这几种基础类型和函数,它们的值会存放在栈内存中。

而引用类型数据,如 Array (所需内存大小不一样), 标准对象 {}, 它们的值存放在堆内存中。

var a = null; // 栈
// 变量 a 存放于栈中,它的值是 null, 也是存放在栈中

var b = { m: 20 }; 
// 变量 b 存放于栈中,它的值是对象的地址,地址也存放在栈中
// 而地址指向的 {m: 20} 作为对象存在于堆内存中

参考资料

MDN
JavaScript专题之类型判断
10分钟了解JS堆、栈以及事件循环的概念