7 种原始类型
- 数字(number):包含整数和浮点数,以及特殊数值(
Infinity
、-Infinity
、NaN
) - 字符串(string):使用单引号
''
、双引号""
、反引号``
括起来的任意文本 - 布尔值(boolean):
true
和false
- 未定义(undefined):含义是未被赋值,如果一个变量已被声明,但未被赋值,那么它的值就是
undefined
- 空(null):表示没有,一般用来表示尚未存在的对象
- 符号(symbol):表示独一无二的值,用于创建对象的唯一标识符
- 任意整数(bigint):可表示任意长度的整数,用来存放超过安全整数(±253-1)范围内的整数
1 种引用类型(object)
- 对象(Object)
- 数组(Array)
- 集合(Map,Set)
- 函数(Function)
- 日期(Date)
- 正则(RegExp)
- 数学(Math)
- 错误(Error)
- JSON
- 基本包装类型:
- Number
- String
- Boolean
null 和 undefined 没有对象包装器,也就没有原型以及属性和方法
判断变量类型
typeof
用于判断除了 null 外的基本类型,支持两种语法形式:typeof x
和 typeof(x)
,是一个操作数而不是函数。这里的括号不是 typeof 的一部分,它是数学运算分组的括号。
instanceof
检测“对象”的具体类型(不能判断基本类型,会全部返回 false)
Object.prototype.toString.call()
可以检测所有类型
可以使用特殊的对象属性 Symbol.toStringTag 自定义对象的 toString 方法的行为:
变量声明
var
- 只有函数作用域和全局作用域,没有块级作用域
- 允许重新声明,后面的会被忽略
- 使用 var 声明的全局函数和变量会成为 全局对象 的属性
- var 声明的变量,可以在其声明语句前被使用(变量提升)
let / constES6
ES6 新增了 2 个关键字,可以将变量绑定到所在的任意作用域中,只作用于被定义时的作用域下
- let:定义一个变量,允许被改变
- const:定义一个常量且必须立即初始化赋值,不允许被改变
const 定义的变量指向的对象不能修改,但是可以改变对象内部的属性。地址不能改,但指向的地址中的内容是可以改的,也就是不能给 const 定义的变量再赋值,但是可以改变这个变量指向的对象的值。
暂时性死区(temporal dead zone,简称 TDZ):
在块级作用域内声明的 let/const 变量,在变量声明完成之前不能访问,否则会报错(变量一定要在声明之后使用)
即使在外部有一个同名变量,内部的暂时性死区范围内也不能访问到外部变量:
变量声明的所有方法
var
,function
,let
,const
,import
,class
变量提升
变量和函数的声明都会在任何其他代码执行前被处理,JavaScript 仅提升声明,而不提升初始化
- 只有声明操作会在编译阶段提升
- 赋值操作会留在原地等待执行阶段
注意
- let/const 不会提升,class 声明也不会提升
- var 可以重复声明,let/const 不能重复声明
- 后面的函数声明会覆盖前面的函数声明
- 函数声明比变量声明优先提升,且不会被变量声明覆盖,但是会被变量赋值覆盖
- 没有声明的变量直接赋值会隐式创建这个名字的全局变量(非严格模式)
- 块语句中的函数声明不会提升到外面,只会提升到块语句中的顶部。浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于 var 声明的变量。但是这个行为可能在未来的 JS 版本中改变,因此要尽可能避免在块语句内部声明函数
- var,function 声明的全局变量属于 window;let/const 声明的不属于
- 在 for (let i = …) 语句中声明的 i 具有块级作用域,即变量仅在其所在的块 {} 内有效,每个迭代中的变量都是独立的
对象包装器
原始值本身没有方法和属性,为了提供在原始值上调用方法和属性的能力,有了对象包装器
除了 null 和 undefined,其他基本类型访问属性时会临时对其进行对象包装。
JavaScript 引擎在需要时会自动执行装箱(boxing)和拆箱(unboxing)操作。装箱是将原始值转换为相应的对象,而拆箱是将对象转换回原始值