最近又再从头看廖雪峰的 JavaScript 教程,之前就看过,但是当时就只是走马观花的看看。
现在准备重新看一遍。因此就有了这篇读书笔记。把一些我认为的重要的地方摘录下来,巩固JavaScript知识。
快速入门
通常我们都把JavaScript代码放到<head>
中。
由<script>...</script>
包含的代码就是JavaScript代码,它将直接被浏览器执行。
第二种方法是把JavaScript代码放到一个单独的.js
文件,然后在HTML中通过<script src="..."></script>
引入这个文件。
把JavaScript代码放入一个单独的.js
文件中更利于维护代码,并且多个页面可以各自引用同一份.js
文件。
可以在同一个页面中引入多个.js
文件,还可以在页面中多次编写<script> js代码... </script>
,浏览器按照顺序依次执行。
strict模式
不用var
申明的变量会被视为全局变量,为了避免这一缺陷,所有的JavaScript代码都应该使用strict模式。
在strict模式下运行的JavaScript代码,强制通过var
申明变量,未使用var
申明变量就使用的,将导致运行错误。
启用strict模式的方法是在JavaScript代码的第一行写上:
|
|
语法
JavaScript每个语句以;
结束,语句块用{...}
注释
以//
开头直到行末的字符被视为行注释,注释是给开发人员看到,JavaScript引擎会自动忽略
另一种块注释是用/*...*/
把多行字符包裹起来,把一大“块”视为一个注释
大小写
请注意,JavaScript严格区分大小写,如果弄错了大小写,程序将报错或者运行不正常。
数据类型
Number
JavaScript不区分整数和浮点数,统一用Number表示。
|
|
字符串
字符串是以单引号’或双引号”括起来的任意文本。请注意,''
或""
本身只是一种表示方式,不是字符串的一部分。
如果字符串内部既包含'
又包含"
,可以用转义字符\
来标识,比如:
|
|
表示的字符串内容是:I'm "OK"!
转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
。
多行字符串
ES6标准新增了一种多行字符串的表示方法,用反引号 ` … ` 表示:
|
|
模板字符串
要把多个字符串连接起来,可以用+
号连接。
ES6新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:
|
|
操作字符串
特别注意,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果。
JavaScript为字符串提供了一些常用方法,注意,调用这些方法本身不会改变原有字符串的内容,而是返回一个新字符串:
toUpperCase() |
把一个字符串全部变为大写 |
---|---|
toLowerCase() |
把一个字符串全部变为小写 |
indexOf() |
搜索指定字符串出现的位置。 没有找到指定的子串,返回-1 |
substring() |
返回指定索引区间的子串 |
布尔值
布尔值和布尔代数的表示完全一致,一个布尔值只有true
、false
两种值。
比较运算符
当我们对Number做比较时,可以通过比较运算符得到一个布尔值。
要特别注意相等运算符==
。JavaScript在设计时,有两种比较运算符:
第一种是==
比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是===
比较,它不会自动转换数据类型,如果数据类型不一致,返回false
,如果一致,再比较。
由于JavaScript这个设计缺陷,不要使用==
比较,始终坚持使用===
比较。
另一个例外是NaN
这个特殊的Number与所有其他值都不相等,包括它自己:
|
|
唯一能判断NaN
的方法是通过isNaN()
函数:
|
|
最后要注意浮点数的相等比较:
|
|
浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值:
|
|
null和undefined
null
表示一个“空”的值,它和0
以及空字符串''
不同,0
是一个数值,''
表示长度为0的字符串,而null
表示“空”。undefined
,它表示“未定义”。
大多数情况下,我们都应该用null
。undefined
仅仅在判断函数参数是否传递的情况下有用。
数组
JavaScript的数组可以包括任意数据类型。数组用[]
表示,元素之间用,
分隔。
创建数组的方法是通过Array()
函数实现:
|
|
然而,出于代码的可读性考虑,强烈建议直接使用[]
。
数组的元素可以通过索引来访问。请注意,索引的起始值为0
。
要取得Array
的长度,直接访问length
属性,请注意,直接给Array
的length
赋一个新的值会导致Array
大小的变化。
请注意,如果通过索引赋值时,索引超过了范围,同样会引起Array
大小的变化。
不建议直接修改Array
的大小,访问索引时要确保索引不会越界。
方法
indexOf
与String类似,Array
也可以通过indexOf()
来搜索一个指定的元素的位置slice
slice()
就是对应String的substring()
版本,它截取Array
的部分元素,然后返回一个新的Array
。slice()
的起止参数包括开始索引,不包括结束索引。
如果不给slice()
传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个Array
push和pop
push()
向Array
的末尾添加若干元素,pop()
则把Array
的最后一个元素删除掉unshift和shift
如果要往Array
的头部添加若干元素,使用unshift()
方法,shift()
方法则把Array
的第一个元素删掉。sort
sort()
可以对当前Array
进行排序,它会直接修改当前Array
的元素位置,直接调用时,按照默认顺序排序。reverse
把整个Array
的元素给掉个个,也就是反转。splice
splice()
方法是修改Array
的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素。concat
concat()
方法把当前的Array
和另一个Array
连接起来,并返回一个新的Array
。
请注意,concat()
方法并没有修改当前Array
,而是返回了一个新的Array
。
实际上,concat()
方法可以接收任意个元素和Array
,并且自动把Array
拆开,然后全部添加到新的Array
里join
把当前Array
的每个元素都用指定的字符串连接起来,然后返回连接后的字符串,如果Array
的元素不是字符串,将自动转换为字符串后再连接。
对象
JavaScript的对象是一组由键-值组成的无序集合。JavaScript对象的键都是字符串类型,值可以是任意数据类型。每个键又称为对象的属性,要获取一个对象的属性,我们用对象变量.属性名
的方式。
JavaScript用一个{...}
表示一个对象,键值对以xxx: xxx
形式申明,用,
隔开。注意,最后一个键值对不需要在末尾加,
。
访问属性是通过.
操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用''
括起来:
|
|
xiaohong
的属性名middle-school
不是一个有效的变量,就需要用''
括起来。访问这个属性也无法使用.
操作符,必须用['xxx']
来访问:
|
|
JavaScript对象的所有属性都是字符串,不过属性对应的值可以是任意数据类型。
如果访问一个不存在的属性会返回什么呢?JavaScript规定,访问不存在的属性不报错,而是返回undefined
。
如果我们要检测是否拥有某一属性,可以用in
操作符。不过要小心,如果in
判断一个属性存在,这个属性可能是继承得到的。
要判断一个属性是否是自身拥有的,而不是继承得到的,可以用hasOwnProperty()
方法。
变量
变量名是大小写英文、数字、$
和_
的组合,且不能用数字开头。变量名也不能是JavaScript的关键字,如if
、while
等。申明一个变量用var
语句。
条件判断
JavaScript使用if () { ... } else { ... }
来进行条件判断。
请注意,if...else...
语句的执行特点是二选一,在多个if...else...
语句中,如果某个条件成立,则后续就不再继续判断了。
JavaScript把null
、undefined
、0
、NaN
和空字符串''
视为false
,其他值一概视为true
。
循环
JavaScript的循环有两种,一种是for
循环,通过初始条件、结束条件和递增条件来循环执行语句块。
for … in
for循环的一个变体是for … in循环,它可以把一个对象的所有属性依次循环出。
由于Array
也是对象,而它的每个元素的索引被视为对象的属性,因此,for ... in
循环可以直接循环出Array
的索引。
请注意,for ... in
对Array
的循环得到的是String
而不是Number
。
while
while
循环只有一个判断条件,条件满足,就不断循环,条件不满足时则退出循环。
do … while
它和while
循环的唯一区别在于,不是在每次循环开始的时候判断条件,而是在每次循环完成的时候判断条件。
用do { ... } while()
循环要小心,循环体会至少执行1次,而for
和while
循环则可能一次都不执行。
Map和Set
Map
和Set
是ES6标准新增的数据类型。
Map
Map
是一组键值对的结构,具有极快的查找速度。
初始化Map
需要一个二维数组,或者直接初始化一个空Map
。Map
具有以下方法:
|
|
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉。
Set
Set
和Map
类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set
中,没有重复的key。
要创建一个Set
,需要提供一个Array
作为输入,或者直接创建一个空Set
。重复元素在Set
中自动被过滤。
通过add(key)
方法可以添加元素到Set
中,可以重复添加,但不会有效果。
通过delete(key)
方法可以删除元素。
iterable
遍历Array
可以采用下标循环,遍历Map
和Set
就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable
类型的集合可以通过新的for ... of
循环来遍历。
使用iterable
内置的forEach
方法,它接收一个函数,每次迭代就自动回调该函数。