1 基础
约 2010 个字 102 行代码 预计阅读时间 8 分钟
Intro
JavaScript & ECMAScript
一般情况下我们认为两者等价
ECMAScript
是一个标准,需要各个浏览器厂商进行实现JavaScript
>ECMAScript
,其完整实现囊括了ECMAScript
,DOM
andBOM
.
- JavaScript 的特点
- 解释型语言
- 类似于 C & Java 的语法结构
- 动态语言
- 基于原型的面向对象
- JavaScript 的编写位置
- HTML 文件的
<script>
标签中 - 外部文件中,并通过
<script>
标签引入- 可以被不同文件引用,利用浏览器的缓存机制加快加载过程
- 用于引入外部文件的
<script>
标签内书写的内容会被忽略(禁止吃里扒外)
- HTML 文件的
- 基本规则
- 严格区分大小写
- 每一条语句以
;
结尾,不手写浏览器会自动添加(也可能加错) - 忽略多个空格和换行
1 字面量 & 变量
-
字面量
一些不可改变的值(如
1
/1000
),可以直接使用(但一般不直接用) -
变量
可以用于保存字面量,其值可以任意改变;
简单的变量声明:
var a
,此时我们尚未赋值,a = undefined
标识符命名规则
在 JS 中,所有支持自主命名的都称为“标识符”(如 变量名 / 函数名 / 属性名),需要满足以下规则:
- 可以包含:字母、数字、下划线、$
- 不能以数字开头
- 不能是 ES 中的 关键字 / 保留字
- 建议使用小驼峰命名法
JS 底层使用 Unicode
编码保存标识符,理论上支持 utf-8
中的所有内容(比如中文)
使用
XXXX
表示Unicode
字符的十进制编号:
JS 中使用
\uXXXX
输出HTML 中使用
&#XXXX
输出
1.1 基本数据类型
JS 中共包含六种数据类型:
- 基本数据类型:
String
,Number
,Boolean
,Null
,Undefined
- 引用数据类型:
Object
我们可以使用
typeof varName
简单检查变量的类型。
String
- 需要使用引号包裹(单双都行,但不要混用)
- 引号不能嵌套(可以大肠包小肠,但是自产自销时需要用
\
进行转义) - 特殊符号也需要使用
\
进行转义
Number
整数计算精度有保障,但是浮点数就 emmm ...
- JS 中的所有数值都属于 Number 型(整数 & 浮点数)
-
最值与无穷
- 最大值
Number.MAX_VALUE
= \(1.7976931348623157*10^{308}\),超过这个值将返回Infinity
- 最小值是最大值的相反数,超过则返回
-Infinity
Number.MIN_VALUE
= \(0.5*10^{323}\) 表示支持的最小正值
Infinity
是一个类型为 Number 的字面量,我们可以通过var a = Infinity
进行赋值 - 最大值
-
NaN
表示 Not a Number,是一个 Number 型的字面量
Boolean
true
or false
Null
只有 null
值,表示 空对象,使用 typeof
返回 Object
Undefined
只有 undefined
值,表示 未定义(声明但没赋值)
1.2 强制类型转换
转 String
关于 toString
方法
toString
方法不会改变原变量的类型,而是返回一个 String 型的执行结果Null
&Undefined
类型没有toString
方法,调用时会报错
- 调用被转换数据类型的
toString
方法 - 调用
String
函数- 对于 Number / Boolean 类型,直接调用
toString
方法 - 对于 Null / Undefined 类型,直接转为字符串
- 对于 Number / Boolean 类型,直接调用
转 Number
-
使用
Number
函数Type Result 存在非数字内容 NaN
空串 / 纯空格 0 true
1 false
0 null
0 undefined
NaN
-
使用
parseInt / parseFloat
函数(String 类型专用)-
提取从头开始匹配的最长连续字串
parseInt("123px456") => 123
parseFloat("123.456.789") => 123.456
-
对「非 String 类型」调用会先转换为 String,再进行对应转换。
parseInt(true) => parseInt("true") => NaN
- 甚至可以悄悄取整
parseInt(198.23) => parseInt("198.23") => 198
-
进制转换
-
非十进制的表示
进制 前缀 示例 16 0x
0x12f
8 0
070
2 0b
0b1010
console.log()
均以十进制输出结果- 不是所有浏览器都支持以
0bxxx
表示二进制数
-
指定进制解析
- 场景:
parseInt("070")
视浏览器可能被解析为 \(56_o\) 或 \(70_d\) - 解决:传入第二个参数指定进制
parseInt("070", 8) === 56
- 场景:
转 Boolean
使用 Boolean
函数,转换规则如下:
Input | Result |
---|---|
一般数字 | true |
0 | false |
NaN |
false |
一般字符串 / 纯空格 | true |
空串 | false |
null |
false |
undefined |
false |
Object |
true |
1.3 包装类
用于将「基本数据类型」转换为「对象」
-
JS 中存在三个包装类
String()
,Number()
,Boolean()
var num = new Number(3); // typeof num 返回 Object(而非 Number) // 注意:实际开发时不会使用(比较结果不符合预期) var n1 = 3; var n2 = 3; n1 == n2; // => true var n3 = Number(3); var n4 = Number(3); n3 == n4; // => false 对象地址不同 // 以及 Boolean 对象作为条件 var b = new Boolean(false); if(b) console.log("ok"); // 会输出 ok(Object 转 Boolean 为 true)
-
我们可以为包装类对象添加属性
-
当我们试图调用「基本数据类型」的 属性/方法 时,浏览器会临时使用包装类将其转换为对象
1.4 String 对象方法
包装类的存在使得我们可以直接使用 String 对象的方法
-
String 在底层是以「字符数组」的形式保存的
- 可以通过
str.length
获取字符串长度 - 可以通过
str[idx]
获取指定位置上的 char
- 可以通过
-
下面是一些方法
方法 描述 charAt(idx)
返回 str[idx]
charCodeAt(idx)
返回 str[idx]
的 Unicode 编码fromCharCode(charCode)
从字符编码创建一个字符串 concat(str1, str2, ...)
拼接多个字符串 indexOf("str", start)
返回从 start
开始首次出现该子串的起始下标,不存在时返回 -1lastIndexOf("str")
返回最后一次出现该子串的起始下标,不存在时返回 -1 slice(start, end)
返回 str[start, end)
子串,不影响原串(允许传入负数)subString(start, end)
和 slice 类似(不允许传入负数,且 p2<p1 时自动交换) subStr(start, len)
不太建议使用 split("指定分隔符")
将 String 拆分为 Array (不指定/指定空串会逐个拆开) toLowerCase()/toUpperCase()
大小写转换
2 基本运算
2.1 运算符
-
类型运算符
typeof
将值的类型以 String 形式返回
-
算数运算符(二元)
-
+
(左结合)-
String + 任意类型,将“任意类型值”转换为 String,随后进行
concat
我们可以使用
var + ''
将任意数据类型转为 String(隐式类型转换,由浏览器自动调用toString
函数) -
Number + 任意非String类型,会对非 Number 的值进行转换后运算
- 任何值与
NaN
运算均返回NaN
-
*
/
会把两侧的数据均转换为 Number
可以使用
var -0 / *1 / /1
将任意数据类型专为 Number -
-
%
朴素的取模
-
-
一元运算符
+
-
正负号,会将非 Number 转为 Number++
--
自增自减++a
先递增再返回结果a++
先返回结果再递增
-
逻辑运算符: 非 Boolean 类型会先进行转换
-
!
非可以使用
!!var
快速将变量转为 Boolean -
&&
与- 第一个条件失败后,不会执行第二个条件
True && Ture
,返回后面的 True 结果- 存在 False 时,返回首个 False 结果
||
或- 第一个条件成功后,不会执行第二个条件
Ture || ?
,返回首个 Ture 结果False || ?
,返回第二个结果
-
-
赋值运算符
=
+=
-=
*=
/=
%=
-
关系运算符
>
>=
<
<=
- 会将非 Number 转换为 Number,返回 Boolean
- 符号两侧均为 String 时,直接逐位比较 Unicode 编码
- 任何值与
NaN
比较均返回false
-
相等运算符
-
==
会自动将两侧转为相同类型进行比较(大部分情况下转 Number)-
undefined == null -> true
-
NaN == Anything -> false
(包括NaN == NaN
,需要用isNaN
函数判断)
-
-
===
全等(不会做类型转换,类型不同直接false
) !=
不等,!==
不全等
-
-
条件运算符(三元)
condition?case1:case2
当 condition 的结果非 Boolean 类型时会进行转换
2.2 优先级
序号越大优先级越低,平级时左结合
.
[]
new
()
++
--
!
~
+/- 符号
typeof
void
delete
%
*
/
+/- 加减法
<<
>>
>>>
<
<=
>
>=
==
!=
===
!==
&
^
|
&&
||
?:
=
+=
-=
/=
*=
%=
<<=
>>=
>>>=
&=
^=
|=
3 语句
获取用户输入
您可以使用 prompt("提示语句")
弹出弹窗以获得用户输入:
-
IF 多分支模版
-
Switch 模版
-
While 模版
-
For 模版
- 执行顺序:初始化 -> 判断条件 -> 循环体 -> 更新
- 初始化/条件/更新都可以 省略 or 写在外面(要留
;
)
-
break & continue
- break 可用于退出最近的一层 switch / 循环语句(不能用于 IF)
- continue 可以用于逃过当次循环的余下部分(作用于最近的循环)
使用 Label
标识循环语句
我们可以通过 labelName:循环语句
的形式进行标识
4 作用域 Scope
变量作用的范围
-
JS 共有两种作用域
-
全局作用域
- 页面打开时创建,关闭时销毁
- 不被函数包裹的代码均在全局作用域中
-
具有代表浏览器窗口的全局对象
window
,可以直接使用在全局作用域中创建的变量都会作为「window 的属性」保存,可以在任意位置访问
在全局作用域中创建的函数都会作为「window 的方法」保存
-
变量的声明提前
使用
var
声明的变量将在「所有代码执行前」被定义(但没有赋值!) -
函数的声明提前
以「声明」形式创建的函数会在所有代码执行前被创造(可以在声明前调用)
-
函数作用域
- 调用函数时创建,执行完毕后销毁(每调用一次就会创建一个独立的作用域)
- 可以访问全局变量,但是全局作用域不能访问函数作用域中变量(
var
定义) -
局部变量与全局变量同名时,优先使用局部变量(可以用
window.name
强行指定)本地不存在时,逐层向上一级查找(直至全局作用域,还是没有报
ReferenceError
) -
也存在「声明提前」
var a = 123; function f() { console.log(a); // 输出 undefined -> 局部声明提前 var a = 234; a = 345; // 就是全局变量(没有提升),上面输出 123(全局值) b = 567; // 没有使用 var 关键字 => 定义了变量 b subF(); // 函数声明提前,正常调用 function subF() {console.log("subF")}; } console.log(a); // 若没有 var => c 就是全局变量,输出 345 console.log(b); // 正常输出 567(在函数中定义了全局变量) // 参数列表相当于 var params; var e = 111; function f2(e) { // 等同于 var e console.log(e); // => undefined e = 222; // => 修改的是局部变量 }
-
5 垃圾回收 GC
- 「垃圾」
- 当一个对象没有任何变量或属性对其进行引用时,我们将永远无法对其进行操作
- 「垃圾」会占用大量内存空间,导致程序运行速度变慢
-
JS 的「垃圾回收机制」
JS 会「自动」将垃圾从内存中销毁(不允许进行手动操作)
但是我们不手动将不再使用的变量指向
null
,JS 将无法进行识别