1、JavaScript 简介
JavaScript是什么?
JavaScript是一种运行在客户端的解释性脚本语言,能够实现HTML网页丰富的动态交互效果。
ECMAScript
为了让JavaScript成为全球标准,几个公司联合ECMA(European Computer Manufacturers Association)组织定制了JavaScript语言的标准,被称为ECMAScript标准。
ECMAScript 是 JavaScript 语言的规范标准,JavaScript 是 ECMAScript 的一种实现。不过,在大多数情况下,这两个词在语境上是可以互换的。
JavaScript的组成
JavaScript是由 ECMAScript、DOM 以及 BOM 三者组成。
ECMAScript:语言核心部分
DOM: Document Object Model,文档对象模型,DOM是专门操作网页内容的API标准
BOM:Browser Object Model,浏览器对象模型,对客户端和浏览器窗口进行访问和操作
2、JavaScript 的基本语法
JavaScript书写位置
-
可以写在html文档中的
标签中,例如:
-
也可以单独写在外部的js文件中,通过
标签进行引入,例如:
注释的使用
js的注释有两种:单行注释(// ...... )和多行注释(/* ...... */)
简单的输入、输出函数
alert() 语句
在浏览器中弹出警示框,内容自定义,js内置方法
prompt() 语句
在浏览器中弹出一个提示对话框,对话框中有一个提示信息 以及 一个输入框,输入框中可根据提示信息输入合理内容。
prompt() 是 js内置方法,有两个参数,都是字符串类型,第一个参数是设置 提示对话框的提示信息,第二个参数是 输入框中的默认初始内容,该参数可以省略不写
console对象
浏览器控制台中进行js语句的执行操作,其中console.log()能够将内容在控制台中打印输出
字面量的概念
用于表达一个固定值(比如数字、字符串、布尔类型、undefined等的字面值)的表示法。 通俗的理解,字面就是所见即所得,js执行代码中的字面量,会立即知道它是什么类型的数据,值为多少。
变量
变量,是计算机内存中存储数据的标识符。使用变量,能够方便地获取和修改内存中的数据。
声明变量
通过var关键字定义变量,var之后需要添加空格,再自定义一个变量名,例如:var num;
命名规则
允许使用字母、数字、下划线、$符号,不能以数字开头
字母区分大小写
不能使用 保留字 和 关键字
命名规范
见名知意
建议使用 驼峰命名:多个单词组成时,第一个单词的首字母小写,之后的每个单词首字母大写,如:backgroundColor、listStyleType
变量赋值
将等号右边的数据,保存到等号左边的变量中
变量名 = 值
在声明变量的同时,可以初始化变量的值,如:var num = 0;
使用变量的特殊情况
- 当只声明了变量,但没赋值,在使用时,默认值为undefined
- 不能使用从未声明的变量,在使用时,会报错,ReferenceError:XXX is not defined
- 从未声明的变量,能够赋值,此时变量为全局变量(与var定义的变量还是存在区别的)
因此,在使用变量之前,必须先声明变量
3、JavaScript的数据类型
基本数据类型: Number、String、Boolean、undefined、null
复杂数据类型: Object
Number,数字类型
表示所有数字,整数、浮点数、特殊值NaN。凡是不加引号的数字,都是Number类型数据。
整数
整数可以被表示成十进制、八进制以及十六进制
十进制:最基本的数值字面量格式
八进制:数值前缀必须为 0、0O、0o,八进制整数只能包括数字0~7,如:045、0O45、0o45
十六进制:前缀为0x或者0X。后面可以包含数字0~9和字母a ~ f或者A ~ F,如:0x45a、0X45A
1、八进制中的特殊情况: 在八进制中,如果以 0 开头,每个 位数 上有超过0~7之间的数字出现,即8或9, 将强制忽视前面的 0 ,直接将后面的数字当做 十进制 处理。
2、在进行算术计算时,所有八进制和十六进制的数字都会被转换成十进制
浮点数
包含整数、小数点、小数部分,所有的浮点数都是十进制下的数字
Infinity 无穷
由于计算机计算能力的限制,高于最大计算值的数将以正无穷Infinity显示,低于最小计算值直接显示 -Infinity
在js中,用Number.MIN_VALUE 表示最小的数(接近 0 ,但不是负数)
用Number.MAX_VALUE 表示最大的数
NaN
Not a Number,“不是一个数字” 的 数字类型。当数据无法转为数字时,或无法正常计算时,结果都为 NaN。
String,字符串类型
字符串,由若干个有序或无序的字符组成的串,包括字母、汉字、特殊符号、空格等,并用一对单引号('')或双引号(" ")包裹。所有的字符串,都是String类型
1、在js的内存中,字符都是用Unicode号来进行存储的,因为计算机只认数字,不认字符。
2、字符串的内容一旦创建,值不可改变,若想改,只能用新字符串替换旧字符串。
Boolean,布尔类型
只有两个值:true
、false
, 且必须是小写字母,不带引号。
布尔类型主要用来保存 对/错、 真/假、成立/不成立,在计算机内部存储中,true
为1 , false
为0
undefined类型
undefined本身也是一个数据,表示未定义。变量在只声明的时候值默认为undefined
null类型
null本身也是一个数据,null值表示一个空对象指针
4、数据类型转换
javascript是弱类型的编程语言,其特点:
1、声明变量时,不用考虑变量中将要存储的数据类型
2、赋值时,动态判断数据的类型
3、运算时,js会根据自己的需要,动态转换数据类型
将数据转换为 String类型
toString()
能够将其他数据类型转为String类型,其中null类型 和 undefined类型无法使用此方法var str = x.toString()
String()
可以将任意数据类型转为String类型,包括undefined 和 null,var str = String(x)
使用 +
号拼接字符串的方式,如 var str = x + ""
+ 号的特殊性
当
+
两边有一个是字符串类型的数据时,计算机会将另一个数据转换为字符串再进行字符串的拼接操作,最总返回字符串类型的数据。而如果两边都是数字,那么就是算术运算。
将数据转换为 Number类型
Number()
能够将任何数据类型转为数字类型,var n = Number(x)
- 字符串:如果是纯数字的字符串(“456”),则转为对应的数字,空字符串("")和空白字符(" ")串则转为0,若是非空非纯数字的字符串,则转为NaN
- 布尔值: true转为1,false转为0
- undefined: 转为 NaN
- null: 转为 0
parseInt()
用于将字符串转成整数的方法,var n = parseInt(str)
,默认情况下,parseInt()方法会将传入的数据先隐式转换为String类型
- 原理:从头开始读取字符串中的每个字符(如果开头是空字符,会跳过空字符),只读取数字字符。只要碰到第一个不是数字的字符,就退出,不认识小数点
.
- 作用: 能够对浮点数进行取整操作; 能够将以数字开头的字符串转为整数数字,如果字符串不是以数字开头,则转为NaN
- Number(x) vs parseInt(str)
Number() 只认识纯数字组成的字符串,且Number可转布尔值(true、false)
parseInt() 能转包含非数字字符的字符串,前提是开头位置是数字,parseInt()转不了布尔值
parseFloat()
能够将以数字开头的字符串转为浮点数,用法与parseInt()方法一样
将数据转换为 Boolean类型
Boolean()
能够将任意数据转为Boolean类型,var bool = Boolean(x)
- false:
""
(空字符串,不是空白字符串)、0
、NaN
、undefined
、null
- true: 除了以上几个转为
false
值以外,其他的数据都将转为true
toString() 和 parseInt()的其他用法——进制转换
-
十进制 转 n进制: x.toString(n)
var x = 5; //十进制数 console.log(x.toString(2)); // "101"
注意,值仍然是String类型
-
其他 n进制 转为 十进制: parseInt(str, n)
parseInt('101a', 2); // 101 --> 5 parseInt('1012a', 2); // 101 --> 5 parseInt('2101a', 2); // NaN parseInt('02101a', 2); // 0 --> 0
注意,parseInt()的第一个参数必须是以数字开头的字符串(如果不是字符串,parseInt会默认将其先转为字符串),且开头的数字必须符合 第二个参数所指定的n进制 的格式(如果仅部分数字符合,则取符合的那部分数字),否则将转为NaN
5、运算符和表达式
程序:人的想法在计算机中的执行步骤
运算符:程序中模拟人的思维运算或判断的 符号
表达式: 由数据、运算符 和 变量 组成的一个公式
返回值: 表达式最终会返回一个结果,这个结果就是返回值
算术运算符
以数值(字面量或变量)作为其操作数,并返回一个单个数值。
常用的算术运算符
+、 -、 *、 /、 %、++、-- 、**
模运算(取余数)%
%
,例如,a / b = c 余 d,则 d = a % b
递增、递减运算 ++、--
++、--
,一元运算符,也是赋值运算符,只有一个操作数,++ 和 -- 符号可以写在变量的前面和后面,分为前置和后置,以 ++ 为例:
前置递增: ++n,自加1,类似于 n += 1 或 n = n + 1,但是可以看出, ++n 更简洁方便。 在使用变量n时,先自加,后返回值
后置递增: n++,意义同上,唯一区别在于, 在使用变量n时,先返回原值,后自加
幂运算符 **
**
,返回第一个操作数做底数,第二个操作数做指数的乘方。幂运算符是右结合的。a ** b ** c 等同于 a ** (b ** c)。 如: 2 ** 3 ** 2 ---> 结果为 512
ES2016中,禁止使用带歧义的幂运算表达式,比如,底数前不能紧跟一元运算符(+、 - 、~、!、delete、void、typeof
)。-2 ** 2
,这在js中是会报错的,因为这会有歧义
正常情况下,一般是两个数字进行算术运算,例如,给定 y = 5,下表是经过各种算术运算符的结果
运算符 | 描述 | 例子 | x 运算结果 | y 运算结果 |
---|---|---|---|---|
+ | 加法 | x = y + 2 | 7 | 5 |
- | 减法 | x = y - 2 | 3 | 5 |
* | 乘法 | x = y * 2 | 10 | 5 |
/ | 除法 | x = y / 2 | 2.5 | 5 |
% | 取模(取余数) | x = y % 2 | 1 | 5 |
++ | 自增 前置自增 | x = ++y | 6 | 6 |
自增 后置自增 | x = y ++ | 5 | 6 | |
-- | 自减 前置自减 | x = --y | 4 | 4 |
自减 后置自减 | x = y-- | 5 | 4 | |
** | 幂 | x = y ** 2 | 25 | 5 |
算术运算中存在的特殊情况
有特殊值参与运算(NaN、Infinity)
NaN参与运算:返回值都为NaN
-
Infinity参与计算,视情况而定。
console.log(Infinity + 5); // Infinity console.log(Infinity - 5); // Infinity console.log(Infinity * 5); // Infinity console.log(Infinity / 5); // Infinity console.log(Infinity % 5); // NaN console.log(5 / Infinity); // 0 console.log(5 % Infinity); // 5 console.log(Infinity + Infinity); // Infinity console.log(Infinity - Infinity); // NaN console.log(Infinity * Infinity); // Infinity console.log(Infinity / Infinity); // NaN console.log(Infinity % Infinity); // NaN
总之,运算结果不确定的数,返回NaN
其他类型的数据参与运算
在算术运算中,会隐式调用Number()将数据转为Number类型,再进行运算
特殊情况,在 +
法中,碰到字符串,都转为字符串,再进行字符串的拼接
console.log(1 + "2"); // "12"
console.log(1 - "2"); // -1
console.log(1 * "2"); // 2
console.log(1 / "2"); // 0.5
console.log(1 % "2"); // 1
console.log(1 - ""); // 1 - 0 --> 1
console.log(1 - " "); // 1 - 0 --> 1
console.log(1 - "12abc"); // 1 - NaN --> NaN
运算顺序
先乘除取余,再加减,有小括号先算小括号
比较运算符
比较运算符(
>、 <、 >=、 <=、 ==、!=、 ===、!==
),也称关系运算符,指两个操作数做比较,比大小,返回值是一个布尔值,true
或false
==
表示等于,只判断值大小是否相等,不判断数据类型
!=
表示不等于,与 == 相反
===
表示全等,首先数据类型必须相同,其次值相同(不进行隐式转换)
!==
表示不全等,与 === 相反
比较运算中的特殊情况
正常情况下,是两个数字进行比较,然而,也存在以下特殊情况
有特殊值参与运算(NaN、Infinity)
-
NaN参与运算:只有
!=
和!==
的情况下,结果返回true
,其他都返回false
。
isNaN(x):专门判断一个数据是否为NaN,如果是NaN,则返回true,反之则为false
通过使用isNaN(),来判断一个数据是否为数字,或者是否能够隐式转换为数字使用总之,NaN不等于、不大于、不小于任何值,包括NaN自身
-
Infinity参与计算,视情况而定。
console.log(Infinity > 8); //true // console.log(Infinity < 8); //false console.log(Infinity >= 8); //true // console.log(Infinity <= 8); // console.log(Infinity == 8); console.log(Infinity != 8); //true // console.log(Infinity === 8); console.log(Infinity !== 8); //true // console.log(Infinity > Infinity); // console.log(Infinity < Infinity); console.log(Infinity >= Infinity); //true console.log(Infinity <= Infinity); //true console.log(Infinity == Infinity); //true // console.log(Infinity != Infinity); console.log(Infinity === Infinity); //true // console.log(Infinity !== Infinity);
总之,Infinity === Infinity,Infinity >= x(包括Infinity自身),且 Infinity!= x(除了Infinity自身)
当其他类型的数据参与算术运算
在比较运算中,首先隐式调用Number()将数据转为Number类型,再进行比较,其中,存在特殊情况:
如果两个数都是字符串,则会根据每个字符的Unicode号进行比较
-
null参与比较运算时: 虽然 null隐式转换为0,但是,当null 与 0 进行比较时,相等 判断 为
false
, !=、>= 和 <= 判断为true
,而且,null == undefinedconsole.log(null == 0); //false console.log(null != 0); //true console.log(null >= 0); //true console.log(null <= 0); //true console.log(null == undefined); //true
运算顺序
从前往后进行比较,前面的结果再与后面的进行比较
比如: 3 > 2 > 1 -----> 结果为 false
根据运算顺序,先运算 3 > 2 ,结果为 true(1),之后再运算 true(1) > 1, 结果就为 false
"a" < "b" < "c" -----> 结果为false
根据运算顺序,先运算 "a" < "b" ,结果为 true,之后再运算 true < "c", 两者进行隐式转换, true(1) < "c"(NaN),结果就为 false
逻辑运算符
逻辑运算符(
&& 、 ||、 !
),常用于布尔类型值之间进行运算,当操作数都是布尔值时,返回值为 布尔值 (true / false)
&&
: 且,程序中称为“逻辑与”
条件1 && 条件2 : 必须条件1 和 条件2 都为 true 时,返回结果才为 true,即,都 真 才 真,有 假 就 假||
:或,程序中称为“逻辑或”
条件1 || 条件2 : 只要任意一个条件为true,结果为true,只有所有条件都为false,结果才为false,即,有 真 就 真,都 假 才 假!
:非,程序中称为“逻辑非”
将条件的true/false结果进行取反颠倒,即,非 真 即 假,非 假 即 真
逻辑运算的特殊情况
在逻辑运算中,隐式调用Boolean()方法,将数据隐式转换为布尔类型的值,再参与逻辑运算。
当其他的数据类型的值参与逻辑运算时,先隐式转换为布尔值参与逻辑运算,最终的返回值不一定是布尔值,因为非布尔值参与运算完之后恢复该数据的初始数据类型。
短路逻辑
逻辑运算中,如果前一个条件已经可以得出最终结论,则后续所有条件不再执行!
(逻辑与 a&&b ) 如果a能被转换为false,那么返回a;否则,返回b。
(逻辑或 a ||b ) 如果a能被转换为true,那么返回a;否则,返回b。
console.log(null && "123"); // null
console.log(12 && "123"); // "123"
console.log(12 || "123"); // 12
console.log(undefined || null); // null
在利用短路逻辑的时候,不再返回布尔值,若参与运算的都是数值,返回值则从两个数值中选择
- 利用短路逻辑,实现按条件执行语句
- 利用 逻辑与 实现条件执行语句
条件 && 操作语句 ---> 如果条件为true,才执行操作语句,否则,什么也不做 - 利用 逻辑或 实现 默认值效果(二选一取值) 值1 || 值2
- 利用 逻辑与 实现条件执行语句
运算顺序
同种逻辑运算符,从前往后运算
多种逻辑运算符:!、 && 、 ||
位运算(部分,了解)
直接由二进制进行的运算,将数值的二进制左移或右移 n 位
左移 n 位:则将数据 * 2 的n次方,如: 1<< 3 ,即 1 左移 3位,值为8,,m << n,m乘以2的n次方
右移n位: 则将数据 / 2 的n次方,如: 8 >> 3,即 8 右移3位,值为1,m >> n,m除以2的n次方
固定套路: 取整数, n>>>0, n^0, n|0
赋值运算符
常用的赋值运算符
=、+=、-=、*=、/=、%=、**=
=
:基本赋值运算,将等号右边的值保存在左边的变量中。
+=、-=、*=、/=、%=、**=
:扩展赋值运算符,对变量内部的值进行修改的简写方法,如:a+=5; ---> a=a+5;
运算符优先级 (从高到底)
- () 优先级最高
- 一元运算符 ++ -- !
- 算术运算符 先 **(幂) * / % 后 + -
- 关系运算符 > >= < <=
- 相等运算符 == != === !=
- 逻辑运算符 先&& 后||
- 赋值运算符
6、条件分支语句
根据不同的条件,执行不同的代码
if 语句
if (条件表达式){
//结构体1
}else{
//结构体2
}
如果条件表达式为 true , 执行 结构体1, 否则执行结构体2
if 语句可以实现选择的功能,两个分支可以选择一个执行,不会全都执行,其中,如果只需实现一个结构体,可以将else分支省略。
-
可以实现多分支的if语句,形如:
if (条件1) { //满足条件1, 执行的结构体 } else if (条件2) { //不满足条件1, 满足条件2, 执行的结构体 } else if (条件3) { //不满足条件1 / 2, 满足条件3, 执行的结构体 } else { //不满足前面所有条件, 执行的结构体 }
-
if 语句的嵌套
if语句的结构体中,可以嵌套另外一组if语句if (条件1) { if (条件2) { //满足条件1, 同时满足条件2, 执行的结构体 } else { // 满足条件1, 但不满足条件2, 执行的结构体 } } else { //不满足条件1, 执行的结构体 }
三元表达式
语法: 条件表达式 ? true_value : false_value;
根据条件表达式的结果,选择执行true_value的语句 或者 false_value的语句
switch语句
switch语句允许一个程序计算一个表达式的值,并根据值匹配到某一个case 标签,如果匹配成功,则执行相关语句
switch (表达式) {
case 值1:
//结构体1;
break;
case 值2:
//结构体2;
break;
...
default:
//结构体n;
}
switch:入口,开关,进入第一个匹配到的case中,开始依次向下执行
break: 终止当前结构的继续执行。一般执行一个case时,结构体中都应该加break;如果相邻的多个case执行相同的操作时,中间可以不写break,减少代码量
当然,最后一个匹配项可以不加break,即default的结构体中可以省略break,甚至有时default可以不写;
条件分支--总结
if语句: 最常用的语句,所有判断情况都能够书写
三元表达式:多用于给变量赋值时根据条件二选一
switch..case语句: 多用于给一个表达式,去匹配多个固定值可能性的情况,这种情况下,使用switch比if else的效率高,因为不带隐式类型转换
7、循环语句
循环三要素:
1、循环条件:保证循环可以继续执行的判断条件(不是退出条件)
2、循环变量:循环条件中,用作判断的变量
3、循环体:循环反复执行的代码,在循环体中,都需要迭代更新循环变量的值
for 循环
- 语法:
for (定义循环变量; 循环条件; 更新循环变量) { // 循环体 }
- for循环执行过程
- 定义循环变量
- 判断循环条件
- 若满足循环条件,则进入循环体,执行循环体中的语句,更新循环变量,本次循环结束。若不满足循环条件,则直接结束循环。
- 重复步骤2、3,直到不满足循环条件,则结束循环。
while 循环
-
语法:
var 循环变量 = 初始值; //声明并初始化循环变量 while (循环条件) { // 循环体 // 更新循环变量 }
while循环执行过程:与for循环类似
do-while循环
-
语法:
var 循环变量 = 初始值; //声明并初始化循环变量 do { // 循环体 // 更新变量 } while (循环条件);
do-while循环执行过程与while类似,唯一区别在于,do-while先执行一次循环,再判断循环条件,是否满足继续执行循环
do-while vs while
只需要看开始执行循环前,循环条件是否满足:
1、如果 满足: 则两者都能够进入循环体,两者完全一样
2、如果 不满足: do-while至少可以执行一次循环体,而while一次都无法执行
循环语句--总结
- 遇到必须先执行一次循环体的循环,使用 do-while 循环
- 而 for循环 和 while 循环中:
1、如果循环变量在更新迭代时,有规律性,则选择for循环
2、如果循环变量的变化没有规律时,则选择while循环,同时可以配合使用break来强行终止循环
break、continue语句
break语句
能够立即终止当前的循环结构,跳出循环体
break语句只能终止当前所在的那层循环,如果嵌套多层循环,外层循环是无法终止的
如果想停止外层循环,则需要在外层添加一个自定义label标签,在内层循环的break
关键字后面 空格 加自定义的label标签名
breakLoop: for (定义循环变量; 循环条件; 更新循环变量) {
for (定义循环变量; 循环条件; 更新循环变量) {
// 循环体
if (条件) {
// 结构体
break breakLoop;
}
}
}
continue语句
立即结束当前次循环,进入下一次循环
continue默认也只能进入自身循环结构的下一次循环,不能结束外层循环的这一次循环而进入下一次
要实现外层循环的方式,与 break 一样,在外层添加自定义label标签
break语句 和 continue语句,都是为了优化性能,减少计算机的计算次数