本文是阅读现代JavaScript 教程的个人笔记(其实只是看不下去博客太容易分心所以边复制边学习),详情请见网址https://zh.javascript.info/。
JavaScript 基础知识1
一、hello world
“script” 标签
使用<script>
标签将 JavaScript 程序插入到 HTML 文档的任何位置。
<script>
标签中包裹了 JavaScript 代码,当浏览器遇到 <script>
标签,代码会自动运行。
不再使用的特性
1、在老的 HTML4 标准中,要求 script 标签有 type 特性。通常是 type="text/javascript"
。这样的特性声明现在已经不再需要。
2、language 特性:<script language=…>
这个特性是为了显示脚本使用的语言。这个特性现在已经没有任何意义,因为语言默认就是 JavaScript。
3、脚本前后的注释。
<script type="text/javascript"><!--
...
//-->
</script>
现代 JavaScript 中已经不这样使用了。这些注释是用于不支持
外部脚本
如果有大量的 JavaScript 代码,可以将它放入一个单独的文件。脚本文件可以通过 src 特性(attribute)添加到 HTML 文件中。<script src="/path/to/script.js"></script>
绝对路径:/path/to/script.js 是脚本文件从网站根目录开始的绝对路径。
相对路径: 例如,src =“script.js”,就像 src=“./script.js”,表示当前文件夹中的 “script.js” 文件。
要附加多个脚本,使用多个标签:
<script src="/js/script1.js"></script>
<script src="/js/script2.js"></script>
使用独立文件的好处是浏览器会下载它,然后将它保存到浏览器的 缓存 中。之后,其他页面想要相同的脚本就会从缓存中获取,而不是下载它。所以文件实际上只会下载一次。这可以节省流量,并使得页面(加载)更快。
如果设置了 src 特性,script 标签内容将会被忽略。
<script src="file.js">
alert(1); // 此内容会被忽略,因为设定了 src
</script>
练习:显示一个提示语
<!DOCTYPE html>
<html>
<body>
<script>
alert("I'm JavaScript!");
</script>
</body>
</html>
二、代码结构
分号
当存在换行符(line break)时,在大多数情况下可以省略分号。
但存在 JavaScript 无法确定是否真的需要自动插入分号的情况。
最好不要省略
注释
单行注释以两个正斜杠字符 // 开始。
多行注释 /*多行注释*/
不支持注释嵌套!
三、“use strict”
2009 年 ECMAScript 5 (ES5) 的出现,增加了新的语言特性并且修改了一些已经存在的特性。为了保证旧的功能能够使用,大部分的修改是默认不生效的。你需要一个特殊的指令 —— “use strict” 来明确地激活这些特性。
当 “use strict” 处于脚本文件的顶部时,则整个脚本文件都将以“现代”模式进行工作。
"use strict";
// 代码以现代模式工作
...
注意事项
“use strict” 可以被放在函数体的开头。这样则可以只在该函数中启用严格模式。但通常人们会在整个脚本中启用严格模式。
- 请确保 “use strict” 出现在脚本的最顶部,否则严格模式可能无法启用。只有注释可以出现在 “use strict” 的上面。
- 没有办法取消 use strict。没有类似于 “no use strict” 这样的指令可以使程序返回默认模式。
- 当你使用 开发者控制台 运行代码时,请注意它默认是不启动 use strict 的。(解决方法见https://zh.javascript.info/strict-mode)
现代 JavaScript 支持 “class” 和 “module” —— 高级语言结构(本教程后续章节会讲到),它们会自动启用 use strict。因此,如果我们使用它们,则无需添加 “use strict” 指令。
四、变量
let message = "hello world";
alert(message);
变量声明的三种方式 ① let ② const ③ var
let
变量命名有两个限制:
① 变量名称必须仅包含字母、数字、符号 $ 和 _。
② 首字符必须非数字。
- 区分大小写
- 允许非英文字母,但不推荐
- 保留字:保留字无法用作变量命名,因为它们被用于编程语言本身了,如 let
const
声明一个常数(不变)变量,可以使用 const 而非 let。
大写形式的常数:在执行之前就已知了(比如红色的十六进制值)
var
var message = "Hi";
alert(message); // Hi
注意事项
var是较老的版本
1、var 声明的变量只有函数作用域和全局作用域,没有块级作用域(if for等)
2、“var” 允许重新声明
//对于let是错的
let user;
let user; // SyntaxError: 'user' has already been declared
//对于var是对的
var user = "Pete";
var user = "John"; // 这个 "var" 无效(因为变量已经声明过了)
// ……不会触发错误
3、“var” 声明的变量,可以在其声明语句前被使用
① var 声明的变量会在函数开头被定义,与它在代码中定义的位置无关(这里不考虑定义在嵌套函数中的情况)
人们将这种行为称为“提升”(英文为 “hoisting” 或 “raising”),因为所有的 var 都被“提升”到了函数的顶部。
② 声明会被提升,但是赋值不会。
③ 立即调用函数表达式(immediately-invoked function expressions,IIFE)。
五、数据类型
在 JavaScript 中有 8 种基本的数据类型(译注:7 种原始类型和 1 种引用类型)。
动态类型(dynamically typed)的编程语言
意思是虽然编程语言中有不同的数据类型,但是你定义的变量并不会在定义后,被限制为某一数据类型。
// 没有错误
let message = "hello";
message = 123456;
- Number 类型
number 类型代表整数和浮点数。 范围是 -253-1 到 +253-1
除了常规的数字,还包括所谓的“特殊数值(“special numeric values”)”也属于这种类型:Infinity、-Infinity 和 NaN。 - BigInt 类型
表示任意长度的整数
// 尾部的 "n" 表示这是一个 BigInt 类型
const bigInt = 1234567890123456789012345678901234567890n;
- String 类型
在 JavaScript 中,有三种包含字符串的方式。
① 双引号:"Hello"
② 单引号:'Hello'
③ 反引号:`Hello`
双引号和单引号都是“简单”引用,在 JavaScript 中两者几乎没有什么差别。
反引号是 功能扩展 引号。它们允许我们通过将变量和表达式包装在 ${…} 中,来将它们嵌入到字符串中。
- Boolean 类型(逻辑类型)
- null 值
相比较于其他编程语言,JavaScript 中的 null 不是一个“对不存在的 object 的引用”或者 “null 指针”。
JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值。 - undefined 值
特殊值 undefined 和 null 一样自成类型。
undefined 的含义是 未被赋值。 - Symbol 类型 用于唯一的标识符。
- Object 类型
其他所有的数据类型都被称为“原始类型”,因为它们的值只包含一个单独的内容(字符串、数字或者其他)。相反,object 则用于储存数据集合和更复杂的实体。
typeof 运算符返回参数的类型。
六、交互:alert、prompt 和 confirm
这些方法都是模态的:它们暂停脚本的执行,并且不允许用户与该页面的其余部分进行交互,直到窗口被解除。
上述所有方法共有两个限制:
①模态窗口的确切位置由浏览器决定。通常在页面中心。
②窗口的确切外观也取决于浏览器。我们不能修改它。
七、类型转换
- 转换为字符串 String(变量)
let value = true; // boolean
value = String(value); // string
- 转换为数字型 Number(变量)
在算术函数和表达式中,会自动进行 number 类型转换。
let str = "123"; // string
let num = Number(str); // 变成 number 类型 123
number 类型转换规则:
undefined -> NaN
null -> 0
true 和 false -> 1 and 0
string -> 去掉首尾空白字符(空格、换行符 \n、制表符 \t 等)后的纯数字字符串中含有的数字。
如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。
- 转换为布尔型
转换规则如下:
直观上为“空”的值(如 0、空字符串、null、undefined 和 NaN)将变为 false。
其他值变成 true。
八、基础运算符,数学运算
1、数学运算
- 加法 +
- 减法 -
- 乘法 *
- 除法 /
- 取余 %
- 求幂 **
2、用二元运算符 + 连接字符串
加号 + 被应用于字符串,它将合并(连接)各个字符串:
let s = "my" + "string";
alert(s); // mystring
注意:只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串。
3、一元运算符
如果运算元不是数字,加号 + 则会将其转化为数字。对数字没用。
// 转化非数字
alert( +true ); // 1
alert( +"" ); // 0
let apples = "2";
let oranges = "3";
// 在二元运算符加号起作用之前,所有的值都被转化为了数字
alert( +apples + +oranges ); // 5
// 更长的写法
// alert( Number(apples) + Number(oranges) ); // 5
用在数字前,-表示取负数
let x = 1;
x = -x;
alert( x ); // -1,一元负号运算符生效
4、赋值运算符
链式赋值(Chaining assignments)
5、自增/自减
自增/自减只能应用于变量。试一下,将其应用于数值(比如 5++)则会报错。
6、位运算符
按位与 ( & )
按位或 ( | )
按位异或 ( ^ )
按位非 ( ~ )
左移 ( << )
右移 ( >> )
无符号右移 ( >>> )
7、逗号运算符
逗号运算符 , 是最少见最不常使用的运算符之一。逗号运算符能让我们处理多个表达式,使用 , 将它们分开。每个表达式都运行了,但是只有最后一个的结果会被返回。
let a = (1 + 2, 3 + 4);
alert( a ); // 7(3 + 4 的结果)
练习
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
我的答案:
10 错 应该是 “10”
-1 (1)注释
1
2
6
9px 错 应该是 “9px”
$45 错 应该是 “$45”
2
NAN
-95 错 应该是 " -9 5" 中间有空格
-14
1
1 错,是NaN (2)注释
NAN 错,是-2 (3)注释
(1)减法 -(像大多数数学运算一样)只能用于数字,它会使空字符串 “” 转换为 0。
(2)undefined 经过数字转换之后会变为 NaN。null 经过数字转换之后会变为 0。
(3)字符串转换为数字时,会忽略字符串的首尾处的空格字符。在这里,整个字符串由空格字符组成,包括 \t、\n 以及它们之间的“常规”空格。因此,类似于空字符串,所以会变为 0。
九、值的比较
比较结果为 Boolean 类型
所有比较运算符均返回布尔值。
字符串比较
非真正的字典顺序,而是 Unicode 编码顺序
在 JavaScript 使用的内部编码表中(Unicode),小写字母的字符索引值更大。
不同类型间的比较
当对不同类型的值进行比较时,JavaScript 会首先将其转化为数字(number)再判定大小。
严格相等
在比较不同类型的值时,处于相等判断符号 == 两侧的值会先被转化为数字。
所以无法比较 空字符串和 false、 0 和 false。
严格相等运算符 === 在进行比较时不会做任何的类型转换。严格不相等”表示为 !==。
undefined、null、比较时候的奇怪点