《JavaScript高级程序设计》第三章语言基础 读书笔记

209 阅读11分钟

4、数据类型

5、Number

1、浮点型

2、值的范围

3、NaN

  • 原理:
    • 1、valueOf(),确定返回值是否可以转换为数值
    • 2、若不能,调用toString(),并测试返回值

4、数值转换

  • Number()
    • boolean true -> 1 false -> 0
    • number 直接返回
    • null -> 0
    • undefined -> NaN
    • string
      • 包含数值,转为十进制
      • 包含浮点,转为浮点
      • 包含十六进制 如 0xf 转为对应十进制
      • 空字符串,返回0
      • 其他 NaN
    • object
      • valueOf(),按上面规则转换返回值
      • 若结果为NaN,调用toString() ,按字符串转换
  • parseInt()
    • 需要得到整数的时候优先
    • 最前面空格忽略
    • 第一个不是数值加减,返回NaN,空字符也返回NaN
    • 第一个是数值加减,往后检测到第一个非数值,立刻忽略后面
    • 识别0x、0开头 转为 对应十进制
    • 第二个参数,作为进制数 parseInt('AF', 16) -> 175
  • parseFloat()
    • 第一个小数点有效,第二个无效
    • 始终忽略开始的0(10进制),只解析10进制

6、String

1、字符串字面量

  • length 获取长度 (双字节不准)

2、特点

  • immutable 不可变 都是重新创建

3、转换为字符串

  • toString()
    • 返回为当前值字符串等价物
    • 适用数值、布尔、对象、字符串。 null、undefined不支持
    • 数值的时候传参表示进制
  • String()
    • 如果有toString() 方法,则调用该方法返回结果
    • null-> "null"
    • undefined -> "undefined"

4、模版字面量

  • 可以直接换行
  • 保留空格

5、字符串插值

  • ${}
  • 通过toString() 强转字符串

6、模版字面量标签函数

7、原始字符串

  • String.raw

7、Symbol

1、基本用法

  • 初始化 Symbol()
  • typeof 返回symbol
  • 可以传入字符串参数作为描述,可以来调试,但于定义标识无关
  • 不能用new 创建,因为为了避免创建符号包装对象,确实需要可以用Object()

2、使用全局符号注册表

  • 共享和重用符号实例,可以用一个字符串作为键 Symbol.for()

    let foo = Symbol.for('foo')
    let other = Symbol.for('foo')
    console.log(foo == other) // true
    
  • 即使采用相同符号描述,也不等同

    let local = Symbol('foo')
    let other = Symbol.for('foo')
    console.log(local == other) // false
    
  • 必须用字符串

  • Symbol.keyFor() 查询全局注册表,返回对应字符串键

3、使用符号作为属性

  • 凡是可以使用字符串或者数值作为属性的地方都能用符号。

  • 获取key

    • Object.getOwnPropertySymbols() 获取symbol键
    • Object.getOwnPropertyNames() 获取常规键
    • Reflect.ownKeys() 返回所有键
  • 如果没有显式保存,那么必须遍历才能找到。

    let o = {
      [Symbol('foo')]: 'foo val',
      [Symbol('bar')]: 'bar val'
    }
    let barSymbol = Object.getOwnPropertySymbols(o).find((symbol)=>symbol.toString().match(/bar/))
    

4、常用内置符号

  • for-of 循环就是在相关对象上使用Symbol.iterator属性
  • 可以通过重写来改变for-of行为

5、Symbol.asyncIterator

  • 作为一个属性表示“一个方法,该方法返回对象默认的AsyncIerator。由for-await-of语句使用”
  • 异步迭代器 for-await-of

6、Symbol.hasInstance

  • 作为一个属性表示"一个方法,该方法决定一个构造器对象是否认可一个对象是他的实例,由instanceof操作符使用"

    function Foo(){}
    let f = new Foo()
    f instansof Foo // true
    Foo[Symbol.hasInstance](f)
    

7、Symbol.isConcatSpreadable

  • 一个属性表示“一个布尔值,如果是true,则意味着应该用Array.prototype.concat()打平其数组元素”

    let init = ['foo']
    let arr = ['bar']
    arr[Symbol.isConcatSpreadable] // undefined
    init.concat(arr) // ['foo', 'bar']
    arr[Symbol.isConcatSpreadable] = false
    init.concat(arr) // ['foo', Array[1]]
    
    let arrLikeObj = {length: 1, 0: 'baz'}
    arrLikeObj[Symbol.isConcatSpreadable] // undefined
    init.concat(arrLikeObj) // ['foo',{...}]
    arrLikeObj[Symbol.isConcatSpreadable] = true
    init.concat(arrLikeObj) // ['foo', 'baz']
    

8、Symbol.iterator

  • 一个属性表示"一个方法,该方法返回对象默认的迭代器,由for-of使用"

9、Symbol.match

  • 一个属性表示"一个正则表达式方法,该方法用正则表达式去匹配字符串,由String.prototype.match() 方法使用"
