第 4 章 变量、作用域和内存问题

  • 变量包含两种类型的值:

    • 基本类型值,指的是简单的数据段
    • 引用类型值,指的是那些可能由多个值构成的对象
  • 复制变量值

    • 复制基本类型的变量值只是复制了该值的副本
    • 复制引用类型的变量值时,同样也会将存储在变量对象的值复制一份放到新变量的空间中,不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。两个变量指向同一个对象。
  • 传递参数

    • 所有函数的参数都是按值传递的
  • 检测类型

    • typeof 检测基础类型
    • instanceof检测引用类型
      • 变量 instanceof 构造函数(例:obj instanceof Object)
      • 所有引用类型的值都是 Object 的实例
  • 执行环境

    • 在浏览器中,全局执行环境是window对象
    • 每个函数都有自己的执行环境
  • 作用域链

    • 当代码在一个环境中执行时,会创建变量对象的一个作用域链
    • 作用域链的前端,始终是当前执行的代码所在环境的变量对象。
    • 作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含对象。这样一直延续到全局执行环境。
    • 全局执行环境的变量对象始终都是作用域链中的最后一个对象。
  • 垃圾收集

    • JavaScript 具有自动垃圾收集机制
      • 对于不再使用的变量打上标记,被打上标记的变量将在执行回收时被清除,释放内存空间。

第 5 章 引用类型

  • 引用类型的值是引用类型的一个实例

  • 引用类型就是一种数据结构,描述了一类对象所具有的属性和方法

  • 创建 Object 实例的方式有两种:

    • ```js
      var obj = new Object();
      1
      2
      3

      - ```js
      var obj = {}; // 与 new Object() 相同,但实际不会调用Object构造函数
  • 访问对象的属性有两种:

    • 点表示法 和 方括号表示法

Array 类型

  • length 属性不是只读的

  • 检测数组

    • ```js
      value instanceof Array;
      1
      2
      3

      - ```js
      Array.isArray(value);
  • 转换方法

    • toLocaleString() 与 toString()相同
    • toString() 返回数组中每个值的字符串形式用逗号分隔拼接而成的字符串
    • valueOf() 返回数组本身

join() 转换方法 (不改原数组)

接收一个参数,用作分隔符的字符串,然后返回包含所有数组项的字符串。

1
2
3
4
5
var arr = ["red", "blue", "green"];
var arrStr = arr.join("|"); // "red|blue|green"

arr.join(); // "red,blue,green"
arr.join(""); // "redbluegreen"

栈方法,后进先出 push() 、pop() (改变原数组)

  • push() 向数组末尾添加成员,返回总长
  • pop() 移除数组末尾一个成员,返回该成员

队列方法,先进先出 push()、shift() 、unshift() (改变原数组)

  • shift() 移除数组首个成员,返回该成员

  • unshift() 在数组前面添加成员,返回总长

push()和 shift() 形成队列方法

unshift 和 pop() 形成反方向队列方法

重排序方法 reverse() 反转 sort() 排序 (改变原数组)

  • reverse() 反转数组项的顺序
  • sort() 接收一个函数作为参数,函数接收两个参数。
    • 自定义排序:函数内,如果第一个参数应该位于第二个之前,则手动返回一个负数,如果两个参数相等,手动返回 0,如果第一个参数应该位于第二个参数之后,则手动返回一个正数。
1
2
3
4
5
6
7
8
9
10
// 升序
arr.sort(function(a,b){
if(a < b) {
return -1
} else if (a > b) {
return 1
} else {
retunr 0
}
})

简写:

1
2
3
arr.sort((a, b) => {
return a - b; // 升序, b-a 降序
});

操作方法 concat() 拼接,slice() 切片,splice() 移接

  • concat() 拼接数组 (不改原数组

    1
    2
    var arr1 = ["a", "b"];
    var arr2 = arr1.concat("c", "d"); // ['a','b','c','d']
  • slice() 切片(不改原数组

    • slice(起始位置 [, 结束位置]) 返回起始位置到结束位置的成员,不包含结束位置。
    1
    2
    3
    var arr1 = [1, 2, 3, 4, 5];
    var arr2 = arr1.slice(1, 3); // [2,3]
    var arr3 = arr1.slice(2); // [3,4,5]
  • splice() 移接 (改变原数组

    • splice(起始位置, 要删除的个数,要插入的项)
      • 要插入的项 可以有 0 个或多个
    • splice() 始终返回一个数组,该数组成员中包含原始数组中被删除的项,如果没有则返回空数组。
    • 数组最强大的方法,可用于删除、插入、替换操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    arr = [1, 2, 3, 4];
    arr.splice(1, 1); // [2]
    arr; // [1,3,4]

    arr = [1, 2, 3, 4];
    arr.splice(2, 0, "a"); // []
    arr; // [1,2,'a',3,4]

    arr = [1, 2, 3, 4];
    arr.splice(3, 1, "a"); // [4]
    arr; // [1,2,3,'a']

位置方法 indexOf()、lastIndexOf()

  • 查找项的位置,没有则返回-1
  • indexOf() 从前面开始找,lastIndexOf() 从后面开始找

迭代方法 every()、some() 、filter()、map() 、forEach() (都不会改变原数组)

  • 5 个迭代方法,每个方法都接收两个参数:

    • 在每项上运行的函数
    • 运行函数的作用域对象
  • 函数接收三个参数:

    • 数组项的值
    • 该项的索引
    • 数组本身
  • every() 如果函数对每项都返回 true,则返回 true

    • 例:判断数组每一项是否都大于 2

      1
      2
      3
      4
      5
      var numbers = [1, 2, 3, 2, 1];
      var result = numbers.every((item, index, array) => {
      return item > 2;
      });
      result; // false
  • some() 如果函数对任一项返回 true,则返回 true

    • 例:判断数组是否包含大于 2 的值

      1
      2
      3
      4
      5
      var numbers = [1, 2, 3, 2, 1];
      var result = numbers.some((item, index, array) => {
      return item > 2;
      });
      result; // true
  • filter() 返回函数会返回 true 的项组成的数组

    • 例:过滤掉数组中小于等于 2 的数

      1
      2
      3
      4
      5
      var numbers = [1, 2, 3, 4, 5];
      var result = numbers.filter((item, index, array) => {
      return item > 2;
      });
      result; // [3,4,5]
  • map() 返回每次函数调用的结果组成的数组

    • 例:给数组每一项乘以 2

      1
      2
      3
      4
      5
      var numbers = [1, 2, 3, 4, 5];
      var result = numbers.map((item, index, array) => {
      return item * 2;
      });
      result; // [2,4,6,8,10]
  • forEach() 循环数组每一项,没有返回值

    • 例:循环每一项

      1
      2
      3
      4
      var numbers = [1, 2, 3, 4, 5];
      numbers.forEach((item, index, array) => {
      // 做一些操作
      });

归并方法 reduce() reduceRight()

  • reduce() 归并为

  • reduceRight() 从右边归并

  • 这两个方法都会迭代数组所有项,然后构建一个最终结果并返回

  • 方法接收两个参数: 每一项上调用的函数,归并基础的初始值

  • 函数接收 4 个参数:前一个的值、当前值、当前值的索引、数组对象

  • 例:求数组每一项之和

    1
    2
    3
    4
    5
    var numbers = [1, 2, 3, 4, 5];
    var result = number.reduce((prev, cur, index, arr) => {
    return prev + cur;
    });
    result; // 15
  • reduce()方法,第一次执行函数时,prev 是数组的第一项,cur 是数组的第二项