UzumakiItachi
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

UzumakiItachi

起风了,唯有努力生存。
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

    • 手撕Promise
    • 手撕JS八股文系列
    • 手撕观察者模式和发布订阅模式
    • 页面可见性——visibilitychange
    • JS数据类型那点事儿
      • 前言
      • JS的数据类型有哪些?
        • 基本类型
        • 引用类型
      • 如何判断类型?
        • typeOf
        • instanceof
        • Object.prototype.toString()
      • 类型强制转换
        • 类型转换前置知识——ToPrimitive(引用类型转换为原始值)
        • 何时自动转为string?
        • 何时自动转为number?
        • 何时自动转为boolen?
      • 总结
    • 作用域、执行上下文和this
    • 防抖和节流
    • 装饰器
    • JS设计模式小结
  • CSS

  • 前端
  • JavaScript
hanhanbuku
2023-03-20
目录

JS数据类型那点事儿

# 前言

js是一门弱类型语言,也就是在创建变量时并不强制限制变量的类型,而是根据赋值决定最终类型。这也就会导致某个变量可能一秒前还是字符串,下一秒就变成number了。虽然在书写过程中灵活度变高了,但是一旦发生bug,排查起来也是非常的头疼。下面就一起来深入了解一下js的数据类型吧

# JS的数据类型有哪些?

首先JS的数据类型一共分为两大类:基本类型和引用类型

# 基本类型

存储在内存栈中,值不可变。分为以下几种:

  • string(字符串)
  • boolean(布尔值)
  • number(数字)
  • symbol(符号)
  • null(空值)
  • undefined(未定义)

注意: 1.string 、number 、boolean 和 null undefined 这五种类型统称为原始类型(Primitive),表示不能再细分下去的基本类型; 2.symbol是ES6中新增的数据类型,symbol 表示独一无二的值,通过 Symbol 函数调用生成,由于生成的 symbol 值为原始类型,所以 Symbol 函数不能使用 new 调用; 3.null 和 undefined 通常被认为是特殊值,这两种类型的值唯一,就是其本身。

# 引用类型

存储在内存堆中,也可称作对象类型。array和function也是对象的子类型。对象在逻辑上是属性的无序集合,是存放各种值的容器。对象值存储的是引用地址,所以和基本类型值不可变的特性不同,对象值是可变的。

# 如何判断类型?

JS为我们提供了以下几种方式可供判断数据类型

# typeOf

通过 typeof操作符来判断一个值属于哪种基本类型。

typeof 'seymoe'    // 'string'
typeof true        // 'boolean'
typeof 10          // 'number'
typeof Symbol()    // 'symbol'
typeof null        // 'object' 无法判定是否为 null
typeof undefined   // 'undefined'

typeof {}           // 'object'
typeof []           // 'object'
typeof(() => {})    // 'function'
1
2
3
4
5
6
7
8
9
10

typeOf可以有效的判断基本数据类型,但是对引用类型的判断稍有欠缺,除了function之外其余的都会判定为Object。需要注意,typeOf判断null类型也为Object。

# instanceof

instanceof可以用来判断引用类型,他的原理是通过构造函数的prototype 是否出现在对象的原型链上来判断的。

[] instanceof Array            // true
({}) instanceof Object         // true
(()=>{}) instanceof Function   // true
1
2
3

要注意,instanceof也不是万能的,例如一个引用类型的子类型:array,function,他们的原形对象Array,Function的原型链最终指向的还是Object,所以在判断他们的类型的时候他们也同时满足Object类型

let arr = []
let obj = {}
arr instanceof Array    // true
arr instanceof Object   // true
obj instanceof Object   // true
1
2
3
4
5

并且如果目标变量的原型链被修改过的话也会导致instanceof判断错误

# Object.prototype.toString()

判断js数据类型的终极办法 Object.prototype.toString()