class StringMatcher{
  constructor(str) {
    this.str = str
	}
  [Symbol.match](target) {
    return target.includes(this.str)
  }
}

10、Symbol.replace

  • 一个属性表示"一个正则表达式方法,该方法替换一个字符串中匹配的子串,由String.prototype.replace() 方法使用"

11、Symbol.search

  • 一个属性表示"一个正则表达式方法,该方法返回字符串中匹配正则表达式的索引,由String.prototype.search() 方法使用"

12、Symbol.species

  • 一个属性表示"一个函数值,该函数作为创建派生对象的构造函数" ,getter 可以覆盖新创建实例的原型定义

13、Symbol.split

  • 一个属性表示“一个正则表达式方法,该方法在匹配正则表达式的索引位置拆分字符串,由String.prototype.split使用"

14、Symbol.toPrimitive

  • 一个属性表示“一个方法,该方法将对象转换为相应的原始值,由ToPrimitive抽象操作使用“

15、Symbol.toStringTag

  • 一个属性表示“一个字符串,该字符串用于创建对象默认字符串描述,由内置方法Object.prototype.toString()使用"

16、Symbol.unscopables

8、Object

  • 属性及方法
    • constructor 创建当前对象的函数
    • hasOwnProperty()判断当前对象实例(不是原型)上是否存在给定的属性。
    • isPrototypeOf 判断当前对象是否为另一个对象的原型
    • propertyIsEnumerable() 给定属性是否可用for-in枚举
    • toLocalString() 返回对象字符串表示,反应本地化执行环境
    • toString() 返回对象的字符串表示
    • valueOf() 返回对象对应的字符串、数值或布尔值表示。
  • Object是所有对象的积累,任何对象都有这些属性和方法。

5、操作符

  • 包括数学操作符、位操作符、关系操作符和相等操作符等
  • 可用于各种值,包括字符串、布尔值甚至对象。
  • 应用于对象时。通常会调用valueOf()和/或toString()方法

1、一元操作符

  • 只操作一个值

1、递增/递减

  • 前缀先作用,后缀后作用
  • 字符串,有效数值先转为数值再应用。string -> number
  • 字符串,不是有效数值,转为NaN。string -> number
  • 布尔值,false转为0,true转为1,再应用。boolean-> number
  • 浮点值, 加1或减1
  • 对象,则其调用valueOf() 方法取得可操作的值。

2、 一元加和减

  • 数值无影响(+)
  • 非数值 等同于使用Number()

2、位操作符

  • 负数 二补数(补码)的二进制编码存储
  • NaN和Infinity 在位操作中当作0处理
  • 非数值会用Number() 转换

1、按位非 ~

  • 返回数值的一补数

    let num1 = 25    // 00000000000000000000000000011001
    let num2 = ~num1 // 11111111111111111111111111100110
    num2 // -26
    
  • 效果相当于取反减1 或 加一取反

2、按位与&

每一位二进制对齐,同1则1,否则0

3、按位或 |

每一位二进制对齐,有1则1,否则0

4、按位异或 ^

每一位二进制对齐,相同则0,不同才1

5、左移 <<

二进制后面补0(左移),求次幂

2 << 5
10 -> 1000000 // 64

6、有符号右移 >>

  • 保留正负,相当于<< 逆运算

7、无符号右移 >>>

  • 正数 与 有符号右移相同

  • 负数,当作正数处理,然后右移

    let old = -64
    let new = old >>> 5
    // -64 11111111111111111111111111000000 
    //     00000111111111111111111111111110
    // new 134217726
    

3、布尔操作符

1、逻辑非 !

  • 始终返回布尔值
  • 先将操作数转换为布尔值,再取反
  • 规则
    • 对象 false
    • 空字符串 true
    • 非空字符串 false
    • 数值0 true
    • 数值非0 (Infinity)false
    • null true
    • undefined true
  • !! 相当于Boolean()

2、逻辑与 &&

  • T&&T -> T 其他 F
  • 可用于任何类型操作数,不限于布尔值,并不一定返回布尔值
    • 第一个操作数是对象,返回第二个操作数
    • 第二个操作数是对象,则只有第一个操作数求值为true才返回该对象
    • 两个操作数都是对象,返回第二个操作数
    • 有一个操作数是null,返回null
    • 有一个操作数是NaN,返回NaN
    • 有一个操作数是undefined,返回undefined
  • 短路操作符,如果第一个操作数决定了结果,永远不会对第二个操作数求值
    • 第一个操作数是false,不会求第二个操作数

3、逻辑或 ||

  • F||F -> F 其他 T
  • 可用于任何类型操作数,不限于布尔值,并不一定返回布尔值
    • 第一个操作数是对象,返回第一个操作数
    • 第一个操作数求值为false,返回第二个操作数
    • 两个操作数都是对象,返回第一个操作数
    • 两个操作数都是null,返回null
    • 两个操作数都是NaN,返回NaN
    • 两个操作数都是undefined,返回undefined
  • 短路操作符,如果第一个操作数决定了结果,永远不会对第二个操作数求值
    • 第一个操作数是true,不会求第二个操作数

