JavaScript 基础语法
1. 变量
- JavaScript 的变量名区分大小写,
A
和a
是两个不同的变量。 - 如果只是声明变量而没有赋值,则该变量的值是
undefined
。undefined
是一个特殊的值,表示“无定义”。 - JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。
- 如果使用
var
重新声明一个已经存在的变量,是无效的。(如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值。) - 变量提升:JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
2. 注释
- JavaScript 提供两种注释的写法:一种是单行注释,用
//
起头;另一种是多行注释,放在/*
和*/
之间。 - 此外,由于历史上 JavaScript 可以兼容 HTML 代码的注释,所以
<!--
和-->
也被视为合法的单行注释。(需要注意的是,-->
只有在行首,才会被当成单行注释,否则会当作正常的运算。)
3. 数据类型
- 数值(number):整数和小数(比如 1 和 3.14)。
- 字符串(string):文本(比如 Hello World)。
- 布尔值(boolean):表示真伪的两个特殊值,即
true
(真)和false
(假)。 - undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值。
- null:表示空值,即此处的值为空。
- 对象(object):各种值组成的集合。
- 狭义的对象(object)
- 数组(array)
- 函数(function)
3.1 typeof 运算符
JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof
运算符instanceof
运算符Object.prototype.toString
方法
typeof 运算符可以返回一个值的数据类型。
数值、字符串、布尔值分别返回 number、string、boolean。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
function f() {}
typeof f
// "function"
typeof undefined
// "undefined"
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
- 空数组([])的类型也是 object
- instanceof 运算符可以区分数组和对象。
- null 的类型是 object,这是由于历史原因造成的。
3.2 null 和 undefined
null
与undefined
都可以表示“没有”,含义非常相似。将一个变量赋值为undefined
或null
,老实说,语法效果几乎没区别。- 在
if 语句
中,它们都会被自动转为false
,相等运算符(==
)甚至直接报告两者相等。 - 区别是这样的:
null
是一个表示“空”的对象,转为数值时为 0;undefined
是一个表示“此处无定义”的原始值,转为数值时为NaN
。 - 判断:使用
===
进行判断。
// 变量声明了,但没有赋值
var i;
i // undefined
// 调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
return x;
}
f() // undefined
// 对象没有赋值的属性
var o = new Object();
o.p // undefined
// 函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined
3.3 布尔值
如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false
,其它值都视为true
。
undefined
null
false
0
NaN
"" // 空字符串
'' // 空字符串
- 注意,空数组(
[]
)和空对象({}
)对应的布尔值,都是true
。 - 判断:使用
===
进行判断;if (x === true) {}
3.4 整数和浮点数
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相同的,是同一个数。
1 === 1.0 // true
0.1 + 0.2 === 0.3
// false
0.3 / 0.1
// 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1)
// false
3.5 数值精度
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,0表示正数,1表示负数
- 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。
精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-253到253,都可以精确表示。
3.6 数值范围
- 如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回
Infinity
。 - 如果一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”,即 JavaScript 无法表示这么小的数,这时会直接返回0。
3.7 NaN
5 - 'x' // NaN
0 / 0 // NaN
typeof NaN // 'number'
NaN === NaN // false
NaN
是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。
- 0 除以 0 也会得到 NaN
- 它的数据类型依然属于 Number
- NaN 不等于任何值,包括它本身
- NaN 在布尔运算时被当作false
- NaN 与任何数(包括它自己)的运算,得到的都是 NaN
3.8 Infinity
Infinity
有正负之分,Infinity
表示正的无穷,-Infinity
表示负的无穷。
// 场景一
Math.pow(2, 1024)
// Infinity
// 场景二
0 / 0 // NaN
1 / 0 // Infinity
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
Infinity > 1000 // true
-Infinity < -1000 // true
Infinity > NaN // false
-Infinity > NaN // false
Infinity < NaN // false
-Infinity < NaN // false
- Infinity 大于一切数值(除了 NaN),-Infinity 小于一切数值(除了 NaN)。
- Infinity 与 NaN 比较,总是返回 false
3.9 与数值相关的全局方法
- parseInt() 用于将字符串转为整数。还可以用于进制转换。
- parseFloat() 用于将一个字符串转为浮点数。
- isNaN() 用来判断一个值是否为 NaN。
- isFinite() 返回一个布尔值,表示某个值是否为正常的数值。
3.10 字符串
字符串可以包含在单引号、双引号或反引号中。
- 由于 HTML 语言的属性值使用双引号,所以很多项目约定 JavaScript 语言的字符串只使用单引号
- 连接运算符(+)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行
- 字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字符(位置编号从0开始)
- length 属性返回字符串的长度,该属性也是无法改变的。比如:
s.length
- es6 新增模板字符串,在反引号
``
内书写,需要拼接的内容用$()
包裹
3.11 Base64 转码
JavaScript 原生提供两个 Base64 相关的方法。
- btoa():任意值转为 Base64 编码
- atob():Base64 编码转为原来的值
要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法。
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
3.12 数组
- 索引/下标从 0 开始
- 数组的深拷贝建议使用
JSON.stringify
和JSON.parse
jsconst arr2 = JSON.parse(JSON.stringify(arr1));
- 数组的遍历:点击查看详情
forEach 方法
for 语句
for...of 语句
3.13 对象
对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型。 简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。
- 对象的所有键名都是字符串(ES6 又引入了 Symbol 值也可以作为键名),所以加不加引号都可以。
- 如果键名是数值,会被自动转为字符串。
- 对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型。可以是函数
- 读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。
- 点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。
- 查看一个对象本身的所有属性,可以使用Object.keys方法。
Object.keys(obj)
; - 属性的删除:delete 命令
delete obj.p // true
- 注意,删除一个不存在的属性,delete 不报错,而且返回 true。
- 属性是否存在:in 运算符
if ('toString' in obj) {}
- in运算符的一个问题是,它不能识别哪些属性是对象自身的,哪些属性是继承的。
- 可以使用对象的
hasOwnProperty
方法判断一下,是否为对象自身的属性。
- 属性的遍历:for...in 循环
for (var p in obj) {}
4. 运算
4.1 算术运算符
加 +
减 -
乘 *
除 /
取余 %
自增 ++
自减 --
4.2 赋值运算符
=
+=
-=
*=
/=
%=
4.3 比较运算符
等于 ==
不等于 !=
大于 >
小于 <
大于等于 >=
小于等于 <=
绝对等于 ===
值和类型均相等不绝对等于 !==
值和类型有一个不相等,或两个都不相等
4.4 逻辑运算符
与 &&
或 ||
非 !
5. 条件语句
JavaScript 提供if
结构和switch
结构,完成条件判断,即只有满足预设的条件,才会执行相应的语句。
5.1 if 语句
if (m === 3) {
m += 1;
}
if (m === 0) {
// ...
} else if (m === 1) {
// ...
} else if (m === 2) {
// ...
} else {
// ...
}
5.2 switch 语句
switch (fruit) {
case "banana":
// ...
break;
case "apple":
// ...
break;
default:
// ...
}
- 每个
case 代码块
内部的break语句
不能少,否则会接下去执行下一个 case 代码块,而不是跳出 switch 结构。 - switch 语句后面的表达式,与 case 语句后面的表示式比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换。
5.3 三元运算符 ?:
// (条件) ? 表达式1 : 表达式2
var even = (n % 2 === 0) ? true : false;
6. 循环语句
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Loops_and_iteration
循环语句用于重复执行某个操作,它有多种形式。
6.1 while 循环
while (条件) {
语句;
}
var i = 0;
while (i < 100) {
console.log('i 当前为:' + i);
i = i + 1;
}
- while 语句的循环条件是一个表达式,必须放在圆括号中。
6.2 for 循环
for (初始化表达式; 条件; 递增表达式) {
语句
}
var x = 3;
for (var i = 0; i < x; i++) {
console.log(i);
}
- for 语句的三个部分(initialize、test、increment),可以省略任何一个,也可以全部省略。
6.3 do...while 循环
do {
语句
} while (条件);
var x = 3;
var i = 0;
do {
console.log(i);
i++;
} while(i < x);
- 不管条件是否为真,
do...while
循环至少运行一次,这是这种结构最大的特点。 - 另外,while 语句后面的分号注意不要省略。
6.4 break 语句和 continue 语句
break
语句用于跳出代码块或循环。continue
语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。
6.5 for...in 语句
for...in
语句循环一个指定的变量来循环一个对象所有可枚举的属性。
let arr = ['a', 'b', 'c']
let obj = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
for (let i in arr) {
console.log(i) // 数组遍历的是下标:0 1 2
}
for (let i in obj) {
console.log(i) // 对象遍历的是它的 key:k1 k2 k3
}
- 最好不用
for...in
语句来遍历数组,因为它会遍历除了数字索引外,还有可能遍历你自定义的属性名字。
6.6 for...of 语句
for...of
语句用于遍历可迭代对象(不包含 object 类型)的值。
let arr = ['a', 'b', 'c']
let obj = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
for (let i of arr) {
console.log(i) // a b c
}
for (let i of obj) {
console.log(i) // 报错:TypeError: obj is not iterable
}
7. 函数
function test()
{
// 执行代码
}