script标签
将脚本添加到网页上,对于服务器端环境(如 Node.js),你只需要使用诸如 "node my.js"
的命令行来执行它。
- 使用
<script>
标签将 JavaScript 程序插入到 HTML 文档的任何位置。 - 当浏览器遇到
<script>
标签,代码会自动运行。 - 现代的标记(markup)
- type特性:现在html5已经不在需要
- language特性:默认就是 JavaScript。不再需要使用它了。
- 外部脚本:js代码过多时,单独放入一个文件,通过src放入html文件。
- 使用独立文件的好处是浏览器会下载它,然后将它保存到浏览器的 缓存 中。
- 其他页面想要相同的脚本就会从缓存中获取,而不是下载它。所以文件实际上只会下载一次。这可以节省流量,并使得页面(加载)更快。
- 如果设置了
src
特性,script
标签内容将会被忽略。
代码结构
- 语句:语句是执行行为(action)的语法结构和命令。
- 分号:大多数情况下可以省略分号。 将换行符理解成“隐式”的分号。这也被称为 自动分号插入。注意也有js引擎识别不到的是否真的需要插入分号的情况
- 注释:
- 单行 //
- 多行 始
“/*”
并以一个星号和正斜杠结束“*/”
。 - 快捷键:单行ctrl+/,多行Ctrl+Shift+/,vscode块级注释 Alt + Shift + A
- 注释不支持嵌套
现代模式,‘’use strict''
需要一个特殊的指令 —— "use strict"
来明确地激活这些新的特性。
- “use strict”
- 当它处于脚本文件的顶部时,则整个脚本文件都将以“现代”模式进行工作。
- 只有注释可以出现在
"use strict"
的上面。 - 没有类似于
"no use strict"
这样的指令可以使程序返回默认模式。一旦进入了严格模式,就没有回头路了。
- 浏览器控制台 4. 打开控制台的时候,默认是不启动
use strict
的。 5. 在控制台启用use strict
javascript
'use strict';// <Shift+Enter 换行>
// ...你的代码
//<按下 Enter 以运行>
//还有一直可靠但不优雅的写法
(function() {
'use strict';
// ...你的代码...
})()
- 我们应该使用 “use strict” 吗? 现代 JavaScript 支持 “class” 和 “module” —— 高级语言结构,它们会自动启用
use strict
。则无需添加"use strict"
指令。
变量
变量 是数据的“命名存储“
- 变量
- 变量命名 4. 变量名称必须仅包含字母、数字、符号
$
和_
。 5. 首字符必须非数字。 6. 命名包括多个单词,通常采用驼峰式命名法(camelCase) 7. 会区分大小写:命名为apple
和APPLE
的变量是不同的两个变量。 8. 保留字:有一张 保留字列表,这张表中的保留字无法用作变量命名,因为它们被用于编程语言本身了。 - 常量
- 声明一个常数(不变)变量,可以使用
const
而非let
- 使用
const
声明的变量称为“常量”。它们不能被修改,如果你尝试修改就会发现报错 - 使用大写字母和下划线来命名这些常量。
- 有些常量是固定已知的,有些常量是在执行时初始赋值之后就不会改变
- 声明一个常数(不变)变量,可以使用
- 正确命名变量
- 简单易读的变量名,能明确知道变量的作用是什么,
数据类型
JS的8中基本数据类型(7个原始数据类型和一个引用类型) 我们可以将任何类型的值存入变量。例如,一个变量可以在前一刻是个字符串,下一刻就存储一个数字
- Number类型
- 整数和浮点数,还有特殊数值:
Infinity
(无穷大)、-Infinity
和NaN
(计算错误,。任何对NaN
的进一步数学运算都会返回NaN
,只有一个例外:NaN ** 0
结果为1
)。
- 整数和浮点数,还有特殊数值:
- BigInt类型 2. “number” 类型无法安全地表示大于
(253-1)
(即9007199254740991
),或小于-(253-1)
的整数。 3. 表示任意长度的整数,可以用于密码学或微秒精度的时间戳。 4. 可以通过将n
附加到整数字段的末尾来创建BigInt
值。 - String类型
- 必须在引号里
- 双引号:
"Hello"
.
- 双引号:
- 单引号:
'Hello'
. - 反引号:
`Hello`
.${……}
- 只有一种
string
类型,一个字符串可以包含零个(为空)、一个或多个字符。,没有char
- Boolean类型 6. boolean 类型仅包含两个值:
true
和false
。 - null值
- 特殊的
null
值不属于上述任何一种类型。它构成了一个独立的类型,只包含null
值。 - JavaScript 中的
null
仅仅是一个代表“无”、“空”或“值未知”的特殊值。
- 特殊的
- undefined值
undefined
的含义是未被赋值
。如果一个变量已被声明,但未被赋值,那么它的值就是undefined
。
- Object类型
object
则用于储存数据集合和更复杂的实体。
- Symbol类型 2.
symbol
类型用于创建对象的唯一标识符。我们在这里提到symbol
类型是为了完整性 - typeof 运算符
- 速进行数据类型检验时,非常有用。
typeof
运算符返回参数的类型。 typeof(x)
与typeof x
相同。
- 速进行数据类型检验时,非常有用。
交互:alert、prompt 和 confirm
- alert: 弹出的这个带有信息的小窗口被称为 模态窗
- prompt:
JavaScript
result = prompt(title, [default]);
1. 接收两个参数:title显示给用户的文本,default指定 input 框的初始值。
2. 方括号表示该参数是可选的,不是必需的。
3. 如果用户取消了输入,则返回 null。
4. 在IE中我们不提供值,IE会将undefined插入prompt
- confirm
JavaScript
result = confirm(question);
1. 一个带有 `question` 以及确定和取消两个按钮的模态窗口。
2. 返回true或者false
类型转换
大多数情况下,运算符和函数会自动将赋予它们的值转换为正确的类型。例如:alert
会自动将任何值都转换为字符串以进行显示。算术运算符会将值转换为数字。
- 字符串转换
String(value)
来将value
转换为字符串类型
- 数字类型转换
- 在算术函数或者表达式中,会自动number类型转换,例如:除法”/"
Number(value)
显式地将这个value
转换为 number 类型。- 如果非数字类型不是一个有效数字,转换的结果是NaN
- number类型转换规则
值 | 变成…… |
---|---|
undefined | NaN |
null | 0 |
true和false | 1和0 |
String | 去掉首尾空白字符(空格、换行符 \n、制表符 \t 等)后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。 |
- 布尔类型转换
- 在逻辑运算,或者通过调用 Boolean(value) 显式地进行转换。
- 直观上为“空”的值(如
0
、空字符串、null
、undefined
和NaN
)将变为false
。
- 直观上为“空”的值(如
- 其他值变成
true
。
- 其他值变成
- 包含 0 的字符串
"0"
是true
基础运算符,数学运算
一元运算符,二元运算符,运算元
- 运算元:运算符应用的对象,比如说乘法运算
5 * 2
,有两个运算元:左运算元5
和右运算元2
。有时候人们也称其为“参数”而不是“运算元”。 - 一元运算符:一个运算符对应的只有一个运算元,比如负号
- 一个运算符拥有两个运算元,比如减号
- 运算元:运算符应用的对象,比如说乘法运算
数学运算
- 支持加减乘除,取余,求幂
- 取余:%
- 求幂:**,例如:
a ** b
将a
提升至a
的b
次幂,其表示为 ab
用二元运算符 + 连接字符串
- 如果加号
+
被应用于字符串,它将合并(连接)各个字符串,只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串。 - 二元
+
是唯一一个以这种方式支持字符串的运算符。其他算术运算符会将其转换成数字运算
- 如果加号
JavaScript
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
alert(2 + 2 + '1' ); // "41",不是 "221"
alert('1' + 2 + 2); // "122",不是 "14"
数字转化,一元运算符 +
- 加号
+
应用于单个值,对数字没有任何作用。但是如果运算元不是数字,加号+
则会将其转化为数字。 - 效果和
Number(...)
相同,但是更加简短。
- 加号
运算符优先级 ……>一元加号(+),一元负号(-)>求幂(
**
)>乘号(*
),除号(/)>加号(+),减号(-)>……>赋值符(=)>……赋值运算符 =,优先级较低
- 链式赋值(Chaining assignments) 例如:
let
a,
b,
c;
a=
b=
c=
2
+
2``;
a=4,b=4,c=4
- 链式赋值(Chaining assignments) 例如:
原地修改
JavaScript
let n = 2;
n += 5; // 现在 n = 7(等同于 n = n + 5)
n *= 2; // 现在 n = 14(等同于 n = n * 2)
alert( n ); // 14
- 自增/自减
- counter++ 相当于 counter = counter + 1
- counter-- 相当于 counter = counter - 1
- 自增/自减只能应用于变量。试一下,将其应用于数值(比如
5++
)则会报错。 - 运算符
++
和--
可以置于变量前,也可以置于变量后。但是是有区别的++
counter //2 立刻使用自增后的值- counter
++
//1 使用其自增之前的值
++/--
运算符同样可以在表达式内部使用。它们的优先级比绝大部分的算数运算符要高。
- 位运算符
- 位运算符把运算元当做 32 位整数,并在它们的二进制表现形式上操作。
- 按位与 &、按位或 | 、按位异或 ^ 、按位非 ~ 、左移<< 、右移 >> 、无符号右移 >>>
- 逗号运算符
- let a = (1 + 2, 3 + 4); //结果为7 这里,第一个表达式
1 + 2
运行了,但是它的结果被丢弃了。随后计算3 + 4
,并且该计算结果被返回。 - 请注意逗号运算符的优先级非常低,比
=
还要低,因此上面你的例子中圆括号非常重要,如果没有圆括号:a = 1 + 2, 3 + 4
会先执行+
,将数值相加得到a = 3, 7
,然后赋值运算符=
执行a = 3
,然后逗号之后的数值7
不会再执行,它被忽略掉了。相当于(a = 1 + 2), 3 + 4
。
- let a = (1 + 2, 3 + 4); //结果为7 这里,第一个表达式
值的比较
- 值的比较
- 大于 / 小于:
a > b
,a < b
。 - 大于等于 / 小于等于:
a >= b
,a <= b
。 - 检查两个值的相等:
a == b
,请注意双等号==
表示相等性检查,而单等号a = b
表示赋值。 - 检查两个值不相等:不相等在数学中的符号是
≠
,但在 JavaScript 中写成a != b
。
- 大于 / 小于:
- 比较结果为 Boolean 类型
- true 或者 false
- 字符串比较,字符串是根据Unicode 编码顺序按字符(母)逐个进行比较的。
- alert( 'Z' > 'A' ); // true
- alert( 'Glow' > 'Glee' ); // true
- alert( 'Bee' > 'Be' ); // true
- 不同类型间的比较
- 当对不同类型的值进行比较时,JavaScript 会首先将其转化为数字(number)再判定大小。
JavaScript
alert( '2' > 1 ); // true,字符串 '2' 会被转化为数字 2
alert( '01' == 1 ); // true,字符串 '01' 会被转化为数字 1
alert( true == 1 ); // true
alert( false == 0 ); // true
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
```
5. 严格相等
1. `==`,区分不出0和false,也无法区分空字符串和 `false`
2. 相等判断符号 `==` 两侧的值会先被转化为数字,
3. 严格相等运算符 `===`,在进行比较的时候不会做任何类型转换
6. 对 null 和 undefined 进行比较
1. `undefined` 和 `null` 在相等性检查 `==` 中不会进行任何的类型转换,它们有自己独立的比较规则,除了它们之间互等外,不会等于任何其他的值。
2. alert( null === undefined ); // false
3. alert( null == undefined ); // true
4. null vs 0
1. alert( null > 0 ); // false
2. alert( null == 0 ); // false
3. alert( null >= 0 ); // true
5. 特立独行的 undefined
```JavaScript
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
(1) 和 (2) 都返回 false 是因为 undefined 在比较中被转换为了 NaN,而 NaN 是一个特殊的数值型值,它与任何值进行比较都会返回 false。
(3) 返回 false 是因为这是一个相等性检查,而 undefined 只与 null 相等,不会与其他值相等。
- 避免问题
- 对于取值可能是
null/undefined
的变量,请按需要分别检查它的取值情况。 - 在使用
>
或<
进行比较时,需要注意变量可能为null/undefined
的情况。比较好的方法是单独检查变量是否等于null/undefined
。 - 只有不同类型的值在比较时才会转换成数字,同类型如字符串的比较规则是逐一字符比较。
- 对于取值可能是
条件分支:if 和 ?
- “if” 语句
- if(...) 语句计算括号里的条件表达式,如果计算结果是 true,就会执行对应的代码块。
- 使用 if 语句都用大括号
{}
来包装代码块,即使只有一条语句。这样可以提高代码可读性。
- 布尔转换
- if (…) 语句会计算圆括号内的表达式,并将计算结果转换为布尔型。
- 数字
0
、空字符串""
、null
、undefined
和NaN
都会被转换成false
。因为它们被称为“假值(falsy) - 其他值被转换为
true
,所以它们被称为“真值(truthy)
- 数字
- if (…) 语句会计算圆括号内的表达式,并将计算结果转换为布尔型。
else
语句- 如果判断条件不成立,就会执行它内部的代码。
- 多个条件:“else if”
- 条件运算符 ‘?’
- 有时它被称为三元运算符
- let result = condition ? value1 : value2;
- 问号运算符的优先级较低]
- 多个“?”
- 使用一系列问号 ? 运算符可以返回一个取决于多个条件的值。
逻辑运算符
JavaScript 中有四个逻辑运算符:||
(或),&&
(与),!
(非),??
(空值合并运算符)
- ||(或)
- 如果参与运算的任意一个参数为
true
,返回的结果就为true
,否则返回false
- 从左到右依次计算操作数。
- 处理每一个操作数时,都将其转化为布尔值。如果结果是
true
,就停止计算,返回这个操作数的初始值。 - 如果所有的操作数都被计算过(也就是,转换结果都是
false
),则返回最后一个操作数。 - 一些用法
- 获取变量列表或者表达式中的第一个真值。
- 短路求值(Short-circuit evaluation)。
- 如果参与运算的任意一个参数为
- &&(与)
- 当两个操作数都是真值时,与运算返回
true
,否则返回false
- 当两个操作数都是真值时,与运算返回
- 与运算寻找第一个假值
- 从左到右依次计算操作数。
- 在处理每一个操作数时,都将其转化为布尔值。如果结果是
false
,就停止计算,并返回这个操作数的初始值。 - 如果所有的操作数都被计算过(例如都是真值),则返回最后一个操作数。
- 与运算
&&
的优先级比或运算||
要高。 - 不要用
||
或&&
来取代if
- !(非)
- 将操作数转化为布尔类型:
true/false
。返回相反的值。
- 将操作数转化为布尔类型:
- 非运算符
!
的优先级在所有逻辑运算符里面最高,所以它总是在&&
和||
之前执行。
空值合并运算符“??”
空值合并运算符(nullish coalescing operator)的写法为两个问号 ??
。 a ?? b
的结果是:如果 a
是已定义的,则结果为a,如果 a
不是已定义的,则结果为 b
如果第一个参数不是 null/undefined
,则 ??
返回第一个参数。否则,返回第二个参数。
- 一系列的值中选择出第一个非
null/undefined
的值。 - 与 || 比较
||
返回第一个 真 值。
??
返回第一个 已定义的 值。
||
无法区分false
、0
、空字符串""
和null/undefined
。它们都一样 —— 假值(falsy values)
- 优先级
??
运算符的优先级与||
相同,它们的优先级都为3
,详见:MDN。
- ?? 与 && 或 || 一起使用
- JavaScript 禁止将
??
运算符与&&
和||
运算符一起使用,除非使用括号明确指定了优先级。
- JavaScript 禁止将
循环:while 和 for
循环 是一种重复运行同一代码的方法。
- “while” 循环
JavaScript
let i = 0;
while (i < 3) { // 依次显示 0、1 和 2
alert( i );
i++;
}
当 condition 为真时,执行循环体的 code。
循环体的单次执行叫作 **一次迭代**。
如果循环体只有一条语句,则可以省略大括号 `{…}`
- “do…while” 循环
- 循环首先执行循环体,然后检查条件,当条件为真时,重复执行循环体。
- 不管条件是否为真,循环体 至少执行一次
- “for” 循环
begin
执行一次,然后进行迭代:每次检查condition
后,执行body
和step
。for
循环的任何语句段都可以被省略。
- 跳出循环
- 随时都可以使用
break
指令强制退出。
- 随时都可以使用
- 继续下一次迭代
continue
指令是break
的“轻量版”。它不会停掉整个循环。而是停止当前这一次迭代,并强制启动新一轮循环(如果条件允许的话)。
- 禁止
break/continue
在 ‘?’ 的右边- 非表达式的语法结构不能与三元运算符
?
一起使用。特别是break/continue
这样的指令是不允许这样使用的。 (
i>
5``)
?
alert``(
i)
:
_continue_``;
// continue 不允许在这个位置
- 非表达式的语法结构不能与三元运算符
- break/continue 标签
JavaScript
labelName: for (...) {
...
}
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let input = prompt(`Value at coords (${i},${j})`, '');
// 如果是空字符串或被取消,则中断并跳出这两个循环。
if (!input) break outer; // (*)
// 用得到的值做些事……
}
}
alert('Done!');
1. 标签不允许我们跳到代码的任意位置。
2. `break` 指令必须在代码块内。
3. `continue` 只有在循环内部才可行。
switch 语句
switch
语句为多分支选择的情况提供了一个更具描述性的方式。
- 语法
switch
语句有至少一个case
代码块和一个可选的default
代码块
JavaScript
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default:
...
[break]
}
如果没有 break,程序将不经过任何检查就会继续执行下一个 case。
1. 任何表达式都可以成为 `switch/case` 的参数
- 类型很关键
- 被比较的值必须是相同的类型才能进行匹配。
函数
- 函数声明
JavaScript
function showMessage() {
alert( 'Hello everyone!' );
}
- 局部变量
- 在函数中声明的变量只在该函数内部可见。
- 外部变量
- 函数也可以访问外部变量
- 如果在函数内部声明了同名变量,那么函数会 遮蔽 外部变量
- 全局变量
- 任何函数之外声明的变量
- 减少全局变量的使用
- 参数
- 我们可以通过参数将任意数据传递给函数。
- 默认值
- 如果一个函数被调用,但有参数(argument)未被提供,那么相应的值就会变成
undefined
。 - 默认参数的计算
- 在传入参数的时候没有给值,就会调用方法的默认参数。如果传入了值,就不会调用默认值的计算
- 显式地检查
undefined
- 如果一个函数被调用,但有参数(argument)未被提供,那么相应的值就会变成
JavaScript
function showMessage(from, text) {
if (text === undefined) {
text = 'no text given';
}
alert( from + ": " + text );
}
//或者用||运算符
function showMessage(from, text) {
// 如果 text 的值为假值,则分配默认值
// 这样赋值 text == "" 与 text 无值相同
text = text || 'no text given';
...
}
- JavaScript 引擎支持 [空值合并运算符]
??
,它在大多数假值(例如0
)应该被视为“正常值”时更具优势,- alert(count ?? "unknown");
- 返回值
- 函数可以将一个值返回到调用代码中作为结果。
- 只使用
return
但没有返回值也是可行的。但这会导致函数立即退出。 - 空值的
return
或没有return
的函数返回值为undefined
- 空值的
return
和return undefined
等效 - 不要在
return
与返回值之间添加新行,return不换行
- 函数命名
- 简短且尽可能准确地描述函数的作用
- 函数 == 注释
- 函数应该简短且只有一个功能
函数表达式
在 JavaScript 中,函数不是“神奇的语言结构”,而是一种特殊的值。
- 函数声明:
function
关键字后面没有函数名。函数表达式允许省略函数名。
JavaScript
function sayHi() {
alert( "Hello" );
}
- 函数表达式:
JavaScript
let sayHi = function() {
alert( "Hello" );
};
- 函数是一个值
- 无论函数是如何创建的,函数都是一个值。
- 函数可以复制
- 一个函数a,现在let b = a,这是函数复制,let b = a ( ),这是把a函数的值复制给了b,而不是复制函数a
- 函数表达式末尾有分号,函数声明没有。是因为函数表达式是赋值语句
- 回调函数
JavaScript
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "You agreed." );
}
function showCancel() {
alert( "You canceled the execution." );
}
// 用法:函数 showOk 和 showCancel 被作为参数传入到 ask
ask("Do you agree?", showOk, showCancel);
ask 的两个参数值 showOk 和 showCancel 可以被称为 回调函数 或简称 回调。
更简洁的写法
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
//这两个函数没有名字,所以叫 匿名函数
1. 一个函数是表示一个“行为”的值
- 一个函数是表示一个“行为”的值
- 函数声明:在主代码流中声明为单独的语句的函数
- 函数表达式:在一个表达式中或另一个语法结构中创建的函数。下面这个函数是在赋值表达式
=
右侧创建的 - 函数表达式是在代码执行到达时被创建,并且仅从那一刻起可用。
- 在函数声明被定义之前,它就可以被调用。,在初始化的时候就会被创建
- 函数声明的另外一个特殊的功能是它们的块级作用域。
- 严格模式下,当一个函数声明在一个代码块内时,它在该代码块内的任何位置都是可见的。但在代码块外不可见。
- 什么时候选择函数声明与函数表达式?首先考虑函数声明语法
- 最好使用函数声明,因为函数在被声明之前也是可见的。这使我们在代码组织方面更具灵活性,通常也会使得代码可读性更高。
箭头函数,基础知识
JavaScript
如果没有参数,括号则是空的(但括号必须保留)
let sayHi = () => alert("Hello!");
let sum = (a, b) => { // 花括号表示开始一个多行函数
let result = a + b;
return result; // 如果我们使用了花括号,那么我们需要一个显式的 “return”
};
alert( sum(1, 2) ); // 3
JavaScript 特性
- 代码结构
- 分号分隔,或者换行也默认视为分隔符
- 严格模式
- 应该在脚本顶部写上
"use strict"
指
- 应该在脚本顶部写上
- 变量
- let:
- const (不变的,不能被改变)
var
(旧式的)
- 交互-模态框
- prompt(question[, default]),提出一个问题 question,并返回访问者输入的内容,如果他按下「取消」则返回 null。
- confirm(question)
- alert(message)
- 运算符
- 常规的:
+ - * /
(加减乘除),取余运算符%
和幂运算符**
。 - 赋值 =
- 按位运算符
- 三元运算符
- 逻辑运算符 || &&
- 空值合并运算符 ??
- 比较运算符 == ,除了
null
和undefined
,它们彼此相等而没有其他情况 ===
,严格相等运算符,不同的类型总是指不同的值。值null
和undefined
是特殊的:它们只在==
下相等,且不相等于其他任何值。
- 常规的:
- 循环
JavaScript
// 1
while (condition) {
...
}
// 2
do {
...
} while (condition);
// 3
for(let i = 0; i < 10; i++) {
...
}
- “switch” 结构
- 它内部使用
===
(严格相等)进行比较。
- 它内部使用
- 函数
- 函数声明
- 函数表达式 ,赋值
- 箭头函数