4、乘性操作符

  • 空字符串作为0, 布尔true 当作1

1、乘法操作符 *

  • 如果都是数值,执行常规运算。
  • 任一NaN, 返回NaN
  • Infinity * 0 -> NaN
  • Infinity * 非0有限数值,根据符号返回
  • Infinity*Infinity -> Infinity
  • 不是数值,先Number()转换后再计算。

2、除法操作符 /

  • 如果都是数值,执行常规运算。
  • 任一NaN, 返回NaN
  • Infinity / Infinity 返回NaN
  • 0 / 0 返回NaN
  • 非0有限数除以0,根据第一个操作数符号返回Infinity或-Infinity
  • Infinity除以任何数值,根据第二个操作数符号返回Infinity或-Infinity
  • 不是数值,先Number()转换后再计算。

3、取模操作符 %

  • 如果都是数值,执行常规运算。
  • 如果被除数是无限值,除数是有限值,返回NaN
  • 如果被除数是有限值,除数是0,返回NaN
  • 如果Infinity % Infinity 返回NaN
  • 如果被除数是有限值,除数是无限值,返回被除数
  • 如果被除数是0,除数不是0,返回0
  • 不是数值,先Number()转换后再计算。

5、指数操作符 **

  • Math.pow() 等同 **

  • 指数赋值操作符 **=

    let s = 3
    s **= 2
    s // 9
    

6、加性操作符

1、加法 +

  • 都是数值
    • 任一NaN, 返回NaN
    • Infinity 加 Infinity -> Infinity
    • -Infinity加 -Infinity -> -Infinity
    • Infinity 加 -Infinity -> NaN
    • +0 加 +0 -> +0
    • -0 加 +0 -> +0
    • -0 加 -0 -> -0
  • 有字符串
    • 都是字符串,第二个要拼接到第一个后面
    • 只有一个字符串,将另一个转为字符串,再拼接
    • 任一操作数是对象数值布尔值,调用toString()方法获取字符串,然后再拼接
    • 对于undefined null,调用String()函数,返回字符串undefined null

2、减法 -

  • 都是数值,执行数学减法
  • 任一NaN, 返回NaN
  • Infinity 减 Infinity -> NaN
  • -Infinity 减 -Infinity -> NaN
  • Infinity 减- Infinity ->Infinity
  • -Infinity 减 Infinity -> -Infinity
  • +0 减 +0 -> +0
  • +0 减 -0 -> -0
  • -0 减 -0 -> +0
  • 任一操作数是字符串,布尔值,null,undefined。后台先调用Number()
  • 任一操作数是对象,调用valueOf(),如果没有就调用toString()

7、关系操作符

  • 都是数值,数值比较
  • 都是字符串,逐个比较对应字符编码
  • 任一数值,另一个转为数值,再比较
    • "a" < 3 , "a" 转为数值NaN,返回false
  • 任一对象,调用valueOf(),取得结果再比较,没有valueOf(),用toString()
  • 任一布尔,转为数值比较
  • NaN 比较 都是false

8、相等操作符

1、等于和不等于

会进行类型转换

  • 任一布尔,转为数值再比较。
  • 一个字符,一个数值,字符转为数值再比较
  • 一个对象,另一个不是,valueOf()取得原始值再比较
  • null == undefined
  • null和undefined不能转换为其他类型的值再比较
  • 任一NaN,相等返回false,不相等返回true
  • 都是对象,比较是不是同一对象。
null == undefined 		// true
"NaN" == NaN					// false
5 == NaN							// false
NaN == NaN						// false
NaN != NaN 						// true
false == 0						// true
true == 1							// true
true == 2							// false
undefined == 0 				// false
null == 0							// false
"5" == 5							// true

2、全等和不全等

不转换类型

推荐使用

9、条件操作符

10、赋值操作符

  • 简单赋值
  • 复合赋值

11、逗号操作符

  • 执行多个操作
  • 返回最后一个值

6、语句

1、if

2、do-while 后测试循环

3、while 先测试循环

4、for

5、for-in

  • 枚举对象中非符号键属性

6、for-of

  • 迭代语句,可遍历迭代对象元素
  • for-await-of 支持生成期约的异步可迭代对象

7、标签语句

8、break和continue

  • break 立即退出循环,强制执行循环后的下一条语句
  • continue立即退出(本次)循环,但会再次从循环顶部开始执行
  • 都可以和标签语句一起执行,退出到执行的循环,多用于循环嵌套

9、with

  • 将代码作用域设置为特定对象
  • 不推荐

10、switch

  • switch(true) 逻辑判断更清晰,每个表达式求值直到返回true
  • 全等比较

7、函数

  • 要么返回值要不不返回值

  • 严格模式

    • 不能用eval、arguments作为名称

    • 参数不能叫eval、arguments

    • 两个命名参数不能拥有同一个名称