Js 数据类型

314 阅读4分钟

0.最新的 ECMAScript 标准定义了哪 8 种数据类型--- 参考

7 种基础类型:

  • Boolean、Number、String
  • Null、Undefined
  • BigInt、Symbol(ES6)

1 种引用类型 :Object


1.null 和 undefined的区别--- 参考

null表示"没有对象",即该处不应该有值

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义

Number(null)
// 0

Number(undefined)
// NaN

2.检查数据类型的方法

1.typeof是检测一个变量是不是基本数据类型的最佳工具

console.log(typeof "");   // string
 
console.log(typeof 1);    // number
 
console.log(typeof true);   // boolean
 
console.log(typeof undefined);    // undefined
 
console.log(typeof null);    // object
 
console.log(typeof {});    // object
 
console.log(typeof []);   // object
 
console.log(typeof function(){});   // function

2. instanceof 检测当前实例是否隶属于某各类

console.log("1" instanceof String);  // false
 
console.log(1 instanceof Number);   // false
 
console.log(true instanceof Boolean);  // false
 
console.log({} instanceof Object);  // true
 
console.log([] instanceof Array);  // true
 
console.log(function(){} instanceof Function)  // true

console.log(null instanceof Null);  // 报错
 
console.log(undefined instanceof Undefined); // 报错

3.constructor

console.log(("1").constructor === String);   // true
 
console.log((1).constructor === Number);   // true
 
console.log((true).constructor === Boolean);   // true
 
console.log(({}).constructor === Object);   // true
 
console.log(([]).constructor === Array);   // true
 
console.log((function() {}).constructor === Function);   // true

4.Object.prototype.toString.call()

console.log(Object.prototype.toString.call("1"));   // {object  String}
 
console.log(Object.prototype.toString.call(1));   // {object  Number}
 
console.log(Object.prototype.toString.call(null));   // {object  Null}
 
console.log(Object.prototype.toString.call(undefined));   // {object  Undefined}
 
console.log(Object.prototype.toString.call(true));   // {object  Boolean}
 
console.log(Object.prototype.toString.call({}));   // {object  Object}
 
console.log(Object.prototype.toString.call([]));   // {object  Array}
 
console.log(Object.prototype.toString.call(function () {});   // {object  Fuction}

3.数据类型转换

强制转换
    Number()
        原始类型:有不能转为数字的,就是NaN
            Number(false) => 0
            Number(true) => 1
            Number(undefined) => NaN
            Number(null) => 0
            Number("1.2") => 1.2
            Number("12") => 12
            Number("1.2.3") => NaN
            Number(new object()) => NaN
            Number(50) => 50
        Number({}) => NaN
    String()
        原始类型值的转换规则
            数值:转为相应的字符串。
            字符串:转换后还是原来的值。
            布尔值:true转为"true"false转为"false"。
            undefined:转为"undefined"。
            null:转为"null"。
        String({a: 1}) => "[object Object]"
        String([1, 2, 3]) => "1,2,3"
    Boolean()
        false
            undefined
            null
            -0
            0或+0
            NaN
            false
            ''
        true
            所有对象,包括{}、布尔对象new Boolean(false)
自动转换
    场景:
        不同类型的数据互相运算
            123 + 'abc' => "123abc"
        对非布尔值类型的数据求布尔值
            if ('abc')
        对非数值类型的数据使用一元运算符(即“+”和“-”)
            + {foo: 'bar'} => NaN
    本质:
        以强制类型为基础,转为需要的number、string、boolean

4.深拷贝和浅拷贝

浅拷贝:浅拷贝通过ES6新特性Object.assign()或者通过扩展运算法...来达到浅拷贝的目的,浅拷贝修改
副本,不会影响原数据,但缺点是浅拷贝只能拷贝第一层的数据,且都是值类型数据,如果有引用型数据,修改
副本会影响原数据。

深拷贝:通过利用JSON.parse(JSON.stringify())来实现深拷贝的目的,但利用JSON拷贝也是有缺点的,
当要拷贝的数据中含有undefined/function/symbol类型是无法进行拷贝的,当然我们想项目开发中需要
深拷贝的数据一般不会含有以上三种类型,如有需要可以自己在封装一个函数来实现。

浅拷贝

首先可以通过 Object.assign 或 展开运算符 ... 来解决这个问题

let a = {
    age: 1
}
let b = Object.assign({}, a) // or {...a}
a.age = 2
console.log(b.age) // 1

通常浅拷贝就能解决大部分问题了,但是当我们遇到如下情况就需要使用到深拷贝了

let a = {
    age: 1,
    jobs: {
        first: 'FE'
    }
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native

深拷贝

let a = {
    age: 1,
    jobs: {
        first: 'FE'
    }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是该方法也是有局限性的:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
  • 在遇到function、 undefined 或者 symbol 的时候,该对象也不能正常的序列化
let a = {
    age: undefined,
    sex: Symbol('male'),
    jobs: function() {},
    name: 'wb'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "wb"}

当然如果你的数据中含有以上三种情况下,可以使用递归来实现一个深拷贝方法,因此,这里就封装一个工具函数来供实现深拷贝。

封装工具

// 精准判断类型函数
function  typeOf (obj) {
  const  toString = Object.prototype.toString
  const  map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  return map[toString.call(obj)]
}
// util 深拷贝函数
export function deepClone (data) {
  const t = typeOf(data)
  let o
  if (t === 'array') {
    o = []
  } else if (t === 'object') {
    o = {}
  } else {
    return data
  }
  if (t === 'array') {
    for (let i = 0; i < data.length; i++) {
      o.push(deepCopy(data[i]))
    }
  } else if (t === 'object') {
    for (let i in data) {
      o[i] = deepCopy(data[i])
    }
  }
  return o
}