JS基础 --- 变量和数据类型

210 阅读9分钟

变量

平时开发中,使用最多的并不是固定的数据, 而是会变换的数据

如果我们希望记录某一个之后会变量的数据,在JavaScript中我们可以定义一个 变量

  • 一个变量,就是一个用于存放任意值的容器
  • 变量的独特之处在于它存放的数值是可以随时改变的

image33e5dc392c709fd6.png

命名方式

 // 定义单个变量
 ​
 // 变量的声明 可以使用var/let/const关键字来声明一个变量
 let userName
 // 使用 = 给变量进行赋值
 userName = 'Klaus'
 ​
 // 变量的声明和赋值可以放在一起进行使用
 let userName = 'Klaus'
 // 同时定义多个变量 --- 不推荐 可读性相对较差
 // 如果需要定义多个变量, 且这些变量之间存在一定的联系的时候
 // 推荐将他们定义成一个对象,形成一个整体来进行使用和维护
 ​
 // 不推荐使用name作为变量名
 // 因为name在js中存在特殊的含义
 // 1. 在浏览器中全局的name为空字符串
 // 2. 在函数中name的值为当前的函数名
 // 3. 在node环境,不存在全局name
 let userName, age
 userName = 'Klaus'
 age = 18
 ​
 // 同时定义多个变量并赋值
 let name = 'Klaus', age = 18
 // 同时给多个变量赋相同的值
 let name = userName = 'Klaus'
 let userName = 'Klaus'
 let age = 23
 ​
 // 变量的值是可以随时发生改变的
 age = 25
 ​
 // 我们可以将一个变量的值赋值给另一个变量
 let nickName = userName
 ​
 // 当我们打印变量的时候,实际上是在打印变量中所存储的值
 console.log(userName, age)

命名规范

强制规范

  • 第一个字符必须是一个字母、下划线( _ )或一个美元符号( $ )

  • 其他字符可以是字母、下划线、美元符号或数字

  • 不能使用关键字和保留字命名

    • 关键字 --- JS中具有特定含义或起到关键作用的单词,例如var,function,let,const等
    • 保留字 --- 目前不是JS的关键字,但是在未来的某一天可能成为JS的关键字的单词,例如enum. interface等
  • JS严格区分大小写

建议规范

  • 多个单词使用驼峰标识

    • 主要以小驼峰为主
    • 某些特定情况下,使用大驼峰,如定义类名,构造函数名等
  • 赋值 = 两边都加上一个空格

  • 变量应该做到见名知意

命名规范

  1. 小托峰 camcelCase
  2. 大驼峰 「 帕斯卡命名法 」 PascalCase
  3. 中划线命名法 kebab-case
  4. 下划线命名法 snake_case

注意事项

  • 如果一个变量未声明(declaration)就直接使用,那么会报错

  • 如果一个变量有声明,但是没有赋值,那么默认值是undefined,也就是说变量的默认值是undefined

  • 使用对象上不存在的值,返回结果也是undefined

  • 使用var声明的变量,本质是一个全局变量,会被自动挂载到window上 --- 不推荐

    • node环境中,不存在这个问题
  • 不使用var/let/const也可以声明一个变量,这种变量本质也是一个全局变量,且这种变量被称之为隐式全局变量 --- 不推荐

数据类型

JavaScript 中的值都具有特定的类型,我们可以将值赋值给一个变量,那么这个变量就具备了特定的类型

且在JavaScript中,变量值的类型是不固定的,一个变量可以在前一刻是个字符串,下一刻就存储一个数字

这种变量值类型不确定的语言就被称为“动态类型”(dynamically typed)语言

 // JS中变量不需要指定对应的变量类型
 // JS在解析到具体行的时候,会自动推导出变量所对应的变量类型
 var userName = 'klaus'

在JavaScript中,一共有8中数据类型,分别是7种基本数据类型语言和1种复杂数据类型

7种基本数据类型 --- 值类型,原始数据类型

  • Number
  • String
  • Boolean
  • Null
  • Undefined
  • BigInt
  • Symbol

1种复杂数据类型 --- 引用类型 --- 本质是将任意个,任意类型的基本数据类型组合在一起进行使用

  • Object

Number

Number 类型用于任何类型的数字: 整数或浮点数

数字number可以有很多操作,比如,乘法 *、除法 /、加法 +、减法 - 等等