Object.prototype.toString.call({})              // '[object Object]'
Object.prototype.toString.call([])              // '[object Array]'
Object.prototype.toString.call(() => {})        // '[object Function]'
Object.prototype.toString.call('seymoe')        // '[object String]'
Object.prototype.toString.call(1)               // '[object Number]'
Object.prototype.toString.call(true)            // '[object Boolean]'
Object.prototype.toString.call(Symbol())        // '[object Symbol]'
Object.prototype.toString.call(null)            // '[object Null]'
Object.prototype.toString.call(undefined)       // '[object Undefined]'

Object.prototype.toString.call(new Date())      // '[object Date]'
Object.prototype.toString.call(Math)            // '[object Math]'
Object.prototype.toString.call(new Set())       // '[object Set]'
Object.prototype.toString.call(new WeakSet())   // '[object WeakSet]'
Object.prototype.toString.call(new Map())       // '[object Map]'
Object.prototype.toString.call(new WeakMap())   // '[object WeakMap]'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 该方法本质就是依托Object.prototype.toString() 方法得到对象内部属性 [[Class]]
  • 传入原始类型却能够判定出结果是因为对值进行了包装
  • null 和 undefined 能够输出结果是内部实现有做处理

# 类型强制转换

类型强制转换一般发生在不同类型的运算上,下面就一起来看看不同类型在不同情况下都会发生哪些强制类型转换吧

一般强制转换分为以下几种

  • 转为string
  • 转为number
  • 转为boolen

# 类型转换前置知识——ToPrimitive(引用类型转换为原始值)

在学习基本类型的强制转换之前我们先来学习一下引用类型的强制转换

ToPrimitive对原始类型不发生转换处理,只针对引用类型(object)的,其目的是将引用类型(object)转换为非对象类型,也就是原始类型。

ToPrimitive 运算符接受一个值,和一个可选的期望类型作参数。ToPrimitive 运算符将值转换为非对象类型,如果对象有能力被转换为不止一种原语类型,可以使用可选的 期望类型 来暗示那个类型。 转换后的结果原始类型是由期望类型决定的,期望类型其实就是我们传递的type。直接看下面比较清楚。 ToPrimitive方法大概长这么个样子具体如下。

/**
* @obj 需要转换的对象
* @type 期望转换为的原始数据类型,可选
*/
ToPrimitive(obj,type)
1
2
3
4
5

type不同值的说明

  • type为string
  1. 先调用obj的toString方法,如果为原始值,则return,否则进行第2步
  2. 调用obj的valueOf方法,如果为原始值,则return,否则进行第3步
  3. 抛出TypeError 异常
  • type为number
  1. 先调用obj的valueOf方法,如果为原始值,则return,否则进行第2步
  2. 调用obj的toString方法,如果为原始值,则return,否则第3步
  3. 抛出TypeError 异常
  • type参数为空
  1. 该对象为Date,则type被设置为String
  2. 否则,type被设置为Number

Date数据类型特殊说明:

对于Date数据类型,我们更多期望获得的是其转为时间后的字符串,而非毫秒值(时间戳),如果为number,则会取到对应的毫秒值,显然字符串使用更多。 其他类型对象按照取值的类型操作即可。

ToPrimitive总结

ToPrimitive转成何种原始类型,取决于type,type参数可选,若指定,则按照指定类型转换,若不指定,默认根据实用情况分两种情况,Date为string,其余对象为number。那么什么时候会指定type类型呢,那就要看下面两种转换方式了。

toString

Object.prototype.toString() toString() 方法返回一个表示该对象的字符串。 每个对象都有一个 toString() 方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用。 这里先记住,valueOf() 和 toString() 在特定的场合下会自行调用。

valueOf

Object.prototype.valueOf()方法返回指定对象的原始值。 JavaScript 调用 valueOf() 方法用来把对象转换成原始类型的值(数值、字符串和布尔值)。但是我们很少需要自己调用此函数,valueOf 方法一般都会被 JavaScript 自动调用。 不同内置对象的valueOf实现:

  • String => 返回字符串值
  • Number => 返回数字值
  • Date => 返回一个数字,即时间值,字符串中内容是依赖于具体实现的
  • Boolean => 返回Boolean的this值
  • Object => 返回this
