变量
平时开发中,使用最多的并不是固定的数据, 而是会变换的数据
如果我们希望记录某一个之后会变量的数据,在JavaScript中我们可以定义一个 变量
- 一个变量,就是一个用于存放任意值的容器
- 变量的独特之处在于它存放的数值是可以随时改变的
命名方式
// 定义单个变量
// 变量的声明 可以使用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严格区分大小写
建议规范
-
多个单词使用驼峰标识
- 主要以小驼峰为主
- 某些特定情况下,使用大驼峰,如定义类名,构造函数名等
-
赋值 = 两边都加上一个空格
-
变量应该做到见名知意
命名规范
- 小托峰
camcelCase
- 大驼峰 「 帕斯卡命名法 」
PascalCase
- 中划线命名法
kebab-case
- 下划线命名法
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
数字表示的范围:
- 最小数字:
Number.MIN_VALUE
, 小于这个的数字会被转化为0 - 最大数字:
Number.MAX_VALUE
整数表示范围
- 最小整数:
Number.MIN_SAFE_INTEGER
- 最大整数:
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:
- 字符串的前后引号类型必须一致
- 字符串中的不同引号类型之间不可以混用
- 字符串底层会被当做字符数组来解析,所以不存在字符类型
除了普通的可打印字符以外,一些有特殊功能的字符可以通过转义字符的形式放入字符串中
\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:
- 在定义变量的时候,尽可能对变量进行初始化,而不是使用默认值undefined
- 不推荐显示的将一个变量赋值为undefined
let num = 0;
let bool = false;
let str = ''
let und = undefined; // bad 不推荐
void 0
在ES3之前,undefined是可以被改值的变量
所以一般使用void 0
来表示undefined
void xxx
中
xxx
是任意合法的JavaScript表达式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
隐式转换
其他类型经常需要转换成字符串类型,比如和字符串拼接在一起或者使用字符串中的方法
- 一个字符串和其他类型进行+操作
- 如果+运算符左右两边有一个是字符串,那么另一边会自动转换成字符串类型进行拼接
- 某些函数的执行也会自动将参数转为字符串类型 例如 alert函数,prompt函数等
console.log(typeof (12 + '')) // => string
console.log(typeof 12 + '') // -> number + '' => number
显示转换
- String函数
- 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
隐式转换
-
在算数运算中,通常会将其他类型转换成数字类型来进行运算
- 但是如果是+运算,并且其中一边有字符串,那么还是按照字符串来连接的
console.log(typeof (1 + '2')) // => string
console.log(typeof ('6' / '2')) // => number
显示转换
-
Number函数
使用Number函数进行类型转换的时候,需要遵循如下的转换规则
值 | 转换后 |
---|---|
undefined | NaN |
null | 0 |
true 和 false | true -> 1 false -> 0 |
string | 1. 在进行类型转换前会去除字符串首尾空格后再进行类型转换 2. 如果去除空格后的字符串是空字符串 -> 0 3. 如果去除空格后的字符串中存在非数值型字符 -> NaN 4. 如果去除空格后的字符串中只存在数值型字符 -> 数值型字符对应的数字 |
object | 任何的对象类型在使用Number函数转换为number类型值的时候,结果都是NaN 包括空对象 |
- 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类型
隐式转换
- 逻辑运算中,例如位于if条件判断语句的条件判断表达式中
显示转换
- Boolean函数
- 使用两个连续的逻辑非运算符
无论是显示转换为Boolean类型还是隐式转换为Boolean类型,它们都遵循如下转换规则:
值 | 转换后 |
---|---|
直观上为“空”的值(如 0、+0、-0、0n、空字符串、null、undefined 和 NaN) 这类值被称之为假值(falsy) | false |
其它值 这类值被称之为真值(truthy) | true |
同样存在 nullish值,表示 undefined 和 null