除了常规的数字,还包括两个的“特殊数值(“special numeric values”)”,这两个特殊的数值也属于Number类型

  • Infinity: 代表数学概念中的 无穷大 ∞, 也可以使用-Infinity表示负无穷大
  • 在js中 1 / 0得到的结果就是无穷大
  • Infinity和-Infinity 这2个关键字的首字母都是大写的
 let n = Infinity
 ​
 // 1. isFinite可以判断一个值是否是有穷尽的
 // 2. Number上的一些类方法在window上也存在同功能同名函数
 console.log(Number.isFinite(n)) // false
 console.log(isFinite(n)) // false
  • NaN --> not a number

    • NaN 代表一个计算错误, 一般是一个错误的操作所得到的结果, 比如 字符串和一个数字相乘
    • 可以使用isNaN函数来判断一个数值是不是NaN,如果是,该函数会返回true,否则返回false
 const foo = 'asv' * 2 // foo -> NaN
 const num = 23 // num -> number
 ​
 console.log(Number.isNaN(foo)) // => true
 console.log(isNaN(num)) // => false

任何的值和NaN进行比较的时候,结果都为false,包括是NaN和其自身进行比较

 console.log(NaN === NaN) // false
 console.log(Object.is(NaN, NaN)) // true

Object.js底层使用全等判断,只不过对NaN进行了特殊处理

数字类型也有其他的进制表示方法,在JS中,可以表示十进制、十六进制、二进制、八进制

 // 十进制
 const num = 100
 ​
 // 二进制 -> 0b中的b不区分大小写
 const bin = 0b100
 ​
 // 八进制 -> 0o中的o不区分大小写
 const oct = 0o100
 ​
 // 十六进制 -> 0x中x不区分大小写
 const hex = 0x100
 ​
 // 无论变量使用什么进制进行编写,输出的最终结果默认都是十进制
 console.log(num, bin, oct, hex) // => 100 4 64 256

数字表示的范围:

  1. 最小数字: Number.MIN_VALUE, 小于这个的数字会被转化为0
  2. 最大数字: Number.MAX_VALUE

整数表示范围

  1. 最小整数: Number.MIN_SAFE_INTEGER
  2. 最大整数:Number.MAX_SAFE_INTEGER

这些值本质都是常量,所以命名使用全大写形式

 const num = Infinity
 ​
 console.log(Number.isSafeInteger(num)) // false
 ​
 // 一些常用的Number类方法会存在于window
 // 但并不是全部都存在于window对象上
 // 例如window对象上不存在isSafeInteger方法
 console.log(isSafeInteger(num)) // error

String

在开发中我们经常会有一些文本需要表示,这个时候我们会使用字符串String

在JS中,字符串可以使用单引号,双引号和反引号进行包裹

单引号和双引号是没有任何的区别的

而反引号中,可以使用${}来嵌入任何合法的JavaScript表达式,并且可以进行换行书写

 const firstWord = "Hello"
 const lastWord = 'World'
 const word = `${firstWord} ${lastWord} ${1 + 2}` // -> Hello Wolrd 3

tips:

  1. 字符串的前后引号类型必须一致
  2. 字符串中的不同引号类型之间不可以混用
  3. 字符串底层会被当做字符数组来解析,所以不存在字符类型

除了普通的可打印字符以外,一些有特殊功能的字符可以通过转义字符的形式放入字符串中

image.png

  • \r:回车,历史上用于经典 Mac OS。
  • \n:换行,Unix/Linux/macOS 的标准。
  • \r\n:回车 + 换行,Windows 系统的标准。
 const firstName = 'Klaus'
 const lastName = 'Wang'// 字符串拼接 --- ES5的传统拼接
 let fullName = firstName + ' ' + lastName
 ​
 // 字符串拼接 --- ES6的模板字符串
 fullName = `${firstName} ${lastName}`

 const str = 'Hello World'// length属性可以获取字符串的长度// 一个基本类型之所以可以调用属性
 // 是因为在调用属性的时候,会转换为对应的包装类类型后,才可以去调用对象的属性
 console.log(str.length) // => 11

Boolean

Boolean(布尔)类型用于表示真假

Boolean 类型仅包含两个值: true (真) 和 false (假)

 let bool
 bool = true // 可以直接给变量赋布尔类型的值
 bool = 1 == 1 // 某些表达式的返回值也是布尔类型