var str = new String('123');
console.log(str.valueOf());//123

var num = new Number(123);
console.log(num.valueOf());//123

var date = new Date();
console.log(date.valueOf()); //1526990889729

var bool = new Boolean('123');
console.log(bool.valueOf());//true

var obj = new Object({valueOf:()=>{
    return 1
}})
console.log(obj.valueOf());//1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 何时自动转为string?

字符串自动转换主要发生在加法运算,当相加的变量里有一个字符串时,另外一个就会发生强制转换,转为string。 基本类型与字符串相加示例

'2' + 1 // '21'
'2' + true // "2true"
'2' + false // "2false"
'2' + undefined // "2undefined"
'2' + null // "2null"
1
2
3
4
5

字符串和对象相加 这个时候对象需要转为字符串,遵循ToPrimitive规则,传入string后,会先调用对象的toString方法,返回的不是原始值的话再调用valueOf方法。

//toString的对象
var obj2 = {
    toString:function(){
        return 'a'
    }
}
console.log('2'+obj2)
//输出结果2a,改写了obj2对象的toString,返回字符串a,为原始类型,所以直接return,最终得到2a

//常规对象
var obj1 = {
   a:1,
   b:2
}
console.log('2'+obj1);
//输出结果 2[object Object],调用toString,返回一个[object Object]的字符串,最终得到2[object Object]

//几种特殊对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['koala',1] // 2koala,1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 何时自动转为number?

  • 有加法运算符,但是无String类型的时候,都会优先转换为Number类型
true + 0 // 1
true + true // 2
true + false //1
1
2
3
  • 除了加法运算符,其他运算符都会把运算自动转成数值
'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN

//一元运算符(注意点)
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

注意

null转为数值时为0,而undefined转为数值时为NaN。

# 何时自动转为boolen?

  • 布尔比较时
  • if(obj) , while(obj) 等判断时或者 三元运算符只能够包含布尔值

# 总结

  • JS数据类型一共分为两大类,分别是基本数据类型(string,boolean,number,symbol,null,undefined)和引用数据类型(Object,以及Object子类型function,array)
  • 判断数据类型的方法大致有三种typeof,instanceof,Object.prototype.toString()
  • typeof可以判断除null以外的其他基本数据类型,无法判断引用类型(null也会返回Object)
  • instanceof可以判断引用类型(基于变量的原型对象去判断),但是不够准确(所有引用类型都有Object这个原型对象),修改原型链会导致误判
  • Object.prototype.toString()是最准确的判断类型的方法,他依托于Object.prototype.toString() 方法得到对象内部属性 [[Class]]
  • 变量在做运算时会发生强制类型转换,常见的转换有转为string,转为number,转为boolen
  • 对象转为string会先调用tostring函数,如果返回的不是原始值再调用valueof函数,如果返回的还不是原始值则抛出错误
  • 对象转为number的逻辑和转为string相同,只是调用函数的顺序变为先调用valueof再调用tostring
  • 转为string的情况一般发生在加法运算符并且有一个字符串参与运算
  • 转为number的情况一般发生在有加法但是无string参与,以及除加法运算符以外的其他运算符
  • 转为boolen的情况一般发生在逻辑判断,三元运算等

以上就是本文全部内容,相信看完之后一般的类型问题已经难不倒你了!

编辑 (opens new window)
上次更新: 2023/03/20, 17:19:19
页面可见性——visibilitychange
作用域、执行上下文和this

← 页面可见性——visibilitychange 作用域、执行上下文和this→

最近更新
01
小程序实现全局状态管理
07-09
02
前端检测更新,自动刷新网页
06-09
03
swiper渲染大量数据的优化方案
06-06
更多文章>
Theme by Vdoing | Copyright © 2023-2025 UzumakiItachi | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式