Loading

JS 红宝书笔记-变量 & 数据类型

变量

JavaScript 中有 3 个关键字可以声明变量:varconstlet。其中,constlet 只能在 ECMAScript6 及更晚的版本中使用

var 声明

  • var 声明的变量,存在变量提升

    function foo() {
      console.log(age)
      var age = 26
    }
    foo() // undefined
    
  • 使用 var 可以反复多次声明同一个变量

    function foo() {
      var age = 16
      var age = 26
      var age = 36
    }
    foo() // 36
    

    这是因为存在变量提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明

let 声明

  • let 声明的范围是块作用域

    if (true) {
      let age = 26
      console.log(age) // 26
    }
    console.log(age) // ReferenceError
    

    age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部。块作用域是函数作用域的子集。

  • let 不允许同一个块作用域中出现冗余声明,会导致报错

    let age
    let age // SyntaxError; 标识符 age 已经声明过了
    
  • let 声明的变量不会在作用域中被提升

    console.log(age) // ReferenceError: age 没有定义
    let age = 26
    
  • let 在全局作用域中声明的变量不会成为 window 对象的属性

  • for 循环中的 let 声明

    for (var i = 0; i < 5; i++) {
      setTimeout(() => console.log(i), 0) // 5 5 5 5 5
    }
    

    setTimeout 是一个异步操作,由于 var 是全局变量,所以执行到这里拿到的是循环结束后的 i 的值,是同一个变量,因而输出的都是同一个最终值

    for (let i = 0; i < 5; i++) {
      setTimeout(() => console.log(i), 0) // 0 1 2 3 4
    }
    

    使用 let 声明迭代变量时,JS 引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例

const 声明

  • const 的行为与 let 基本相同,唯一一个重要的区别就是它声明变量时必须同时初始化变量
  • 尝试修改 const 声明的变量会导致运行时错误,如果 const 变量引用的是一个对象,修改这个对象内部的属性并不违反 const 的限制
  • 不允许重复声明
  • 作用域是块

变量声明的最佳实践

  • 不使用 var
    限制自己只使用 letconst 有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值
  • const 优先,let 次之
    使用 const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。只在提前知道未来会有修改时,再使用 let

数据类型

ECMAScript 有 6 种简单数据类型

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

还有一种复杂的数据类型:Object

typeof 操作符

typeof 可以返回的字符串如下:

  • number
  • string
  • boolean
  • undefined
  • object
  • function
  • symbol

可以看出,typeof 能判断简单数据类型(null 除外),可以判断是否为 Object,但是无法具体细分子类型

Undefined 类型

  • 当使用 varlet 声明了变量但没有初始化时,就相当于给变量赋值了 undefined
  • 一般来说,永远不用显式地给某个变量设置 undefined
  • 对于未声明的变量、声明但未初始化的变量,typeof 返回的都是 "undefined"

Null 类型

  • null 值表示一个空对象指针
  • 在定义将要保存对象值的变量时,建议使用 null 来初始化,可以保持 null 是空对象指针的语义

Boolean 类型

不同类型与布尔值之间的转换规则:

image-20211104222002298

需要注意的是,空对象、空数组都是 truely,也就是可以转换为 true

Boolean({}) // true
Boolean([]) // true

if 等流程控制语句会自动执行其他类型到布尔值的转换

let arr = []
if (arr) {
  console.log('yes')
}

arr 为空数组,是 truely 变量,结果输出字符串 "yes"

Number 类型

Number 类型可以表示整数和浮点数。由于存储浮点数使用的内存空间是存储整数值的两倍,所以 ECMAScript 总是想方设法把值转换为整数

let floatNum1 = 1.;   // 小数点后面没有数字,当成整数 1 处理 
let floatNum2 = 10.0; // 小数点后面是零,当成整数 10 处理

浮点数存在精度问题,不要直接进行比较

数值转换

  • Number() 可用于任何数据类型
  • parseInt() 用于将字符串转换为数值
    更专注于字符串是否包含数值模式。字符串最前面的空格会被忽略,从第一个非空格字符开始转换
  • parseFloat() 用于将字符串转换为数值

String 类型

字符串转换

  • toString() 方法
    可见于数值、布尔值、对象和字符串;null 和 undefined 没有 toString() 方法
  • String() 转型函数
    • 如果值有 toString() 方法,则调用该方法并返回结果
    • 如果值是 null,返回 "null"
    • 如果值是 undefined,返回"undefined"

Symbol 类型

  • 用来创建唯一记号,进而用作非字符串形式的对象属性
  • 只要创建 Symbol() 实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性
posted @ 2021-11-04 22:37  neoscar  阅读(56)  评论(0编辑  收藏  举报