Undefined

undefined 类型只有一个值,那就是 undefined, 对应的类型是Undefined(首字母大写)

如果我们声明一个变量,但是没有对其进行初始化时,它默认就是undefined

当我们去取对象上的某个属性的时候,如果这个属性不存在,那么默认取到的值也是undefined

 const und;
 const unde = undefined
 console.log(und === unde) // => true

tips:

  1. 在定义变量的时候,尽可能对变量进行初始化,而不是使用默认值undefined
  2. 不推荐显示的将一个变量赋值为undefined
 let num = 0;
 let bool = false;
 let str = ''
 ​
 let und = undefined; // bad 不推荐

void 0

在ES3之前,undefined是可以被改值的变量

所以一般使用void 0来表示undefined

void xxx

  1. xxx 是任意合法的JavaScript表达式
  2. void表达式返回结果永远是undefined

现代浏览器,已经不存在这个问题

Object

Object 类型是一个特殊的类型,我们通常把它称为引用类型或者复杂类型

其他的数据类型我们通常称之为 “原始类型”,因为它们的保存的仅仅是变量的数据值

而Object类型的变量保存的是数据的值在内存中的引用地址

在编程语言中,指针和引用的含义是一致的,他们都是指在内存中的某一块地址

Object往往可以表示一组数据,是将多个相关联的变量组合在一起形成的一个集合

 // 在JavaScript中我们可以使用 花括号 来定义对象
 const user = {
   // 属性名 : 属性值
   name: 'Klaus',
   // 多个属性之间使用 逗号 进行分割
   // 最后一个属性后的逗号省略
   age: 23
 }
 ​
 // 我们可以通过点语法获取对象中的属性
 console.log(user.name)
 ​
 // 我们也可以通过中括号语法来获取对象的属性
 // 如果使用中括号语法去获取对象的属性的时候,中括号中存放的是存储属性名的变量
 const key = 'name'
 console.log(user[key])

Null

Null 类型同样只有一个值,即 null

null值用于表示暂时未知的值

 // null类型通常用来表示一个对象为空
 // 所以通常我们在给一个对象进行初始化时,会赋值为null
 // 因此 null 可以看成是一种特殊的对象
 // null一般之和object类型的值一起结合使用
 let obj = null
 // 有的时候,我们可能会使用空对象来对对象进行初始化赋值
 // 但是这是不推荐的
 // 1. null指向的内存地址是0x0, 也就是一块特殊的内存地址,其并不会在堆内存中创建任何的内容
 //    但是{}本质上只是一个没有任何属性的对象,所以其依旧会在内存中创建对应的地址空间来进行存储
 ​
 // 2. if(条件) { ... } 
 //    if之类的条件判断语句会自动将条件转换成boolean类型值
 //    null转boolean结果为false 可以直接使用
 //    {} 转boolean结果为true 不可以直接使用,容易出现bug
 let obj = {}

typeof 操作符

因为 ECMAScript 的类型系统是松散的,所以需要使用typeof操作符来确定任意变量的数据类型

使用 typeof 操作符会返回如下结果中的一种:

结果说明
number值的类型为数值
string值的类型为字符串
boolean值的类型为布尔类型
undefined值的类型为undefined
object值的类型为object或null 因为null一般用来表示一个对象为空 在JS中,typeof 对象(除函数外)结果都是object,包括set,map,数组等
function值的类型为函数
symbol值的类型为symbol
bigInt值的类型为bigInt

typeof 变量 vs typeof(变量)

typeof是一个操作符,并非是一个函数

 // 函数的调用
 // 函数名(参数列表)
 sum(20, 30)
 ​
 // 操作符的调用
 // 操作符 参数列表
 typeof num

如果通过typeof(变量)来进行使用,其小括号并不是表示是函数调用,而是表示后续的内容是一个整体

 let num = 23
 ​
 console.log(typeof(num)) // => number
 console.log(typeof   (num)) // => number
 ​
 // typeof操作符如果后边的内容使用括号进行包裹
 // 那么就说明后边的内容是一个整体
 console.log(typeof(num + 3)) // => number
 console.log(typeof num + 3) // => number3

数据类型转换

在开发中,我们会经常需要对数据类型进行转换

大多数情况下,运算符和函数会自动将赋予它们的值转换为正确的类型

这种由JS Engine自动帮助我们完成的类型转换被称之为隐式转换

 let bool = true
 console.log(10 + bool) // => 11

但是,有的时候我们可能需要手动对数据类型进行转换

这种由我们自己主动进行的数据类型转换就被称之为显示转换

其它类型转String

隐式转换

其他类型经常需要转换成字符串类型,比如和字符串拼接在一起或者使用字符串中的方法

  1. 一个字符串和其他类型进行+操作
  • 如果+运算符左右两边有一个是字符串,那么另一边会自动转换成字符串类型进行拼接
  1. 某些函数的执行也会自动将参数转为字符串类型 例如 alert函数,prompt函数等
 console.log(typeof (12 + '')) // => string
 console.log(typeof 12 + '') // -> number +  '' => number

显示转换

  1. String函数
  2. toString方法
 console.log(typeof String(234)) // => string
 ​
 // 1. null和undefined是没有办法调用方法的,所以他们不可以使用toString方法转换为字符串类型
 // 2. 在JS中所有的Number按照浮点数进行解析
 //    所以123.toString()会被解析为123.0toString() --> 此时JS Engine在进行解析的时候,就会报错
 //    所以需要在123外包裹一个括号,以表示他们是一个整体 --> (123).toString() 此时浏览器就可以正常解析
 //    同样的 123..toString() 123.0.toString() (new Number(123)).toString() 
 //    也可以完成相应的功能,但是他们的阅读性没有(123).toString()好,所以并不推荐
 console.log(typeof (123).toString()) // => string
 ​
 // 3. {}.toString 是会报错的,因为JS引擎会将{}解析为代码块,代码块是无法调用方法的
 //    同理function() {}.toString()也是会报错的,其{}也会被解析为代码块
 //    如果要可以直接调用toString方法,需要使用小括号进行包裹,以表示他们是一个整体
 console.log(({}).toString())
 console.log((function() {}).toString())
 ​
 // 数组可以直接调用toString方法,不需要使用小括号进行包裹
 console.log([].toString())

其它类型转Number

隐式转换

  1. 在算数运算中,通常会将其他类型转换成数字类型来进行运算

    • 但是如果是+运算,并且其中一边有字符串,那么还是按照字符串来连接的
 console.log(typeof (1 + '2')) // => string
 console.log(typeof ('6' / '2')) // => number

显示转换

  1. Number函数

    使用Number函数进行类型转换的时候,需要遵循如下的转换规则

转换后
undefinedNaN
null0
true 和 falsetrue -> 1 false -> 0
string1. 在进行类型转换前会去除字符串首尾空格后再进行类型转换 2. 如果去除空格后的字符串是空字符串 -> 0 3. 如果去除空格后的字符串中存在非数值型字符 -> NaN 4. 如果去除空格后的字符串中只存在数值型字符 -> 数值型字符对应的数字
object任何的对象类型在使用Number函数转换为number类型值的时候,结果都是NaN 包括空对象
  1. parseInt / parseFloat函数
 console.log(parseInt('a12')) // => NaN
 console.log(parseInt('12')) // => 12
 console.log(parseInt('12.5')) // => 12
 console.log(parseInt('12a')) // => 12
 ​
 console.log(parseFloat('12')) // => 12
 console.log(parseFloat('12.5')) // => 12.5
 console.log(parseFloat('a12.5')) // => NaN
 console.log(parseFloat('12.5a')) // => 12.5
 ​
 // parseInt和parseFloat在进行类型转换的时候
 // 也是会去除字符串的首尾空格后再进行对应的类型转换
 console.log(parseInt('     12    ')) // => 12
 console.log(parseFloat('    12    ')) // => 12

其它类型转换为Boolean类型

隐式转换

  1. 逻辑运算中,例如位于if条件判断语句的条件判断表达式中

显示转换

  1. Boolean函数
  2. 使用两个连续的逻辑非运算符

无论是显示转换为Boolean类型还是隐式转换为Boolean类型,它们都遵循如下转换规则:

转换后
直观上为“空”的值(如 0、+0、-0、0n、空字符串、null、undefined 和 NaN) 这类值被称之为假值(falsy)false
其它值 这类值被称之为真值(truthy)true

同样存在 nullish值,表示 undefined 和 null