JS笔记(一)
- 什么是 JavaScript?
- HTML 中的 JavaScript
- 语言基础
第 1 章 什么是 JavaScript ?
JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。
所有现代的 HTML 页面都使用 JavaScript。
为什么学习 JavaScript?
JavaScript 是 web 开发人员必须学习的 3 门语言中的一门:
- HTML 定义了网页的内容
- CSS 描述了网页的布局
- JavaScript 控制了网页的行为
JavaScript 是一种轻量级的编程语言,是可插入 HTML 页面的编程代码。插入 HTML 页面后,可由所有的现代浏览器执行。JavaScript 可以做到:
- 直接写入 HTML 输出流
- 对事件的反应
- 改变 HTML 内容
- 改变 HTML 图像
- 能够改变任意 HTML 元素的大多数属性,而不仅仅是图片。
- 改变 HTML 样式
- 验证输入
完整的 JavaScript 由三部分组成:
- 核心(ECMAScript)
- 文档对象模型(DOM)
- 浏览器对象模型(BOM)
1.1 ECMAScript
ECMAScript即ECMA-262定义的语言,他描述了这门语言的:
- 语法
- 类型:
- 语句:
- 关键字:
- 保留字:
- 操作符:
- 全局对象
1.2 DOM
文档对象模型 DOM 是一个应用编程接口,用于在 HTML 中使用扩展的 XML。 DOM 将整个页面抽象为一组分层节点。使用 DOM 可以轻松的控制网页的内容结构,以及创建、删除、修改节点。
1.3 BOM
浏览器对象模型 BOM 的 API,用于支持访问和操作浏览器的窗口。使用 DOM,开发者可以操控浏览器显示页面以外的部分。
第 2 章 HTML 中的 JavaScript
将 JavaScript 引入网页,首先要解决它与网页的主导语言 HTML 的关系问题。
2.1 <script> 元素
将 JavaScript 插入 HTML 的主要办法是使用 <script> 元素。
HTML 中的脚本必须位于 <script> 与 </script> 标签之间。
脚本可被放置在 HTML 页面的 <body> 和 <head> 部分中。
<script>
function sayHi() {
console.log(“Hello,world!”);
}
</script>
2.1.1 src 属性
要包含外部文件的 JavaScript,就必须使用 src 属性。属性值是一个 URL,指向包含 JavaScript 的代码文件,如:
<script src=”example.js”></script>
如果使用了 src 属性,那么 script 标签内不要再加别的内容,加上的内容会被忽略。
其中 script 标签可以包含外域的 URL,如:
<script src=”http://www.somewhere.com/example.js" ></script>
2.1.2 推迟执行脚本
设置 <script> 的 defer 属性,表示脚本在执行的时候不会改变页面结构。也就是说,脚本会被延迟到整个页面都被解析完毕后再运行。如:
<script defer src=”example1.js”></script>
<script defer src=”example2.js”></script>
2.1.3 异步执行脚本
<script>元素定义了 async 属性。从改变脚本处理方式上看,async 属性与 defer 类似。当然,它们两者也都只适用于外部脚本,都会告诉浏览器立即开始下载。
不过,与 defer 不同的是,标记为 async 的脚本并不保证能按照它们出现的次序执行。
如下面这个例子,第二个脚本可能先于第一个脚本执行。因此它们之间没有依赖关系。
<script async src=”example1.js”></script>
<script async src=”example2.js”></script>
2.1.4 动态加载脚本
除了<script>标签,还有其他方式可以加载脚本。因为 JavaScript 可以使用 DOM API,所以通过向 DOM 中动态添加 script 元素同样可以加载指定的脚本。只要创建一个 script 元素并将其添加到DOM 即可。
let script = document.createElement(‘script’);
script.src = ‘gibberish.js’;
script.async = false;
document.head.appendChild(script);
2.2 行内代码与外部文件
推荐使用外部文件,理由如下:
- 可维护性。JavaScript 代码如果分散到很多 HTML 页面,会导致维护困难。而用一个目录保存所有 JavaScript 文件,则更容易维护,这样开发者就可以独立于使用它们的 HTML 页面来编辑
代码。 - 缓存。浏览器会根据特定的设置缓存所有外部链接的 JavaScript 文件,这意味着如果两个页面都用到同一个文件,则该文件只需下载一次。这最终意味着页面加载更快。
- 适应未来。通过把 JavaScript 放到外部文件中,就不必考虑用 XHTML 或前面提到的注释黑科技。包含外部 JavaScript 文件的语法在 HTML 和 XHTML 中是一样的
2.3 文档模式
指混杂模式与标准模式。
2.4 <noscript> 元素
针对早期浏览器不支持 JavaScript 的问题,需要一个页面优雅降级的处理方案。最终,<noscript>元素出现,被用于给不支持 JavaScript 的浏览器提供替代内容。虽然如今的浏览器已经 100%支持JavaScript,但对于禁用 JavaScript 的浏览器来说,这个元素仍然有它的用处。
<noscript> 元素可以包含任何可以出现在<body>中的 HTML 元素,<script>除外。
在下列两种情况下,浏览器将显示包含在<noscript>中的内容:
- 浏览器不支持脚本;
- 浏览器对脚本的支持被关闭。
如下面这段代码,如果浏览器支持脚本,则用户永远不会看到它:
<noscript>
<p>This page requires a JavaScript-enabled browser.</p>
</noscript>
第 3 章 语言基础
- 语法
- 数据类型
- 流控制语句
- 理解函数
3.1 语法
ECMAScript 的语法很大程度上借鉴了 C 语言和其他类 C 语言,如 Java 和 Perl。
3.1.1 区分大小写
3.1.2 标识符
- 第一个字符必须是一个字母、下划线或美元符号。
- 剩下的其他字符可以是字母、下划线、美元符号或数字。
3.1.4 严格模式
ECMAScript 5 增加了严格模式(strict mode)的概念。严格模式是一种不同的 JavaScript 解析和执
行模型,ECMAScript 3 的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。
启用严格模式,在脚本开头加上这一行:
“use strict”;
也可以单独指定一个函数在严格模式下执行,只要把这个预处理指令放到函数体开头即可:
function doSomething() {
”use strict”;
// 函数体
}
3.1.5 语句
ECMAScript 中的语句以分号结尾。
包含多条语句的代码块用花括号括起来。
3.2 关键字与保留字
关键字如下:
break do in typeof
case else instanceof var
catch export new void
class extends return while
const finally super with
continue for switch yield
debugger function this
default if throw
delete import try
始终保留:
enum
严格模式下保留:
implements package public
interface protected static
let private
模块代码中保留:
await
这些词汇不能用作标识符,不要使用关键字和保留字作为标识符和属性名。
3.3 变量
ECMAScript 变量是松散类型的,意思是变量可以用于保存任何类型的数据。
有 3 个关键字可以声明变量:var、const 和 let。
其中,var 在ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。
3.3.1 var 关键字
要定义变量,可以使用 var 操作符:
var message;
这行代码定义了一个名为 message 的变量,可以用它保存任何类型的值。
不初始化的情况下,变量会保存一个特殊值 undefined。
var message = “hi”;
var 声明作用域,意味着该变量将在函数退出时被销毁。
但是在函数内定义变量时省略 var 操作符,可以创建一个全局变量。
function test() {
message = “hi”; // 全局变量
}
3.3.2 let 声明
let 跟 var 的作用差不多,但有着非常重要的区别。最明显的区别是,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。
对声明冗余报错不会因混用 let 和 var 而受影响。这两个关键字声明的并不是不同类型的变量,它们只是指出变量在相关作用域如何存在。
3.3.3 const 声明
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。
const age = 26;
age = 36; // TypeError: 给常量赋值
3.3.4 声明风格及最佳实践
1.不使用 var
有了 let 和 const,大多数开发者会发现自己不再需要 var 了。限制自己只使用 let 和 const 有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值。
2.const 优先,let 次之
使用 const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。因此,很多开发者认为应该优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let。这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为。
3.4 数据类型
ECMAScript 有 6 种简单数据类型(也称为原始类型),还有一种复杂数据类型叫 Object。
3.4.1 typeof 操作符
需要一种手段来确定任意变量的数据类型。
- “undefined”表示值未定义;
- “boolean”表示值为布尔值;
- “string”表示值为字符串;
- “number”表示值为数值;
- “object”表示值为对象(而不是函数)或 null;
- “function”表示值为函数;
- “symbol”表示值为符号。
下面是使用 typeof 操作符的例子:
let message = “some string”;
console.log(typeof message); // “string”
console.log(typeof(message)); // “string”
console.log(typeof 95); // “number”
3.4.2 Undefined 类型
Undefined 类型只有一个值,就是特殊值 undefined。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。
3.4.3 Null 类型
Null 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给typeof 传一个 null 会返回”object”的原因。
在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值。这样,只要检查这个变量的值是不是 null 就可以知道这个变量是否在后来被重新赋予了一个对象的引用。
3.4.4 Boolean 类型
Boolean(布尔值)类型是 ECMAScript 中使用最频繁的类型之一,有两个字面值:true 和 false。
let found = true;
let lost = false;
所有其他 ECMAScript 类型的值都有相应布尔值的等价形式。要将一个其
他类型的值转换为布尔值,可以调用特定的 **Boolean()**转型函数:
let message = “Hello world!”;
let messageAsBoolean = Boolean(message);
下表总结了不同类型与布尔值之间的转换规则。
数据类型 | 转换为 true 的值 | 转换为 false 的值 |
---|---|---|
Boolean | true | false |
String | 非空字符串 | “”(空字符串) |
Number | 非零数值(包括无穷值) | 0、NaN(参见后面的相关内容) |
Object | 任意对象 | null |
Undefined | N/A(不存在) | undefined |
3.4.5 Number 类型
最基本的数值字面量格式是十进制整数,直接写出来即可:
let intNum = 55; // 整数
要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少有一个数字。
在小数点后面没有数字的情况下,数值就会变成整数。
let floatNum1 = 1.1;
let floatNum2 = 0.1;
let floatNum3 = .1; // 有效,但不推荐
ECMAScript 可以表示的最小数值保存在 Number.MIN_VALUE 中,可以表示的最大数值保存在 Number.MAX_VALUE 中。
如果某个计算得到的数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无穷)值。
要确定一个值是不是有限大(即介于 JavaScript 能表示的最小值和最大值之间),可以使用 **isFinite()**函数,如下所示:
let result = Number.MAX_VALUE + Number.MAX_VALUE;
console.log(isFinite(result)); // false
有一个特殊的数值叫 NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作失败了,为此,ECMAScript 提供了 **isNaN()**函数。
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false,10 是数值
console.log(isNaN(“10”)); // false,可以转换为数值 10
console.log(isNaN(“blue”)); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值 1
有 3 个函数可以将非数值转换为数值:Number()、parseInt()和 parseFloat()。Number()是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。
3.4.6 String 类型
String(字符串)数据类型表示零或多个 16 位 Unicode 字符序列。字符串可以使用双引号(”)、单引号(’)或反引号(`)标示。
字符串的长度可以通过其 length 属性获取:console.log(text.length); // 28
ECMAScript 中的字符串是不可变的,要想修改必须先销毁原始的字符串。
let lang = “Java”;
lang = lang + “Script”;
有两种方式把一个值转换为字符串。首先是使用几乎所有值都有的 **toString()**方法。通过传入参数,可以得到数值的二进制、八进制、十六进制。
let num = 10;
console.log(num.toString()); // “10”
console.log(num.toString(2)); // “1010”
console.log(num.toString(8)); // “12”
console.log(num.toString(10)); // “10”
console.log(num.toString(16)); // “a”
3.4.7 Symbol 类
Symbol(符号)是 ECMAScript 6 新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。
let sym = Symbol();
console.log(typeof sym); // symbol
3.4.8 Object 类型
ECMAScript 中的对象其实就是一组数据和功能的集合。
let o = new Object();
每个 Object 实例都有如下属性和方法:
- constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是 Object() 函数。
- hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如 o.hasOwnProperty(“name”))或符号。
- isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。
- propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用(本章稍后讨论的)for-in 语句枚举。与 hasOwnProperty()一样,属性名必须是字符串。
- toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
- toString():返回对象的字符串表示。
- valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。
3.5 操作符
包括数学操作符(如加、减)、位操作符、关系操作符和相等操作符等。
3.5.1 一元操作符
- 递增/递减操作符
- 一元加和减
3.5.2 位操作符
- 按位非 let num2 = ~num1;
- 按位 let result = 25 & 3;
- 按位或 let result = 25 | 3;
- 按位异或 let result = 25 ^ 3;
- 左移 let newValue = oldValue << 5;
- 有符号右移 let newValue = oldValue >> 5;
- 无符号右移 let newValue = oldValue >>> 5;
3.5.3 布尔操作符
- 逻辑非 console.log(!false); // true
- 逻辑与 let result = true && false;
- 逻辑或 let result = true || false;
3.5.4 乘性操作符
- 乘法操作符
- 除法操作符
- 取模操作符
3.5.5 指数操作符
console.log(3 ** 2); // 9
3.5.6 加性操作符
要注意如果两个操作数都是字符串,则将第二个字符串拼接到第一个字符串后面。
let result2 = 5 + “5”; // “55”
3.5.7 关系操作符
包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=)。
let result1 = 5 > 3; // true
let result2 = 5 < 3; // false
3.5.8 相等操作符
- 等于和不等于
- 全等和不全等
let result1 = (“55” == 55); // true,转换后相等
let result2 = (“55” === 55); // false,不相等,因为数据类型不同
3.5.9 条件操作符
条件操作符是 ECMAScript 中用途最为广泛的操作符之一,语法如下:
**variable = boolean_expression ? true_value : false_value;**、
比如:
let max = (num1 > num2) ? num1 : num2;
3.5.10 赋值操作符
如:
let num = 10;
num += 10;
3.5.11 逗号操作符
let num1 = 1, num2 = 2, num3 = 3;
let num = (5, 1, 4, 8, 0); // num 的值为 0
3.6 语句
- if 语句
- do-while 语句
- while 语句
- for 语句
- for-in 语句 for (property in expression) statement
- for-of 语句 for (property of expression) statement
- 标签语句 label: statement,可以在后面通过 break 或 continue 语句引用
- break 和 continue 语句 后面可加标签
- with 语句 with (expression) statement;
- switch 语句
其中对于with语句,如:
with(location) {
let qs = search.substring(1);
let hostName = hostname;
let url = href;
}
3.7 函数
函数形式如下:
function functionName(arg0, arg1,…,argN) {
statements
}