跳至主要內容

《JavaScript高级程序设计》笔记

Mr.Chen笔记笔记红宝书大约 12 分钟约 3617 字

《JavaScript 高级程序设计》笔记

第 1 章 JavaScript 简介

  • JavaScript 诞生于1995

  • 一个完整的 JavaScript 由这三部分组成:

    • ECMAScript (核心)
    • DOM (文档对象模型)
    • BOM (浏览器对象模型)
  • ECMAScript 的 宿主环境 包含 :

    • 浏览器
    • Node
    • flash
  • ECMAScript 大致规定了下列组成部分:

    • 语法
    • 类型
    • 语句
    • 关键字
    • 保留字
    • 操作符
    • 对象

第 2 章 在 HTML 中使用 JavaScript

  • <script> 标签有下列常见属性:
    • async 表示立即下载脚本,不妨碍页面的其他操作(异步下载)
      • 无法保证每个 js 的顺序
      • 用于互不依赖的 js
      • 主要目的是不让页面等 js
    • defer 延迟到文档完全解析和显示之后在执行
      • </html>标签之后执行
    • src 外部文件链接
    • type 表示编写代码使用的脚本语言的内容类型
      • text/javascript

第 3 章 基本概念

  • 语法,借鉴了 C 语言

    • 区分大小写
    • 标识符,指的是变量、函数、属性的名字
      • 第一个字符必须是 字母、下划线、或美元符号
      • 其他字符可以是字母、下划线、美元符号或数字
  • 严格模式

    'use strict'
    
    
  • 数据类型

    • 基本数据类型
      • Undefined、Null、Boolean、Number、String
      • typeof操作符,一般用于基本类型的检测,返回相应类型的字符串
        • “undefined”,"boolean","string","number","object","function"
    • 复杂数据类型
      • Object
  • Null类型

    • 表示空对象指针
    • 只要意在保存对象的变量还没有真正保证对象,则保存null
    • undefined派生自null,因此用==比较返回true
  • 浮点数,指的是数值中包含一个小数点,并且小数点后面至少有一位数字

  • NaN

    • 任何涉及 NaN 的操作都返回NaN
    • NaN与任何值都不相等,包括NaN本身
  • 数值转换

    • 有 3 个函数可以把非数值转换为数值
      • Number() 可以用于任何数据类型
      • parseInt() 专门用于字符串转数值,用于解析整数
      • parseFloat() 专门用于字符串转数值,用于解析浮点数
  • 字符串

    • 数值、布尔值、对象、字符串值本身 都有 toString()方法,用于转为字符串
    • undefined 和 null 没有 toString()方法,但可以使用 String()方法
  • Object 类型

    • 对象其实就是一组数据与功能的集合

    • 使用 Object()构造函数创建对象

      var obj = new Object() // 同 obj = {}
      
    • 每个对象实例都有下列属性和方法

      • constructor 指向用于创建当前对象的构造函数 。(对于上面例子而言,就是Object()
      • hasOwnProperty(propertyName) 用于检查给定属性是否在当前对象实例中
      • isPrototypeOf(Object) 用于检查传入的对象是否是当前对象的原型
      • propertyIsEnumerable(propertyName) 用于检查给定的属性是否能够使用for-in来枚举
      • toLocaleString() 返回对象的字符串表示,该字符串与执行环境的地区对应
      • toString() 返回对象的字符串表示
      • valueOf() 返回对象的字符串、数值、布尔值表示。通常与toString()返回值相同

      所有对象都有以上属性和方法

  • 操作符

    • 一元操作符
      • ++

      • 前置与后置的区别是与其他数运算时,前置会先执行递增(减)再与其他数运算,后置会先与其他数运算再对自身执行递增(减)
    • 布尔操作符
      • 与 (&&)
        • 短路操作,即如果第一个操作数能决定结果,就不会对第二个操作数求值
      • 或 (||)
        • 短路操作,即如果第一个操作数能决定结果,就不会对第二个操作数求值
      • 非 (!)
        • 先使用 Boolean()转成布尔值再取反
  • 语句(也称流控制语句)

    • if-else

    • do-while

      • 后测试循环语句,在对表达式求值之前,循环体内的代码至少会被执行一次

        var i = 0
        do {
          i += 2
        } while (i < 10) // 只要i小于10就会一直循环
        
    • while

      • 前测试语句

        var i = 0
        while (i < 10) {
          i += 2
        } // 只要i小于10就会一直循环
        
    • for

      • 使用 while 循环做不到的,使用 for 循环同样做不到。就是说,for 循环只是把与循环有关的代码集合在一个位置

        for (初始化; 条件; 循环后执行) {
          // ...
        }
        
      • break 立即退出循环

      • continue 退出当前单次循环

    • for- in 用来枚举对象的属性

  • 函数

    • 任何函数都可以在任何时候返回任何值
    • 未指定返回值的函数会返回一个 undefined
    • 通过 arguments 访问参数,它是一个类数组

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

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

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

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

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

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

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

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

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

第 5 章 引用类型

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

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

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

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

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

Array 类型

  • length 属性不是只读的

  • 检测数组

    • value instanceof Array
      
    • Array.isArray(value)
      
  • 转换方法

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

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

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

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,如果第一个参数应该位于第二个参数之后,则手动返回一个正数。
// 升序
arr.sort(function(a,b){
    if(a < b) {
        return -1
    } else if (a > b) {
        return 1
    } else {
        retunr 0
    }
})

简写:

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

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

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

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

    • slice(起始位置 [, 结束位置]) 返回起始位置到结束位置的成员,不包含结束位置。
    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() 始终返回一个数组,该数组成员中包含原始数组中被删除的项,如果没有则返回空数组。
    • 数组最强大的方法,可用于删除、插入、替换操作
    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

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

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

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

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

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

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

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

    • 例:循环每一项

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

归并方法 reduce() reduceRight()

  • reduce() 归并为

  • reduceRight() 从右边归并

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

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

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

  • 例:求数组每一项之和

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

第 6 章 面向对象的程序设计

6.1 理解对象

  • 对象的定义:无序属性的集合,其属性可以包含基本值、对象或者函数。
    • 一组键值对,其中值可以是数据或函数

6.1.1 对象的属性

​ 包含两种:数据属性访问器属性

1.数据属性
  • configurable 可配置性(限制 delete 删除属性和Object.defineProperty()方法是否起效。),默认 true
  • enumerable 可列举性,默认 true
  • writable 可写性,默认 true
  • value 值,默认 undefined

使用Object.defineProperty()方法修改这些默认属性。接收三个值:属性所在的对象、属性名、描述符对象

var person = {}
Object.defineProperty(person, 'name', {
  writable: false,
  value: 'xu'
})

console.log(person.name) // xu
person.name = 'gao' // 修改无效
console.log(person.name) // xu

使用此方法定义属性如未指定configurableenumerablewritable 将默认false

2.访问器属性

包含两个函数:getter 函数和 setter 函数(这两个函数都是非必需)。读取时调用 getter,访问时调用 setter。

使用Object.defineProperty()方法定义访问器属性。

var book = {
  _year: 2020,
  edition: 1
}

Object.defineProperty(book, 'year', {
  get: function () {
    return this._year
  },
  set: function (newValue) {
    if (newValue > 2020) {
      this._year = newValue
      this.edition += newValue - 2020
    }
  }
})

book.year = 2021
console.log(book.edition) // 2

当 getter 函数和 setter 函数只指定其中一个时,另外一个将不能用。

6.1.2 定义多个属性

Object.defineProperties()方法定义多个属性。接收两个参数: 要添加或修改属性的对象 、第二个参数是一个对象,其属性与第一个参数中的属性一一对应。

var book = {}
Object.defineProperties(book, {
  _year: {
    // 数据属性
    writable: true,
    value: 2004
  },
  edition: {
    // 数据属性
    writable: true,
    value: 1
  },
  year: {
    // 访问器属性
    get: function () {
      return this._year
    },
    set: function (newValue) {
      if (newValue > 2004) {
        this._year = newValue
        this.edition += newValue - 2004
      }
    }
  }
})

// 定义了三个属性,每个属性有不同的描述符

6.1.3 读取属性的特性(描述符对象)

Object.getOwnPropertyDescriptor()方法获取描述符,接收两个参数: 属性所在的对象、属性名

var book = {}
Object.defineProperties(book, {
  _year: {
    // 数据属性
    writable: true,
    value: 2004
  },
  edition: {
    // 数据属性
    writable: true,
    value: 1
  },
  year: {
    // 访问器属性
    get: function () {
      return this._year
    },
    set: function (newValue) {
      if (newValue > 2004) {
        this._year = newValue
        this.edition += newValue - 2004
      }
    }
  }
})

var descriptor = Object.getOwnPropertyDescriptor(book, '_year')
console.log(descriptor) // {value: 2020, writable: true, enumerable: false, configurable: false}
var descriptor = Object.getOwnPropertyDescriptor(book, 'year')
console.log(descriptor) // {enumerable: false, configurable: false, get: ƒ, set: ƒ}

6.2 创建对象

使用 Object 构造函数或对象字面量方式创建对象。缺点:使用同一个接口创建很多对象时,会产生大量重复代码。解决方案:使用工厂模式的一种变体。

6.2.1 工厂模式

第 7 章 函数表达式

第 8 章 BOM

第 9 章 客户端检测

第 10 章 DOM

第 11 章 DOM 扩展

第 12 章 DOM2 和 DOM3

第 13 章 事件

第 14 章 表单脚本

第 15 章 使用 Canvas 绘图

第 16 章 HTML5 脚本编程

第 17 章 错误处理与调试

第 18 章 JavaScript 与 XML

第 19 章 E4X

第 20 章 JSON

第 21 章 Ajax 与 Comet

第 22 章 高级技巧

第 23 章 离线应用与客户端存储

第 24 章 最佳实践

第 25 章 新兴的 API

上次编辑于: