javascript 高级程序设计第四版

在线代码运行

什么是javascript

完整的JavaScript包含

  1. 语言定义(ECMAScript)、

    ECMAScript,即 ECMA-262定义的语言,ECMA-262到底定义了什么?在基本的层面,它描述这门语言的如下部分:  语法  类型  语句  关键字  保留字  操作符  全局对象 ECMAScript 只是对实现这个规范描述的所有方面的一门语言的称呼。JavaScript 实现了 ECMAScript,而 Adobe ActionScript同样也实现了ECMAScript。

  2. 文档对象模型(DOM)

    提供与网页内容交互的方法和接口

  3. 浏览器对象模型(BOM)

    提供与浏览器交互的方法和接口

HTML 中的JavaScript

DOMContentLoaded

浏览器已经完全加载了HTML,并构建了DOM树,但是IMG和样式表这样的外部资源并未被加载完成,但其一定会等待script资源加载并运行完成

DOM 已经就绪,因此处理程序可以查找 DOM 节点,并初始化接口

DOMContentLoaded 和脚本

如果HTML文档中存在script标签是,就会等待script下载并运行完成,因为script脚本可能会修改DOM

DOMContentLoaded 和样式

外部样式表不会影响 DOM,因此 DOMContentLoaded 不会等待它们。

如果在样式后面有一个脚本,那么该脚本必须等待样式表加载完成:

  1. <!doctype html>
  2. <head>
  3. // 假设style.css编写了如下样式
  4. body {
  5. margin-top: 10px;
  6. }
  7. <link type="text/css" rel="stylesheet" href="style.css">
  8. </head>
  9. <body>
  10. <script>
  11. // 在样式表加载完成之前,脚本都不会执行
  12. alert(getComputedStyle(document.body).marginTop); // 10px
  13. </script>
  14. </body>

原因是,脚本可能想要获取元素的坐标和其他与样式相关的属性,如上例所示。因此,它必须等待样式加载完成。

**DOMContentLoaded** 等待脚本时,它现在也在等待脚本前面的样式。

defer推迟执行脚本

当我们需要先加载 JavaScript 库,然后再加载依赖于它的脚本时,这可能会很有用。

defer告诉浏览器不需要等待此脚本,继续构建DOM,脚本会在后台下载,DOM构建完成后,脚本才会执行

  • defer脚本不会阻塞DOM构建
    ```

    …content before script…

…content after script…

- 具有 `defer` 特性的脚本总是要等到 DOM 解析完毕,但在 `DOMContentLoaded` 事件之前执行。**会阻塞**`**DOMContentLoaded**`

…content before scripts…

…content after scripts…

  1. - defer会并行下载,等都下载完成后再按顺序执行
  2. <a name="c0eab20f"></a>
  3. ### [async](https://zh.javascript.info/script-async-defer#async)异步执行脚本
  4. > 将独立的第三方脚本集成到页面时,此时采用异步加载方式是非常棒的:计数器,广告等,因为它们不依赖于我们的脚本,我们的脚本也不应该等待它们:
  5. - 不会阻塞DOM
  6. - 脚本独立,互不等待
  7. - DOMContentLoaded也不会相互等待
  8. `async` 脚本会在后台加载,并在加载就绪时运行。DOM 和其他脚本不会等待它们,它们也不会等待其它的东西。`async` 脚本就是一个会在加载完成时执行的完全独立的脚本
  9. <a name="60e9906a"></a>
  10. ## 语言基础
  11. <a name="ddc7d28b"></a>
  12. ### 变量
  13. <a name="e0417c8d"></a>
  14. ### var声明提升
  15. ```javascript
  16. // 使用 var 时,下面的代码不会报错。这是因为使用这个关键字声明的变量会自动提升到函数作用域顶部
  17. function foo() {
  18. console.log(age); var age = 26;
  19. }
  20. foo();
  21. // undefined 之所以不会报错,是因为 ECMAScript 运行时把它看成等价于如下代码:
  22. function foo() {
  23. var age;
  24. console.log(age); age = 26;
  25. }
  26. foo(); // undefined

let声明

let和var的区别

  • 作用域区别
    • let声明的是块级作用域

javaScript高级程序设计 - 图1

age变量之所以不能在if块外部引用,是因为他的作用域仅限于该块内部

  • var声明的是函数作用域

javaScript高级程序设计 - 图2

  • 冗余声明区别
    • let不允许同一块级作用域出现冗余声明
    • var允许
  • 作用域提升区别

    • let不会被提升

      1. // age 不会被提升
      2. console.log(age); // ReferenceError:age 没有定义
      3. let age = 26;
    • var会被提升

      1. // name 会被提升
      2. console.log(name); // undefined
      3. var name = 'Matt';
  • 全局声明区别

    • let全局作用域中声明不会成为window对象的属性

      1. let age = 26;
      2. console.log(window.age); // undefined
    • var则会

      1. var name = 'Matt';
      2. console.log(window.name); // 'Matt'

      数据类型

      简单和复杂数据类型

      六种基本数据类型

  • string

  • boolean
  • Number
  • undefined
  • null
  • symbol

