《你不知道的JavaScript下卷》

208 阅读4分钟

第一章

深入编程

语句

  • 变量 它们就好比可以存放东西的小盒子
  • 字面量 如2 本身就是一个值,称为字面量,因为它独立存在而没有保存在变量中
  • 对象属性访问 obj.a obj["a"]的形式
  • !=(粗略不等) !==(严格不等)
  • 字符串字面量值由双引号单引号围住,数字和布尔型字面量可以直接表示(如:42,true)
  • 每个函数都有自己的作用域

第二章

深入JavaScript

对象

  • 在JavaScript程序中,你还需要经常和其他两个值类型打交道:数组和函数。但你更应该将它们看作是对象类型的特殊子类型,而不是内置类型
  • 数组: 数组是一个持有(任意类型)值的对象,这值不是通过命名属性/键值索引,而是通过数字索引位置。
  • 函数: 因为typeof返回"function" ,这意味着function是一个主类型

值的比较

  • 1 类型转换
    • 显示的转换与隐式的类型转换。显示的类型转换就是你可以在代码中看到的类型由一种转换到另一种,而隐式的类型转换多是其他运算可能存在的隐式副作用而引发的类型转换。
    • 比较也会产生隐式转换
  • 2 "假"值
    • ""(空字符串)
    • 0 -0 NaN(无效数字)
    • null undefined
    • flase
  • 相等
    • == 检查的是允许类型转换下的值的相等性,而===检查不允许类型转换下的值的相等性
    • 数组默认情况下回转换为字符串
    var a = [1,2,3]
    var b = [1,2,3]
    var c = 1,2,3
    
    a == c // true
    b == c // true
    a == b // false
  • "无效数字值"NaN 规范设定NaN及不小于也不大于任何其他值

严格模式

根据严格模式编译指示防止的位置,你可以选择使用单独的函数或者整个文件来遵循严格模式:

  • 使用严格模式的一个关键区别(改进!)是,不允许省略var 的隐式自动全局变量声明:
function foo(){
  "use strict";
  a = 1//省略var,出现ReferenceError 错误
}
foo()

作为值的函数

不仅你可以向函数传入值(参数),函数本身也可以作为值赋给变量或者向其他函数传入,又或者从其他函数传出

因此,应该将函数值视为一个表达式与其他的值或者表达式类似

var foo = function(){}
var x = function bar(){}
  • 第一个赋给变量foo的函数表达式被称为匿名的
  • 第二个函数表达式是命名的,即使它的引用赋值给了变量x。虽然匿名函数表达式的使用仍然极为广泛,但也要记住命名函数表达式

立即调用函数表达式

function foo(){..}
// foo函数引用表达式,然后()执行它
foo();
// IIFE 函数表达式,然后()执行它
(function IIFE(){..})()
  • 包裹的括号就是JavaScript语法能够防止其成为普通函数声明的部分
  • IIFE也有返回值
var x = (function IIFE(){
  return 42
})()

闭包

你可以将闭包看做“记忆”并在函数运行完毕后继续访问这函数作用域(变量)的一种方法

  • 模块闭包最常见的应用就是模块模式。

第一部分总结

前面讲的这些都是之前你不知道的上,中的内容,这里只是简单的回顾而已。所以应该是第二部分的内容才是本书的重点吧

ES6 及更新版本

  • 过早的访问let声明的应用导致了这个ReferenceError叫作临时死亡区
var funcs = []
for (let i = 0; i < 5; i++) {
  funcs.push(function () {
    console.log(i)
  })
};
console.log(funcs[3]()) //3

var funcs = []
for (var i = 0; i < 5; i++) {
  funcs.push(function () {
    console.log(i)
  })
};
console.log(funcs[3]()) //5

每次循环都重新声明了一个新的i,这意味着loop迭代内部创建的闭包封闭的是每次迭代中的变量。而把var i ,这个外层作用域中只有一个i,这个i被封闭进去,而不是每个迭代的函数会封闭一个新的i。

  • const 只是赋值本身不可变。如果这个值是复杂值,比如对象或者数组,其内容仍然是可以修改的。
{
 const a = [1,2,3]
 a.push(4)
 console.log(a) // [1,2,3,4]
 a = 42 //TypeError
}

spread/rest(展开或收集)

function foo(x,y,...z){
  console.log(x,y,z)
}
foo(1,2,3,4,5) // 1 2 [3,4,5]
var a = [2,3,4]
var [b,..c] = a 
console.log(b,c)

2.3 默认参数值

x = x || 2; 这种做法,当我们传入的是0,那么会输出的是2,但是我们传入的就是0

function foo( x = 11,y = 42){
  console.log(x + y)
}
foo(5,undefind) //47
foo(5,null) // 47

解构

把这个功能看作是一个结构化赋值方法,会比较容易理解一些

对象属性的结构要看清楚哦,不要理解成键值对

默认值赋值

var [a = 3,b = 6,c = 9, d = 12 ] = foo()
var {x=5,y=10,z=15,w=20} = bar()

console.log(a,b,c,d) //1 2 3 12

console.log(x,y,z,d) // 4 5 6 20

箭头函数

我们应该清楚箭头函数是匿名函数表达式

for of

JavaScript 默认提供了iterable 的标准内建值包括

  • Arrays
  • Strings
  • Generators
  • Collections/TypedArrays

--2020-12-17 第二部分第二章