JavaScript基本类型你可能不懂!

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

前言

我将从数据类型的概念、检测方法、转换方法几个方面,帮你梳理和深入学习 JavaScript 的数据类型的知识点。

数据类型概念

JavaScript 的数据类型有下图所示的 8 种:

image.png

前 7 种类型为基础类型,最后 1 种(Object)为引用类型,也是你需要重点关注的,因为它在日常工作中是使用得最频繁,也是需要关注最多技术细节的数据类型。

引用类型也分几种:Array - 数组对象、RegExp - 正则对象、Date - 日期对象、Math - 数学函数、Function - 函数对象。

基础类型、引用类型的存储区别:

  1. 基础类型:存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;
  2. 引用类型:存储在堆内存,存储的是地址,多个引用指向同一个地址,这里会涉及一个“共享”的概念。

看几个案例

题目一

let a = {
  name: 'lee',
  age: 18
}
let b = a;
console.log(a.name);  // lee
b.name = 'son';
console.log(a.name);  // son
console.log(b.name);  // son
复制代码

通过结果可以看出来,a、b用的是同一个数据源。

题目二

let a = {
  name: 'Julia',
  age: 20
}
function change(o) {
  o.age = 24;
  o = {
    name: 'Kath',
    age: 30
  }
  return o;
}
let b = change(a);
console.log(b.age);    // 30
console.log(a.age);    // 24
复制代码
  1. a作为参数被传入change,此时a、o共用一个数据,所以o被修改会影响a。
  2. 当o被重新赋值后,o、a不在存在联系。

数据类型检测

第一种判断方法:typeof

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof console.log // 'function'
复制代码
  1. 前 6 个都是基础数据类型;
  2. 虽然 typeof null 会输出 object,但这只是 JS 存在的一个悠久 Bug,不代表 null 就是引用数据类型,并且 null 本身也不是对象。因此,null 在 typeof 之后返回的是有问题的结果,不能作为判断 null 的方法。如果你需要在 if 语句中判断是否为 null,直接通过 ‘===null’来判断就好。
  3. 引用数据类型,用 typeof 来判断的话,除了 function 会判断为 OK 以外,其余都是 'object',是无法判断出来的。

第二种判断方法:instanceof

let Car = function() {}
let benz = new Car()
benz instanceof Car // true
let car = new String('Mercedes Benz')
car instanceof String // true
let str = 'Covid-19'
str instanceof String // false
复制代码

因为所有引用类型的数据都有原型,所以可以从原型链上判断,instanceof源码:

function myInstanceof(left, right) {
  // 这里先用typeof来判断基础数据类型,如果是,直接返回false
  if(typeof left !== 'object' || left === null) return false;
  // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left);
  while(true) {                  //循环往下寻找,直到找到相同的原型对象
    if(proto === null) return false;
    if(proto === right.prototype) return true;//找到相同原型对象,返回true
    proto = Object.getPrototypeof(proto);
  }
}
// 验证一下自己实现的myInstanceof是否OK
console.log(myInstanceof(new Number(123), Number));    // true
console.log(myInstanceof(123, Number));                // false
复制代码

上述两种方法优缺点

  1. instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;
  2. 而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断。

完美方法:Object.prototype.toString

Object.prototype.toString({})       // "[object Object]"
Object.prototype.toString.call({})  // 同上结果,加上call也ok
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(function(){})  // "[object Function]"
Object.prototype.toString.call(null)   //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g)    //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([])       //"[object Array]"
Object.prototype.toString.call(document)  //"[object HTMLDocument]"
Object.prototype.toString.call(window)   //"[object Window]"
复制代码

完整写法:

function getType(obj){
  let type  = typeof obj;
  if (type !== "object") {    // 先进行typeof判断,如果是基础数据类型,直接返回
    return type;
  }
  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正则中间有个空格
}
/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */
getType([])     // "Array" typeof []是object,因此toString返回
getType('123')  // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined)   // "undefined" typeof 直接返回
getType()            // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g)      //"RegExp" toString返回
复制代码

猜你喜欢

转载自juejin.im/post/7086281788464562213
今日推荐