一种复杂类型

  • Object

函数在ECMAScript中被认为是对象,并不代表一种数据类型

typeof

  • typeof null // object

    这是因为,null被认为是一个对空对象的引用

值的范围

  • 可以表示的最小,数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e324;
  • 可以表示的最大数值保存在 Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308。

如果某个计算得到的 数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无 穷)值。

  • 任何无法表示的负数以-Infinity(负无穷大)表示,
  • 任何无法表示的正数以 Infinity(正 无穷大)表示

    NaN

    NaN的意思是“不是整数” ```javascript 0/0 // NaN

-0/+0 // NaN

  1. 如果分子是非 0值,分母是有符号 0或无符号 0,则会返回 Infinity 或-Infinity
  2. ```javascript
  3. console.log(5/0); // Infinity
  4. console.log(5/-0); // -Infinity

布尔类型转换

image.png

数字类型转换

image.png

标签语句

标签语句用于给语句加标签,语法如下:
label: statement
下面是一个例子:

  1. start: for (let i = 0; i < count; i++) {
  2. console.log(i);
  3. }

在这个例子中,start 是一个标签,可以在后面通过 break 或 continue 语句引用。标签语句的
典型应用场景是嵌套循环。

  • break

    1. let num = 0;
    2. outermost:
    3. for (let i = 0; i < 10; i++) {
    4. for (let j = 0; j < 10; j++) {
    5. if (i == 5 && j == 5) {
    6. break outermost;
    7. }
    8. num++;
    9. }
    10. }
    11. console.log(num); // 55
  • continue ```javascript let num = 0; outermost: for (let i = 0; i < 10; i++) { for (let j = 0; j < 10; j++) { console.log(i, j) if (i == 5 && j == 5) {

    1. continue outermost;

    } num++; } } console.log(num); // 95

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1445427/1640183007381-6dde969e-1ff5-4ea8-b097-802426bf9347.png#clientId=uaea8f2c6-c988-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=551&id=u095e6126&margin=%5Bobject%20Object%5D&name=image.png&originHeight=551&originWidth=648&originalType=binary&ratio=1&rotation=0&showTitle=false&size=28683&status=done&style=none&taskId=u3545c0b4-2136-4e30-9c36-73f48d78926&title=&width=648)
  2. <a name="F4opa"></a>
  3. ## 基本引用类型
  4. <a name="FSYGq"></a>
  5. ### 引用类型
  6. ```javascript
  7. let date = new Date()
  8. // Date()就是引用类型
  9. // date 就是实例

原始值包装类型

  1. let a = new String('a')
  2. // String() 是原始值包装类型
  3. // a 是原始值包装对象
  1. let value = "25";
  2. let number = Number(value); // 转型函数
  3. console.log(typeof number); // "number"
  4. let obj = new Number(value); // 构造函数
  5. console.log(typeof obj); // "object"

字符串操作方法

返回子字符串,第一个参数表示子字符串的开始位置,第二个参数表示子字符串的结束位置,,但对substr而言,是需要截取的子字符串数量,不传第二个参数表示截取到末尾

  1. let stringValue = "hello world";
  2. console.log(stringValue.slice(3));// "lo world"
  3. console.log(stringValue.substring(3)); // "lo world"
  4. console.log(stringValue.substr(3));// "lo world"
  5. console.log(stringValue.slice(3, 7)); // "lo w"
  6. console.log(stringValue.substring(3,7)); // "lo w"
  7. console.log(stringValue.substr(3, 7)); // "lo worl" 从索引3开始算,有7个字符串,包含空格,包含索引3

当某个参数是负值时,这 3个方法的行为又有不同。比如,slice()方法将所有负值参数都当成字
符串长度加上负参数值。 而 substr()方法将第一个负参数值当成字符串长度加上该值,将第二个负参数值转换为 0。 substring()方法会将所有负参数值都转换为 0。看下面的例子:

  1. let stringValue = "hello world";
  2. console.log(stringValue.slice(-3)); // "rld"
  3. console.log(stringValue.substring(-3)); // "hello world"
  4. console.log(stringValue.substr(-3)); // "rld"
  5. console.log(stringValue.slice(3, -4)); // "lo w"
  6. console.log(stringValue.substring(3, -4)); // "hel"
  7. console.log(stringValue.substr(3, -4)); // "" (empty string)