Javascript知识点全解析

发表时间: 2022-03-20 19:39

# 一、基本语法

1. 基本语句

1. alert(); 浏览器弹出一个警告框

2. document.write(); 在body标签内写入内容

3. console.log(); 在控制台中输出结果 控制台查看方法 F12 console

2. JS中严格区分大小写

3. JS中每一条语句以(;)分号结尾 注意: 英文状态下的分号

1. 如果不写分号,浏览器会自动添加,但是会消耗一些系统资源

2. 而且有的时候,浏览器会加错分号,所以在开发中分号必须写

4. JS中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化

# 二、字面量与变量

1.字面量,都是一些不可改变的值 比如:

​ 1 2 3 4 5 这些数字就是字面量 特点: 不会被改变 1 在未来的某一天会变为其他值吗??

​ 字面量都是可以直接使用的,但是我们一般不会直接使用字面量

​ 比如: 字面量 12345646464654 我在第一行代码中使用了 并且在 一万行的时候也使用了该字面量。 容易出错,不方便使用。

​ 2.变量

​ 变量可以用来保存字面量,而且变量的值也是可以任意改变的

​ 变量更加方便我们使用,所以在开发中都是通过变量去保存一个字面量,而很少直接使用字面量

​ 变量怎么使用呢?

声明变量

在js中使用`var`关键字来声明一个变量

```javascript

var a;

// 声明过变量之后需要对该变量进行赋值

a = 1;

// 在控制台中输出a变量的结果

console.log(a); --> 1

// 这要声明变量需要两步 比较麻烦 我们可以缩写为一步 也就是 声明与赋值同时进行

var a = 1;

console.log(a);

// 现在有一个字面量 80 我们现在不知道这个字面量到底代表着什么

// 这时候 变量可以对该字面量进行一个描述 例如:

var age = 80;

age == 年龄;

```

# 三、标识符

1. 在JS中所以的可以由我们自主命名的都可以称为是标识符

2. 例如:变量名、函数名、属性名都属于标识符

3. 命名一个标识符时需要遵守如下的规则:

1. 标识符中可以含有:字母、数字、下划线(_)、$

2. 标识符不能以数字开头

3. 标识符不能是ES中的关键字或者是保留字

```javascript

var var = 10;

// 控制台中将会报错

```

4.[关键字与保留字参考网站](
https://www.runoob.com/js/js-reserved.html)

5.标识符一般都采用驼峰式命名法

​ -首字母小写,每个单词的开头字母大写,其余字母小写

​ helloWorld

​ xxxYyyZzz

# 四、数据类型

​ 数据类型代表的就是 字面量的类型

​ 在JS中一共有 6 种数据类型

​ String 字符串

​ Number 数值

​ Boolean 布尔值

​ Null 空值

​ Undefined 未定义

​ Object 对象

​ 其中 String Number Boolean Null Undefined 都属于基本数据类型

​ 而Object 属于引用数据类型 (在内存中的存储方法不同)

## 4.1 字符串

​ String 字符串

​ 在JS中字符串需要用引号 括起来

​ var str = "我是字符串";

​ 使用双引号或者单引号都可以,但是不要混着用

​ 引号不能嵌套,双引号内不能在有双引号,单引号内不能在有单引号 双引号内可以有单引号 单引号内可以有双引号

​ 在字符串中我们可以使用 \ 反斜杠 作为转义字符

​ 例如:

​ \ " 代表 "

​ \ ' 代表 '

​ \n 代表换行

​ \t 代表一个制表符

​ \ \ 代表 \

## 4.2 Number

​ 在JS中所有的数值都是Number类型,包括整数和浮点数(小数),在谷歌浏览器控制台中 数值是蓝色 字符串是黑色

​ 在JS中我们可以使用一个运算符 typeof 来检查一个变量的数据类型

​ 语法:typeof 变量

​ 检查字符串时,会返回string

​ 检查数值时,会返回number

​ NaN 是一个特殊的数字,表示 Not A Number

​ 用typeof 检查一个NaN也返回number

​ 如果使用JS 对浮点数进行运算,可能得到一个不精确的结果 例如:

```javascript

var a = 0.1 + 0.2;

console.log(a); --> 0.30000000000000004;

```

## 4.3 Boolean 布尔值

​ 布尔值只有两个,主要用来逻辑判断

​ true

​ - 代表真

​ false

​ - 代表假

```javascript

var boo = true;

console.log(typeof boo); --> // boolean

// 使用typeof 检查一个布尔值的时候 返回的结果就是 boolean

```

## 4.4 Null 和 Undefined

​ Null(空值)类型的值只有一个,就是null

​ null 这个值专门用来表示一个为空的对象

​ 使用typeof 检查一个null 值的时候,会返回object

​ Undefined(未定义)类型的值只有一个,就是undefined

​ 当声明一个变量,但是并不给变量赋值时,它的值就是undefined

​ 使用typeof 检查一个undefined 时,也会返回 undefined

```javascript

var a = null;

console.log(typeof a); --> object

var b = undefined;

console.log(typeof b)l --> undefined

var c;

console.log(c); --> undefined

```

# 五、强制数据类型转换

​ 强制数据类型转换

​ 指将一个数据类型强制转换为其他的数据类型

​ 类型转换主要指,将其他的数据类型,转换为 String Number Boolean

​ 5.1 将其他数据类型转换为String

```javascript

var a = 123;

console.log(typeof a);

console.log(a);

// 将 a 变量转换为字符串

/*

第一种方法:

调用被转换数据类型的toString()方法

*/

a.toString(); // 注意大小写

console.log(typeof a); --> number // 结果没有变化

console.log(a);

// 注意:该方法不会影响到原变量,它会将转换的结果返回

var b = a.toString();

console.log(typeof b);

// 布尔值转换字符串

var a = true;

a = a.toString();

console.log(typeof a);

// null 和 undefined 这两个值没有toString()方法

/*

方法二:

调用String()函数,并将被转换的数据作为参数传递给函数

使用String()函数做强制类型转换时,

对于Number和Boolean实际上就是调用toString()方法

但是对于null和undefined,就不会调用toString()

它会直接将null 转换为 "null" undefined同理

*/

```

​ 5.2 其他数据类型转换为 Number类型

```javascript

/*

将其他的数据类型转换为Number

方式一:

调用Number()函数

字符串 转换 数字

1. 如果是纯数字的字符串,则直接将其转换为数字

2. 如果字符串中有非数字的内容,则转换为NaN

3. 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0

*/

var a = "123";

a = Number(a);

console.log(typeof a, a); --> number

var a = "abc1";

a = Number(a);

console.log(typeof a, a); --> number NaN

var a = " ";

a = Number(a); --> 0

// 布尔值 转换 数字

var a = true;

a = Number(a); --> 1

var a = false;

a = Number(a); --> 0

// null 转换为 数字

var a = null;

a = Number(a); --> 0

// undefined 转换为 数字

var a = undefined;

a = Number(a); --> NaN

// 现在我们可以将 一个纯数字的字符串转换为数字 现在我们通过js获取到一个元素的 宽度 :"125px"

// 刚好我需要用这个值 进行计算 这时候用我们的Number()函数肯定是不行的

// 我们有新的函数可以解决这个问题 parseInt() 注意大小写

var a = "125px";

a = parseInt(a); --> 125

// parseInt()函数的作用就是 从左到右 依次去找数字 如果碰到非数字的话就会停止查找将结果返回

// 对应的还有一个 parseFloat()函数 用来取小数

var a = "123.1234566px";

a = parseFloat(a); --> 123.1234566

```

​ 5.3 将其他数据类型转换为 布尔值(Boolean)

```javascript

/*

转换为Boolean 我们使用的就是Boolean()函数

*/

var a = 123;

// 调用Boolean()函数

a = Boolean(a); --> true

// 数字 0 是 false NaN 也是 false

var a = NaN;

a = Boolean(a); --> false

// 除了 0 和 NaN 以外 都是true

// 字符串转布尔值

var str = "abcd";

str = Boolean(str); --> true

var str = "false";

str = Boolean(str); --> true

// 字符串转换布尔值 除了空串 其余的都是true

var str = '';

str = Boolean(str); --> false

// null 和 undefined 转换为布尔值

var a = null;

a = Boolean(a); --> false

var a = undefined;

a = Boolean(a); --> false

// null 和 undefined 都可以转换为布尔值 false

// 对象也会转换为 true

```

# 六、运算符

​ 运算符也叫操作符

​ 通过运算符可以对一个值或者多个值进行运算,并获取运算结果

​ 例如:typeof 就是一个运算符 用来获取一个值的数据类型

```javascript

var a = 123;

var result = typeof a; // 讲运算结果保存的变量中

console.log(result); // typeof 的返回值是字符串的形式

```

## 6.1 算数运算符(二元运算符) 操作两个数

​ + - * / %

​ + 可以对两个值进行加法运算,并将结果返回,不会改变原变量

​ - 可以对两个值进行减法运算,并将结果返回,不会改变原变量

​ * 可以对两个值进行乘法运算,并将结果返回,不会改变原变量

​ / 可以对两个值进行除法运算,并将结果返回,不会改变原变量

```javascript

var a = true + 1;

console.log(a); --> 2

var a = false + 1;

console.log(a); --> 1

var a = null + 1;

console.log(a); --> 1

var a = undefined + 1;

console.log(a); --> NaN // NaN与任何值进行运算结果都为NaN

// 当对非number类型的值进行运算时,会将它转换为number类型再运算

// + 有一种特殊情况 当字符串与其他数据类型进行 + 运算时,会进行字符串拼接

var a = 123 + "345";

console.log(a); --> "123345";

var a = 123 + 234 + "abc";

console.log(a); --> "357abc"

// 任何值 做 - / * 运算时都会自动转换为number + 运算时 会转换为字符串 再进行拼接

```

## 6.2一元运算符

​ 一元运算符 只需要一个操作数 比如:typeof 就是一个一元运算符

​ 另外的两个一元运算符 + -

​ + 正号

​ - 负号

```javascript

var a = 123;

a = +a;

console.log(a); --> 123

// 正号不会对数字产生任何影响

var a = 123;

a = -a;

console.log(a); --> -123

// 负号可以对数字进行负号的取反

// 也可以对字符串的纯数字 进行类型转换

var a = "12";

a = +a;

console.log(a); --> 12 number

```

## 6.3自增与自减

​ 通过自增可以使变量在自身的基础上增加1

```javascript

var a = 1;

a = a + 1;

console.log(a); --> 2

// 自增 就是 ++

// 对于一个变量自增以后,原变量的值会立即自增

var a = 1;

a++;

console.log(a); --> 2

// 自增还有另外一个写法 ++a

var a = 2;

++a;

console.log(a); --> 3

// 自增分为两种:后++ 和 前++

// 无论是前++ 或者 后++,都会立即使原变量自增1

// 他们之间不同的是 a++ 和 ++a 的返回值不同

var a = 1;

console.log(a++); 1

console.log(a); 2

// 自减原理同自增

```

## 6.4逻辑运算符

​ JS中为我们提供了三种逻辑运算符

​ ! 非

​ ! 可以用来对一个值进行非运算

```javascript

var a = true;

console.log(a); --> true

// 对a进行非运算

a = !a;

console.log(a); --> false

// 所谓非运算就是对一个布尔值进行取反操作

// true 变 false false 变 true

// 如果对非布尔值进行非运算,则会将其转换为布尔值 然后进行运算

var b = 2;

b = !b;

console.log(b); --> false

```

​ && 与

```javascript

// && 可以对符号两侧的值进行与运算并返回结果

// 运算规则如下

var result = true && false;

console.log(result); --> false

// 如果两个值都是true 则返回true

var result = true && true;

console.log(result); --> true

// 两个值中只要有一个值为false 则返回false

var result = false && true;

console.log(result); --> false

var result = false && false;

console.log(result); --> false

// 逻辑与 在判断的时候 如果第一个值的结果是false 则不会去看第二个值的结果

true && alert("1");

false && alert("2");

```

​ || 或

```javascript

// 逻辑或刚好 与 逻辑与相反

// 只要有一个为true 则返回true

var result = false || true;

console.log(result); --> true

// 两个值都为false 则返回false

var result = false || false;

console.log(result); --> false

// 逻辑或 在判断的时候 如果第一个值的结果是true 则不会去看第二个值的结果

true || alert("1");

false || alert("2");

```

​ 逻辑与 逻辑和 非布尔值的情况

```javascript

// 对与非布尔值进行与或运算时,会先将其转换为布尔值,然后在进行运算,并且返回原值

var result = 1 && 2;

console.log(result); --> 2

var result = 2 && 1;

console.log(result); --> 1

// 如果两个值 都为true 则返回后面的

// 第一个值为false 则返回第一个值

var result = 0 && 2;

console.log(result); --> 0

// 第一个值为true 第二个为false 则返回第二个值

var result = 1 && NaN;

console.log(result); --> NaN

// 逻辑或 也是先将其转换为布尔值 然后进行运算

// 第一个值为true 则直接返回第一个值

var result = 1 || 0;

console.log(result); --> 1

// 第一个值为false 则回去看第二个值 并返回第二个值

var result = NaN || 100;

console.log(result); --> 100

var result = "" || "hello"; --> ???

var result = -1 || "你好"; --> ???

```

## 6.5 赋值运算符

​ = 可以将符号右侧的值赋值给符号左侧的变量

```javascript

var a = 123;

console.log(a); --> 123

```

​ +=

```javascript

var a = 10;

a = a + 5;

console.log(a); --> 15

// a += 5 等价与 a = a + 5

// 更方便的一个写法 注意 += 是一个运算符

a += 5;

console.log(a); --> 20

```

​ -=

```javascript

var a = 10;

a = a - 5;

console.log(a); --> 5

// a -= 5 等价与 a = a - 5

// 更方便的一个写法

a -= 5;

console.log(a); --> 0

```

​ *= /= %= 都与上面相同

## 6.6 关系运算符

​ 通过关系运算符可以比较两个值之间的大小关系,如果关系成立返回 true 不成立则返回 false

```javascript

// > 大于号

// 判断符号左侧的值是否大于右侧的

// 如果关系成立,返回true,如果关系不成立则返回false

var result = 5 > 10;

console.log(result); --> false

result = 5 > 4;

console.log(result); --> true

result = 5 > 5;

console.log(result); --> false

// >= 大于等于

// 判断符号左侧的值是否 大于 或 等于 右侧的值

result = 5 >= 5; // true

result = 4 >= 6; // false

// < 小于

// 判断符号左侧的值是否 小于 右侧的值

result = 10 < 100; // true

result = 100 < 10; // false

// <= 小于等于

// 判断符号左侧的值是否 小于 或 等于 右侧的值

result = 10 <= 10; //true

result = 12 <= 10; //false

// 关系运算符和数学里面的比较 是一样的

// 下面来看对非布尔值进去比较的情况

// 数值与其他数据类型进行比较时 会将其他数据类型转换为 数值类型 在进行比较

result = 1 > true; // false

result = 1 >= true; // true

result = 1 > "0"; // true

result = 10 > null; // true

result = 10 > "hello"; // false NaN 与任何值比较时 都时false

result = 10 < undefined; // false

result = true > false; // true

result = false > true; // false

// 比较两个字符串时,不会转换为number类型在进行比较,而是去比较字符的Unicode编码

// 在比较字符编码时是一位一位的比较

result = "1" < "5"; // true

result = "a" > "b"; // false

// 字符串中可以使用转义字符输入unicode编码 \u四位编码

console.log("\u2620")

// HTMl中使用编码 &#四位编码; 注意编码要从十六进制转换为十进制

<p>☠</p>

```

## 6.7 相等运算符

​ 相等运算符用来比较两个值是否相等

​ 如果相等会返回true,否则返回false

```javascript

// 使用 == 来做相等运算

console.log(1 == 1); // true

var a = 10;

console.log(a == 4); // false

// 当使用==来比较两个值时,如果值的类型不同,则会自动进行类型转换,然后进行比较

console.log("1" == 1); // true

// 都转换为number 进行比较

console.log(true == "1"); // true

// 这时候null 没有转换为number 不要管转成什么记住这个特殊的就ok了

console.log(null == 0); // false

// undefined 衍生自 null 所以他们相等

console.log(undefined == null); // true

// NaN不和任何值相等,包括它本身

console.log(NaN == NaN); // false

// 如果判断这个值是否时NaN 利用一个函数 isNaN() 如果该值时NaN 返回true

var a = NaN;

console.log(isNaN(a)); // true

```

​ 不相等运算符

```javascript

// 不相等和相等刚好相反,用来比较两个值是否不相等

console.log(10 != 5); // true

console.log(1 != 1); // false

// 不相等比较两个值的时候,如果类型不同,也会进行类型转换,然后进行比较

```

​ 严格相等运算符

```javascript

// ===

// 相等会做类型转换,而严格相等不会进行类型转换,如果两个值的类型不同,直接返回false

console.log("123" === 123); // false

```

​ 严格不等运算

```javascript

// !==

// 不相等会做类型转换,而严格不相等不会进行类型转换,如果两个值的类型不同,直接返回true

console.log("123" !== 123); //true

```

## 6.8 条件运算符(三元运算符)

​ 语法:条件表达式 ? 语句1 : 语句2;

```javascript

// 条件运算符在执行时,首先对条件表达式进行求值

// 如果该值为true,则执行语句1,并返回执行结果

// 如果该值为false,则指向语句2,并返回执行结果

var a = 10;

var b = 20;

a > b ? alert("a大") : alert("b大");

// 获取 a 和 b 中的最大值

var max = a > b ? a : b;

// 练习 获取 a b c 中最大的值

var a = 10;

var b = 20;

var c = 30;

```

## 6.9 运算符的优先级

​ 就和数学中一样,在JS中运算符也有优先级

​ 比如:先乘除 后加减

```javascript

var result = 1 + 2 * 3; // 7

// 如果||的优先级高,或者两个一样高 返回3

// 如果&&的优先级高,返回 1

var result = 1 || 2 && 3; // 1

```

[优先级对照表](
https://www.sojson.com/operation/javascript.html)

​ 没有必要去记这个表 我们可以利用() 来改变优先级

# 七、代码块

```javascript

// 我们的程序是由一条一条语句构成的

alert(1);

console.log(1);

document.write(1);

// 语句是按照自上到下的顺序一条一条执行的

// 在JS中可以使用 {} 来为语句进行分组

{

alert(1);

console.log(1);

document.write(1);

}

// 现在这就是一组语句 它们要么都执行,要么都不执行 代码块后边不需要写;(分号)

// JS中的代码块只有分组的作用 代码块内部的内容 在外部是完全可见的

```

# 八、流程控制语句

​ JS中的程序时从上到下一行一行执行的

​ 通过流程控制语句可以控制程序的执行流程,

​ 使流程可以根据一定的条件选择执行

​ 语句的分类:

​ 1. 条件判断语句

​ 2. 条件分支语句

​ 3. 循环语句

```javascript

// 条件判断语句

// 使用条件判断语句可以在执行某个语句之前进行判断,如果条件成立才会执行语句,不成立就不执行

// 语法:

if(条件表达式)

语句

// if语句在执行时,会先对条件表达式进行求值判断,

// 如果条件表达式的值为true,则执行if后的语句,反之不执行if后的语句

if(true)

alert("你看我出来不");

// 只能控制到if语句的下一行语句 不会控制到其他语句

// 如果要控制多条语句 那我们的代码块就有作用了

if(true){

语句1

语句2

}

// 例子 : a 大于 10,并且 a 小于等于20 执行语句

// if语句 语法二:

/*

if(条件表达式){

语句

}else{

语句

}

条件为 true 执行if下面的语句 条件为false 执行else下的语句

*/

var age = 60;

if(age >= 60){

alert("你可以退休了");

}else{

alert("你还年轻努力挣钱");

}

/*

语法三:

if(条件表达式){

语句

}else if(条件表达式){

语句

}else if(条件表达式){

语句

}else{

语句

}

当改语句执行时,会从上到下依次对条件表达式进行求值判断

如果为true,则执行当前语句

改语句中,只会有一个代码块被执行

*/

// 例子: 年龄判断

// 练习

/*

输入框 prompt() 可以弹出一个输入框 在括号中可以输入提示文字 函数的返回值就是用户输入的内容

从键盘输入小明的期末成绩:

当成绩为100时,奖励100W

当成绩为[80 - 99]时,奖励一台MacBook

当成绩为[60 - 80]时,奖励一份试卷

其他时,等着挨打吧

*/

/*

高:180cm以上,钱:1000万以上,颜值:600分以上;

如果三个条件同时满足,则弹出:"就你了 绝对嫁你";

如果三个条件有为真的情况,则弹出:"算了 将就以下";

如果三个条件都不满足:则弹出:"看不上 不嫁";

*/

/*

编写程序,由键盘输入三个整数分别存入变量num1,num2,num3中

对他们进行排序,并且从小到大输出

*/

```

## 8.2 条件分支语句 switch 语句

```javascript

// 语法:

/*

switch(条件表达式){

case 表达式:

语句...

break;

case 表达式:

语句...

break;

case 表达式:

语句...

break;

default:

语句...

break;

}

switch...case..语句

在执行时会依次将case后的表达式的值和switch后的条件表达式的值进行严格相等比较

如果比较结果为true,则从当前case处开始执行代码

*/

// 根据num的值,输出对应的中文

var num = 1;

switch(num){

case 1:

console.log("壹");

break;

}

// 练习题

/*

对于成绩大于60分的,输出'合格'。低于60分的,输出'不合格'

*/

switch(true){

case score >= 60:

console.log('合格');

break;

default:

console.log('不合格');

break;

}

```

## 8.3 while循环语句

```javascript

// 语法:

/*

while(条件表达式){

语句...

}

通过循环语句可以反复的执行一段代码多次

while语句在执行时,先对条件表达式进行求值判断,

如果值为true,则执行循环体,循环体执行完毕之后,继续对条件表达式进行求值判断

如果还为true,则继续执行


如果值为false,则终止循环

*/

var n = 1;

while(true){

alert(n++);

}

// 将条件写死为true的循环,称为死循环

// 该循环不会停止,除非浏览器关闭

// 循环体中 我们可以使用 break 来打断循环

var n = 1;

while(true){

// 判断n是否等于10

if(n == 10){

// 退出循环

break;

}

}

// 创建一个循环,往往需要三个步骤

// 1. 初始化一个变量

var i = 0;

// 2.在循环体中设置一个条件表达式

while(i < 10){

// 3. 定义一个更新表达式

i++;

// 循环体执行一次 i 变量更新一次 条件表达式不成立,循环停止

}

// do...while循环 很相似

// 语法:

/*

do{

alert(i++);

}while(i <= 10);

*/

// 两者的执行流程不同,do...while语句在执行时,先执行,后判断

// 而while循环,先判断,后执行

// 循环练习

// 假如投资的年利率为5%,试求从1000块涨到5000块,需要花费多少年?

// 要求用户必须输入0-100之间的数字,如果输入错误将继续弹出输入框

```

## 8.4 for循环语句

```javascript

// 创建一个执行10次的while循环

// 1. 初始化一个变量

var i = 0;

// 2. 定义条件表达式

while(i < 10){

// 更新表达式

alert(i++);

}

// while循环的初始化变量,更新表达式的位置都不是固定的

// for循环中,给我们提供了专门的位置用来放三个表达式:

/*

for(初始化变量;条件表达式;更新表达式){

语句...

}

*/

for(var i = 0; i < 10; i++){

alert(i)

}

// for循环的执行流程:

/*

1. 先执行初始化表达式,声明变量(只会执行一次)

2. 执行条件表达式,判断是否执行循环

3. 条件为true,执行循环体

4. 执行更新表达式

*/

// 练习:

/*

1. 打印1-100之间所有的奇数之和

2. 打印1-100之间所有7的倍数的个数以及总和

3. 水仙花数

水仙花数指一个3位数,它的每个位置上的数字的三次方之和等于它本身

例如:(1*1*1 + 5*5*5 + 3*3*3) == 153

范围(100-1000)

4. 判断用户输入的数字,是否是一个质数

*/

```

## 8.5 for循环的嵌套

```javascript

// 写法:

for(var i = 0; i < 10; i++){

console.log(i);

for(var n = 0; n < 10; n++){

console.log(n);

}

}

/*

通过程序打印如下内容:


*****

*****

*****

*****

*****




*

**

***

****

*****


*/

// 练习: 99乘法表

// 打印出 1 - 100之间所有的质数

```

# 九、对象

```javascript

/*

JS中数据类型:

String

Number

Boolean

Null

Undefined

----- 以上五种属于基本数据类型

Object 对象

----- 对象属于引用类型


在JS中来表示一个人的信息(name,sex,age)

*/

var name = "王某";

var sex = "男";

var age = 18;

// 如果使用基本数据类型的数据,我们所创建的变量都是独立的,不能成为一个整体。

// 对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性

// 让这些变量都存储在一个对象中,那他们就有联系了,都在一个对象中

// 对象的分类:

/*

1. 内置对象

由ES标准中定义的对象,在任何的ES的实现中都可以使用

比如:Math String Number Boolean Function Object...

2. 宿主对象

由JS的运行环境提供的对象,目前来讲主要指浏览器提供的对象

比如: BOM DOM

3. 自定义对象

由开发人员自己创建的对象

*/

// 创建对象

var obj = new Object(); // 使用new关键字调用的函数,是构造函数

// 构造函数是专门用来创建对象的函数

console.log(obj); --> {}

// 用typeof 检查对象的数据类型时,返回的时 object

/*

在对象中保存的值称为属性

向对象中添加属性

写法:对象.属性名 = 属性值;

*/

// 向obj中添加一个name属性

obj.name = "王某";

// 向obj中添加一个sex属性

obj.sex = "男";

// 向obj中添加一个age属性

obj.age = 18;

console.log(obj); --> {name:"王某",sex:"男",age:18}

/*

读取对象中的属性

语法:对象.属性名

*/

console.log(obj.name); --> "王某";

console.log(obj.sex); --> "男";

console.log(obj.age); --> 18;

// 去读取一个对象中没有的属性时,会返回undefined,并不会报错

/*

修改对象的属性值

语法:对象.属性名 = 新值

*/

obj.name = "尼古拉斯赵四";

console.log(obj.name); --> "尼古拉斯赵四"

/*

删除对象的属性

语法:delete 对象.属性名

*/

delete obj.name;

console.log(obj.name); --> undefined

/*

对象写属性以及读属性的新方法:

写法:对象["属性名"] = 属性值;

读取:对象["属性名"];

对象的属性值可以是任意类型的值,属性的值可以是对象

var obj = new Object();

obj.test = new Object();


in 运算符

可以检查一个对象中是否含有指定的属性,有 返回true 无 返回false

*/

var obj = new Object();

console.log("name" in obj); --> false

// 基本类型 与 引用类型

var a = 123;

var b = a;

a++;

console.log(a, b);

var obj = new Object();

obj.name = "abc";

var obj2 = obj;

obj.name = "ccc";

console.log(obj.name, obj2.name);

// JS中的基本数据类型都是保存在栈内存中,值与值之间会独立存在的,修改一个不会影响另外一个

// 对象是保存在堆内存中的,每创建一个新的对象,都会在堆内存中开辟出一个新的空间

// 而变量保存的是对象的内存地址(对象的引用)

var obj1 = new Object();

var obj2 = new Object();

console.log(obj1 == obj2); --> false

/*

对象的字面量写法

*/

var obj = {

name:"www",

age:18

}

```

### 9.1 浅拷贝和深拷贝

```javascript

// 浅拷贝 将该对象的引用地址复制一份

var yj = {

name: 'yj',

hobby: 'call 666, rap, dance, basketball'

}

var lxl = yj;

lxl.name = 'lxl';

console.log(lxl, yj);

// 深拷贝 将该对象的所有属性复制一份到新的对象中

var lzx = {

ouxiang: 'cxk',

hobby: 'call 666, rap, dance, man'

}

var obj = {};

for(var i in lzx){

obj[i] = lzx[i];

}

console.log(lzx, obj);

```

### 9.2 继承

```javascript

原型链继承

// 父类 构造函数

function Person(name, age){

this.name = name;

this.age = age;

}

Person.prototype.say666 = function(){

console.log(this.name + 666);

}

var lzx = new Person('cxk', 66);

console.log(lzx);

// 子类 构造函数

function Monkey(weiba){

this.weiba = weiba;

}

// 原型链继承

Monkey.prototype = lzx;

Monkey.prototype.constructor = Monkey;

console.log(Monkey.prototype);

var m24 = new Monkey('50cm');

// 函数继承

// 父类 构造函数

function Person(name, age){

this.name = name;

this.age = age;

}

Person.prototype.say666 = function(){

console.log(this.name + 666);

}

var lzx = new Person('cxk', 66);

// 子类 构造函数

function Monkey(weiba, name, age){

Person.call(this, name, age);

this.weiba = weiba;

}

var swk = new Monkey('red', 'swk', 108);

console.log(swk);

swk.say666(); say666 is not a function

组合式继承

// 父类 构造函数

function Person(name, age){

this.name = name;

this.age = age;

}

Person.prototype.say666 = function(){

console.log(this.name + 666);

}

// 子类 构造函数

function Monkey(weiba, name, age){

Person.call(this, name, age);

this.weiba = weiba;

}

Monkey.prototype = new Person();

var m24 = new Monkey('a', 'b', 22);

console.log(m24);

```

#### 9.3 闭包

```javascript

闭包就是函数套函数,内层函数可以访问到外层函数的局部变量。

可以防止变量污染,不影响到全局作用域

会造成内存泄漏

```

# 十、函数

```javascript

函数

函数也是一个对象

函数中可以封装一些代码,在需要时可以执行这些代码

假设我现在有三行代码,在一百行的时候需要执行,在一万行也要执行

那我们就可以将这三行代码封装成一个函数,在需要执行的时候,调用一下函数就ok了

创建一个函数对象

var fun = new Function();

console.log(typeof fun); function

使用typeof 检查一个函数时,返回一个function

我们可以将要封装的代码以字符串的形式传递给构造函数

var fun = new Function("console.log('这是我的第一个函数')");

封装在函数中的代码不会立即执行

函数中的代码 会在函数调用的时候执行

函数调用语法:函数名字()

fun();

这时候你可以在控制台中看到打印的结果

函数对象具有普通对象的所有功能

fun.name = "abc";

console.log(fun.name); --> abc

在开发中我们不会这样来写一个函数

我们会使用 函数声明 来创建一个函数

语法:

function 函数名(形参1,形参2,形参...){

语句...

}

function fun(){

console.log(1);

}

fun();

函数表达式来创建一个函数 (匿名函数)

var fun = function(){

console.log(1);

}

fun();

函数的参数

function fun(a, b, c){ 声明的时候括号里面的参数叫做形参

形参就相当于在函数体中声明了变量但没有赋值

console.log(a, b, c); 在函数体中可以使用形参 但是如果没有传入实参,则返回默认值undefined

}

fun(1, 2, 3); 调用的时候括号里面传的参数叫做实参

函数的返回值

创建一个函数,用来计算三个数的和

function sum(a, b, c){

alert(a + b + c);

}

调用函数

sum(1, 2, 3);

这时候我们的函数只能将结果打印出来

我们用这个函数 只想得到结果 而不是输出结果 这时候我们就要在函数中使用 return关键字

function sum(a, b, c){

return a + b + c;

}

sum(1, 2, 3);

返回值我们写好了 问题是怎么拿到这个返回值呢 很简单 返回值就是函数的执行结果

console.log(sum(2, 3, 4));

也可以用一个变量来接收这个返回值

var result = sum(3, 4, 5);

console.log(result);

return 语句之后的代码 不会被执行 就像是break一样 而且return 后面可以跟任意类型的值

一个函数如果没有指定返回值,那这个函数的默认返回值就是undefined

console.log(alert(1));

练习:

定义一个函数,判断一个数字是否是偶数,如果是返回true,否则返回false

定义一个函数,根据用户输入的三个数字进行比较,最终将最大的值返回

立即执行函数(自执行函数)

(function(){

})

这样我们的匿名函数没有报错,但是这个时候并没有执行它,那执行它的方法就是在括号外面进行一次调用

(function(){

alert(1);

})()

函数在定义完之后,立即被调用

立即执行函数只会执行一次

也可以说是一次性函数

自执行函数的形参 实参 和 普通函数是一样的

对象中的方法

var obj = {

sayName:function(){

alert(1);

}

}

执行对象中的一个函数的方法就是 对象.属性名() 可以叫做 调用该对象下的一个方法

obj.sayName();

我们可以使用 for...in语句来枚举对象中的所有属性

for(var i in obj){

console.log(i); i 代表的就是对象中的属性名

}

JS中的作用域:

全局作用域:函数外就是全局作用域

全局作用域中有一个全局对象window,我们可以直接使用,它代表浏览器的窗口

是由我们的浏览器创建的

在全局作用域中,创建的变量都作为window对象的属性来保存

var a = 1;

window.a; --> 1

但是我们在使用的时候可以将window对象省略掉

创建的函数都会作为window对象的方法保存

function fun(){

alert(1);

}

window.fun();

同样window可以不写

alert() == window.alert()

函数作用域:函数内部

全局作用域中声明的变量,可以在任何地方使用

函数作用域中用var声明的变量,在全局作用域中无法使用

在函数作用域中使用一个变量时,它会先在函数中寻找,如果没有就去上一级找

JS代码在执行的时候,会有一个变量提升

将所有 var 关键字声明的变量,提升到代码的顶部

还会将所有命名函数提升到顶部

变量提升还存在于 函数作用域中

说出下面代码的执行结果

var a = 123;

function fun(){

alert(a);

}

fun();

var a = 123;

function fun(){

alert(a);

var a = 456;

}

fun(a);

alert(a);

var a = 123;

function fun(){

alert(a);

a = 456;

}

fun();

var a = 123;

function fun(a){

alert(a);

a = 456;

}

fun();

alert(a);

```

## 10.1 函数中的隐藏参数 this

​ this 会指向一个对象

​ 这个对象我们称为函数指向的上下文对象

​ 根据函数调用方式的不同,this会指向不同的对象

```javascript

function fun(){

console.log(this); window

}

以函数的形式调用时,this永远指向window

var obj = {

sayName: function(){

console.log(this);

}

}

以一个方法的形式来调用,this永远指向调用该方法的对象

构造函数中 this 指向的是一个空对象

```

## 10.2 工厂模式创建对象

​ 在函数中定义一个对象的模板 需要一个对象 就调用一次函数

​ 但是我们使用工厂模式创建的对象 没有一个类型的区别

​ 定义一个人的工厂 定义一个机器人的工厂 最终出来的对象都是Object 无法区分

```javascript

function person(name, sex, age){

var obj = {};

obj.name = name;

obj.sex = sex;

obj.age = age;

return obj;

}

var a = person("刘能", "male", 60);

var b = person("赵四", "male", 61);

```

## 10.3 构造函数

​ 构造函数就是用来创造对象实例的 和 工程模式相似

​ 构造函数就是一个普通的函数,不同的是构造函数首字母大写

​ 构造函数和普通函数的区别就是,调用的方式不同

​ 普通函数是函数名调用,而构造函数是通过new关键字调用(重要)

```javascript

function Person(name, age){

// 写法不同于 工厂模式

this.name = name;

this.age = age;

this.sayName = function(){

console.log(this.name);

}

}

var person1 = new Person("谢广坤", 180);

使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类

我们将通过一个构造函数创建的对象,称为是该类的实例

```

​ new 关键字的作用:

​ 1. 在函数体中声明了一个空对象

​ 2. 将函数体中的所有this 指向这个空对象

​ 3. 逐行执行函数中的代码

​ 4. 将空对象 return 返回出去

```javascript

function Person(){


}

var per = new Person();

function Dog(){


}

var dog = new Dog();

instanceof 可以检查一个对象是否是一个类的实例

语法:

对象 instanceof 类(构造函数)

如果是 返回 true 否则 返回 false

console.log(per instanceof Person); true

console.log(per instanceof Dog); false

所有的对象都是Object的后代

所以任何对象和Object做instanceof检查时都会返回true

```

## 10.4 构造函数的修改

```javascript

function Person(name, age){

this.name = name;

this.age = age;

this.sayName = function(){

console.log(this.name);

}

}

var person1 = new Person("谢广坤", 180);

在Person类中,为每一个对象都添加了一个sayName方法,

目前我们的方法都是在构造函数内部创建的,也就是构造函数执行一次就会创建一个sayName方法

而且所有的sayName方法都是唯一的

这样就导致了构造函数执行一次就会创建一个新的方法,执行一万次就创建一万个方法,

最重要的是这些方法做的事都是一样的

那我们可以让所有对象 共享这个方法 这样就没必要创建多个方法了

function Person(name, age){

this.name = name;

this.age = age;

this.sayName = sayName;

}

function sayName(){

console.log(this.name);

}

var person1 = new Person("谢广坤", 180);

我把sayName方法定义在了全局作用域中 这样的话就只有一个函数

我们每个对象只需要去调用公共的函数就OK了

但是我们把函数定义在全局作用域中 会污染我们的命名空间

```

## 10.5 原型 prototype

```javascript

function Person(){


}

var per = new Person();

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype

console.log(Person.prototype);

这个属性对应着一个对象,这个对象就是我们所说的原型对象

如果函数作为普通函数调用prototype没有任何作用

当函数通过构造函数调用时,它所创建的对象中都会有一个属性,指向该构造函数的原型对象

这个隐藏的属性叫做__proto__

console.log(per.__proto__ == Person.prototype); true

原型对象就相当与一个公共的区域,所有同一个类的实例都可以访问到这个原型对象

这时候我们可以将对象中公有的内容,统一放到原型对象中

```

## 10.6 原型的补充

```javascript

in 运算符 去检查对象中是否含有某个属性时,如果对象中没有,就会去原型中找

对象有hasOwnProperty()方法来检查对象自身中是否含有该属性

function Person(){


}

var per = new Person();

per这个实例的原型就是Person的原型,那原型呢又是一个对象,是对象就有原型

per.__proto__.__proto__ 实例的原型的原型就是Object Object的原型就是null 也就是没有了

现在来看 hasOwnProperty 属于哪个原型对象

per.__proto__.__proto__.hasOwnProperty("hasOwnProperty"); true

这个就是我们说的一个原型链 逐层往上找 直到没有

```

## 10.7 垃圾回收(GC)

```javascript

程序运行过程中会产生垃圾

这些垃圾积攒过多以后,会导致程序运行的速度过慢,

所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生的垃圾

var obj = new Object();

这个对象我们进行了一系列的操作 最后不使用这个对象了 这时候干啥呢

我们将这个变量与这个对象断开链接

var obj = null;

那这时候在堆内存中的这个对象 就是一个垃圾 虽然断开连接 但是它还存在

这种对象过多会占用大量的内存

问题就是咋样去清理这个垃圾

在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁

我们不需要也不能进行垃圾回收的操作

但是你如果不断开连接的话 浏览器不会去清理这个对象的

那我们需要做的就是 将用完的对象设置为 null

```

# 十一、数组

```javascript

数组也是一个对象

它和我们普通的对象功能类似,也是用来存储一些元素的

不同的是普通对象是使用字符串作为属性名的,

而数组是使用数字来作为索引操作元素

索引就是从0开始的整数

数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据

创建数组对象

var arr = new Array();

console.log(arr, typeof arr); [] object

向数组中添加元素

语法:数组[索引] = 值

arr[0] = 10;

console.log(arr); [10];

arr[1] = 20;

console.log(arr); [10,20];

读取数组中的元素

语法:数组[索引]

console.log(arr[0]); 10

console.log(arr[3]); undefined

如果读取数组中不存在的元素,不会报错,而会返回undefined

获取数组的长度

Array对象下的 length 属性会返回数组的长度

语法:数组.length

console.log(arr.length); 3

利用length属性 向数组最后一位添加一个新元素

语法:数组[数组.length] = 新值

arr[arr.length] = 33;

console.log(arr); [10,20,33]

```

## 11.1 数组的字面量写法

```javascript

使用字面量来创建数组

var arr = [];

console.log(typeof arr); object

使用字面量创建数组时,可以在创建时就指定数组中的元素

var arr = [1,2,3,4];

console.log(arr); [1,2,3,4]

使用构造函数创建数组时,也可以同时添加元素,将要写的元素写在实参中

var arr = new Array(1,2,3,4);

console.log(arr); [1,2,3,4];

当你在实参中只写一个数字的时候代表创建一个长度为多少的数组

var arr = new Array(10);

console.log(arr.length); 10

数组中的元素可以是任意的数据类型

var arr = [1,"a",true,null,undefined,{},[1,2,3]];

二维数组就是数组套数组

```

## 11.2 数组中的四个方法

```javascript

var arr = ["刘能","赵四","谢广坤"];

push方法 向数组的最后一位添加一个或多个新的元素,并返回数组的长度

var result = arr.push("宋小宝","小沈阳","小沈龙");

console.log(arr); ["刘能","赵四","谢广坤","宋小宝","小沈阳","小沈龙"]

push方法有返回值 返回新的长度

console.log(result); 6

pop方法 可以删除数组的最后一位并返回它

var result = arr.pop();

console.log(arr); ["刘能","赵四","谢广坤","宋小宝","小沈阳"]

console.log(result); "小沈龙"

unshift方法 向数组的第一位添加一个或者多个新元素 并返回新的数组长度

var result = arr.unshift("王宝强");

console.log(arr); ["王宝强","刘能","赵四","谢广坤","宋小宝","小沈阳"]

console.log(result); 6

向第一位添加完新元素以后,后面的元素的索引会被改变

shift方法 删除数组第一位的元素,并返回它

var result = arr.shift();

console.log(arr); ["刘能","赵四","谢广坤","宋小宝","小沈阳"]

console.log(result); "王宝强"

```

## 11.3 数组的遍历

```javascript

var arr = ["王宝强","刘能","赵四","谢广坤","宋小宝","小沈阳"];

所谓的遍历就是将数组中的所有元素都提取出来

console.log(arr[0],arr[1],arr[2]);

这样的取值太墨迹 而且也不方便

我们可以利用循环来遍历一个数组

for(var i = 0; i < 10; i++){

console.log(arr[i]);

}

这样子的话可以取出来元素 但是我的数组并没有这么多元素 所有我们的条件表达式不能写死

我们可以使用数组的length属性 来当作循环的条件

for(var i = 0; i < arr.length; i++){

console.log(arr[i]);

}

```

## 11.4 数组的练习

```javascript

function Person(name, age){

this.name = name;

this.age = age;

}

var per1 = new Person("赵四", 40);

var per2 = new Person("刘能", 36);

var per3 = new Person("谢广坤", 14);

var per4 = new Person("宋小宝", 19);

var per5 = new Person("宋晓锋", 30);

将五个对象装到一个数组中

创建一个函数,可以将数组中满18岁的对象提取出来

然后封装进一个新的数组中,并返回这个新数组

```

## 11.5 slice和splice

```javascript

slice方法 可以用来提取数组中指定的元素

该方法不会改变原数组,而是将截取到的元素封装在一个新数组中返回

该方法有两个实参:

1. 截取开始的位置的索引,包含开始索引

2. 截取结束的位置的索引,不包含结束索引

var arr = ["王宝强","刘能","赵四","谢广坤","宋小宝","小沈阳"];

arr.slice(0,2); ["王宝强","刘能"]

arr.slice(1,2); ["刘能"]

如果传递一个负值,则从后往前寻找

splice方法 可以用于删除数组中指定的元素

var result = arr.splice(0,2);

console.log(arr);["赵四","谢广坤","宋小宝","小沈阳"];

这个方法会影响到原数组,并将删除的元素作为返回值返回

console.log(result); ["王宝强","刘能"];

重要的是splice方法的实参有点不一样

第一个实参代表开始位置

第二个是从开始位置往后删除多少个

splice方法第二个实参以后 就是删除元素以后 要添加新的值

练习题

var arr = [1,2,3,4,5,1,3,4,1,2,5,6];

去除数组中重复的数字

```

## 11.6 数组剩余方法

```javascript

concat方法 可以连接两个或更多的数组,并返回结果

var arr = [1,2,3,4];

var arr1 = [1,2,3,4,5];

var result = arr.concat(arr1);

console.log(result); [1,2,3,4,1,2,3,4,5];

达到一个拼接数组的作用

join方法 可以将一个数组中的所有的元素都放在一个字符串中,并且值与值之间用逗号隔开

var arr = [1,2,3,4];

var result = arr.join();

console.log(result); "1,2,3,4"

reverse方法 可以颠倒数组中元素的顺序

var arr = [1,2,3,4,5];

var result = arr.reverse();

console.log(result); [5,4,3,2,1]

sort方法 对数组中的元素进行排序

sort排序是按照 unicode编码进行比较 也就是说会将数组中的值转换为字符串在进行比较 例如:

var arr = ["b","d","t","a",4,3,31,56];

var result = arr.sort();

console.log(result); [3, 31, 4, 56, "a", "b", "d", "t"]

练习:

冒泡排序

将数组中的元素进行从小到大排列

```

## 11.7 函数arguments

```javascript

在调用函数时,浏览器会传入两个隐藏的参数:

1. this

2. arguments

function fn(){

console.log(arguments);

}

fn();

arguments 是一个类数组对象 它不是数组 但是它也可以通过索引来操作数据,也可以获取长度

arguments instanceof Array false

arguments 代表函数调用传入的所有实参

arguments 的length属性就是用来获取实参的长度

这时候就算没有形参 我们也可以使用实参 arguments[0]就是第一个实参

```

## 11.8 函数原型上的三个方法

```javascript

call apply bind

三个方法都是用来改变函数this指向的

call apply 调用以后会立即调用该函数

bind 调用该方法以后 不会立即调用 而是将改变this后的函数当做返回值返回

三者传参

call(指向, 实参...)

apply(指向, [实参...])

bind(指向)(实参...)

var obj = {

name: 'abc',

age: 20

}

function fn(x, y){

this.name = '123';

console.log(this, x, y);

}

fn.call(obj);

fn.apply(obj);

var result = fn.bind(obj);

result();

```

# 十二、Date对象

```javascript

Date对象来表示一个时间

要用一个对象 就要new 一个实例出来

var d = new Date();

console.log(d); Wed Sep 04 2019 22:06:48 GMT+0800 (中国标准时间)

这要就能获取当前对应的时间

创建一个指定的时间对象

var d1 = new Date("11/06/2019 11:30:10");

console.log(d1);

日期的格式 月份/日/年 时:分:秒

下来就是看Date对象下的方法

d.getFullYear() 获取年份

d.getMonth() 获取月份

d.getDate() 获取天数

d.getDay() 获取周几

d.getHours() 获取小时

d.getMinutes() 获取分钟

d.getSeconds() 获取秒

d.getTime() 获取1970.1.1 到现在的毫秒数

d.setFullYear() 设置年份

d.setMonth() 设置月份

d.setDate() 设置天数

d.setDay() 设置周几

d.setHours() 设置小时

d.setMinutes() 设置分钟

d.setSeconds() 设置秒数

d.setTime() 设置毫秒

d.toUTCString() 转换为服务器时间

```

# 十三、Math对象

```javascript

我们的Math不需要创建实例 Math直接就是一个对象 它里面封装了一些数学运算相关的属性和方法

console.log(Math.PI); 3.1415926

Math下的方法:

Math.abs() 取绝对值

Math.ceil() 向上取整

Math.floor() 向下取整

Math.random() 随机数 0 - 1 之间的任意数字 包括 0

Math.pow(x, y)求x的y次幂

Math.round() 四舍五入

Math.max(x, y)返回x和y中最大值

Math.min(x, y)返回x和y中最小值

随机颜色案例

var colorArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];

function getRandomColor () {

var color = "#";

for(var i = 0; i < 6; i++){

var randomNumber = Math.floor(Math.random() * 16);

color += colorArr[randomNumber];

}

return color;

}

```

# 十四、正则表达式

#### 14.1 正则对象创建

```javascript

构造函数创建

new RegExp(规则, 修饰符)

修饰符: i 忽略大小写 g 全局匹配

字面量写法

/规则/修饰符

```

#### 14.2 正则对象下的方法

```javascript

var reg = /a/gi

检查字符串中是否符合正则表达式 符合返回 true 反之 false

reg.test()

```

#### 14.3 字符串下支持正则表达式的方法

```javascript

String.replace()

String.split()

String.search()

String.match()

```

#### 14.4 []

```javascript

[abc] == a | b | c

[0-9] 所有数字

[a-z] 所有小写字母

[A-Z] 所有大写字母

[A-z] 所有大小写字母

[0-9a-zA-Z_]

() 一组

```

#### 14.5 量词

```javascript

+ 1次/多次

* 0次/1次/多次

? 0次/1次

{x,y} 至少出现x次,最多出现y次

{x,} 至少出现x次

{x} 必须出现x次

?! 其后不紧跟 (?!)

?= 其后紧跟 (?=)

^ 首位出现

$ 末尾出现

```

#### 14.6 元字符

```javascript

. 除了换行符以外任意字符

\w 字母、数字、下划线

\W 非字母、数字、下划线

\d 数字

\D 非数字

\s 空格

\S 非空格

[\u4e00-\u9fa5] 所有中文

```

# 十五、DOM

#### 15.1 获取元素的方法

```javascript

document.getElementById('');


document.getElementsByClassName(''); IE 8 不兼容

document.getElementsByTagName('');

document.querySelector('css选择器'); Node

document.querySelectorAll('css选择器'); NodeList

```

#### 15.2 Node节点下的属性:

```javascript

nodeName 返回大写的标签名

nodeType 返回节点类型 1 Element 2 属性 3 text 9 document

nodeValue 返回节点的值 Node节点的nodeValue返回null 文本节点返回文本内容

innerText 可读写节点内容 IE的 不会写进去标签 不会解析标签 只解析内容

innerHTML 可读写节点内容 除IE以外 将标签解析到HTML中 读取的时候会拿到标签

className 可读写类名

id 可读写id名

style 读取的时候会拿到一个对象,这个对象中有每个行内css属性 写的时候会覆盖行内样式

src 可读取src属性值

标签内的属性 都可以用一个方法来替代

Node.setAttribute('属性名', '属性值') 设置自定义属性

Node.getAttribute('属性名') 获取属性值

```

#### 15.3 表单元素属性

```javascript

// 表单元素属性

type 可读写input的类型

disabled true 禁用 false 开启

value 可读写input的内容

placeholder 可读写文本占位符

checked 多选框是否被选中 boolean

```

#### 15.4 DOM节点的查找属性

```javascript

// DOM节点的查找属性

Node.parentNode 找他父级节点

Node.children 找所有子级节点 Node.childNodes 高版本浏览器会获取到文本节点 IE中获取的就是Node节点

Node.nextElementSibling 查找下一级兄弟节点 Node.nextSibling IE的 你懂


Node.previousElementSibling 查找上一级兄弟节点 Node.previousSibling IE的

Node.firstElementChild 查找第一个子级节点 Node.firstChild IE的

Node.lastElementChild 查找最后一个子级节点 Node.lastChild IE的

```

#### 15.5 DOM的增删改 方法

```javascript

// DOM的增删改 方法

创造一个标签

document.createElement()

向该元素末尾添加新的元素

Node.appendChild()

向目标元素之前添加一个新元素

Node.insertBefore(新元素, 目标)

删除元素

Node.removeChild(删除目标)

替换元素

Node.replaceChild(新元素, 替换目标)

```

#### 15.6 DOM节点下的事件

```javascript

onclick 单击事件

onmouseover 鼠标移上事件 触碰到子级也会触发一次

onmouseout 鼠标移出事件 触碰到子级也会触发一次

onmouseenter 鼠标移上事件 解决上述问题

onmouseleave 鼠标移出事件 解决上述问题

onmousedown 鼠标按下事件

onmouseup 鼠标弹起事件

onmousemove 鼠标移动事件

onmousewheel 鼠标滚轮事件 没有滚动条也可以触发

onscroll 鼠标滚轮事件 有滚动条才会触发

onfocus 获取焦点事件

onblur 失去焦点事件

onchange 内容发生改变时触发的事件

onkeydown 键盘按下事件

onkeyup 键盘弹起事件

onkeypress 键盘按下事件

```

#### 15.7 定时器

```javascript

setInterval(function(){}, time) 每隔多少毫秒执行一次匿名函数

clearInterval()

setTimeout(function(){}, time) 多少毫秒之后执行一次匿名函数

clearTimeout()

```

#### 15.8 事件对象

```javascript

所有的事件处理函数中,都有一个参数event,这个event就是事件对象

事件对象获取兼容:形参event 可以直接获取 google window.event IE

常用的事件对象下的属性有:

target 触发事件的元素

srcElement IE中的target

wheelDelta 判断滚轮向下滚还是向上滚 IE google

deltaY 判断滚轮向下滚还是向上滚 google

detail 判断滚轮向下滚还是向上滚 firefox

clientX 当前鼠标距离浏览器最左边的距离

clientY 当前鼠标距离浏览器最上边的距离

offsetX 获取当前鼠标距离事件源左边的距离

offsetY 获取当前鼠标距离事件源上边的距离

pageX 获取当前鼠标距离浏览器左部的距离(包括被卷曲的距离)

pageY 获取当前鼠标距离浏览器顶部的距离(包括被卷曲的距离)

screenX 获取当前鼠标距离屏幕左侧的距离

screenY 获取当前鼠标距离屏幕顶部的距离

```

#### 15.9 事件委托

```javascript

将子级的事件委托给父级去做

优点:

1. 解决了动态添加元素无法绑定事件

2. 优化性能,将多个事件转换为一个事件

缺点:

1. this 指向被破坏, 解决方法为 利用事件对象下的target属性当做this

```

#### 15.10 事件传播机制(事件代理)

```javascript

1. 捕获阶段

2. 目标阶段

3. 冒泡阶段

事件触发默认是在冒泡阶段触发

新的绑定事件的方法是 addEventListener('事件名', '匿名函数', booolean) true 代表 捕获阶段触发 默认 false

addEventListener 不会覆盖事件 会叠加

```

# 十六、BOM

#### 16.1 三大家族

```javascript

offset client scroll

offsetWidth 获取元素宽度(自身宽度 + 内填充 + 边框)

offsetHeight 获取元素高度(自身高度 + 内填充 + 边框)

offsetLeft 获取元素距离上一级定位元素的左边距

offsetTop 获取元素距离上一级定位元素的上边距

offsetParent 获取上一级定位元素

clientWidth 获取元素宽度(自身宽度 + 内填充)

clientHeight 获取元素高度(自身高度 + 内填充)

scrollWidth 获取元素的宽度(自身宽度 + 内填充 + 溢出范围)

scrollHeight 获取元素的宽度(自身高度 + 内填充 + 溢出范围)

scrollLeft 获取页面x轴被卷曲的距离

scrollTop 获取页面y轴被卷曲的距离

document.body.scrollTop || document.documentElement.scrollTop

```

#### 16.2 navigator对象

```javascript

返回浏览器信息

var result = navigator.userAgent;

/chrome/gi.test(result); // google chrome

/msie/gi.test(result); // ie

/firefox/gi.test(result); // firefox

```

#### 16.3 location对象

```javascript

返回地址栏信息

location.href 浏览器地址栏所有信息

location.reload() 刷新网页

```

#### 16.4 history对象

```javascript

浏览器历史记录

history.back() 上一页

history.forward() 下一页

history.go(指定页数) 跳转到指定页数

```

#### 16.5 获取css属性

```javascript

IE9及以下

Node.currentStyle

google chrome

getComputedStyle(Node)

```

#### 16.6 window下的方法和属性

```javascript

加载事件

DOM元素加载完毕 css加载完毕 外部资源加载完毕后触发的

window.onload = function(){


}

window.innerWidth 返回浏览器窗口宽度

window.innnerHeight 返回浏览器窗口高度

window.onresize = function(){

浏览器窗口发生改变的时候触发的事件

}

```

# 十七、jQuery

jquery 就是 javascript 的库

```html

$ == jQuery

引入

<script src='jquery1.x.js'></script>

```

```javascript

$()

实参为css选择器的时候,用来获取DOM节点,返回一个jquery实例对象

实参中传入一个原生Node节点,会将这个Node节点转换为jQuery实例对象

实参为匿名函数,代表加载事件 DOM元素加载完毕以后就会触发这个函数

实参为标签名,代表创建一个标签

```

#### 17.1 jQuery 常用方法

```javascript

text() === innerText

html() === innerHTML

css(对象) === style

attr() === setAttribute() getAttribute()

val() === value

addClass() === className

removeClass() === className 不传实参的时候 清空class 传入指定的class就清除指定的class

toggleClass() 有则删 没则加

find(选择器) 查找子级

closest(选择器) 查找父级

eq(索引值) 查找当前jQuery对象中第几个元素

index() 获取当前元素所在jQuery对象中的索引值

append() 向目标元素最后一位添加新的元素

appendTo() 将新元素添加到目标元素最后一位

prepend() 向目标元素第一位添加新的元素

prependTo() 将新元素添加到目标元素第一位

remove() 删除指定元素

before() 向当前元素之前插入一个新的元素

after() 向当前元素之后插入一个新的元素

clone() default false 不克隆事件 true 克隆事件

动画

fadeIn 淡入

fadeOut 淡出

fadeToggle 淡入出

slideDown 卷闸门降

slideUp 卷闸门升

slideToggle 卷闸门升降

show 展示

hide 隐藏

toggle 展示/隐藏

animate(css对象, 时间) 自定义动画

```

#### 17.2 jQuery 绑定事件

所有事件 去掉on click(function(){事件处理函数})

#### 17.3 jQuery 加载事件

```javascript

// window.onload 加载完所有资源后才会触发(视频音乐都是)

// 加载完HTML元素后就会触发

$(docuemnt).ready(function(){

})

$(function(){

})

```

# 十八、AJAX

AJAX == Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

浏览器只能在加载页面的时候去发送`HTTP`请求,在页面不刷新的情况下我们是无法去操作一个`http`请求的。

访问一个网站的时候通过域名访问到服务器,服务器返回HTML代码,这是一条HTTP请求,然后HTML中有引入外部资源的标签,浏览器解析到这些标签的时候就会触发`HTTP`请求,去获取外部资源,一个网页是由很多次`HTTP`请求拿到资源并展现给客户。

AJAX出现的目的就是为了让开发人员在页面不刷新的情况下去发送一条`HTTP`请求。

AJAX 就是 XMLHttpRequest()构造函数,通过它的实例对象我们就可以操作`HTTP`请求了。

```javascript

同步写法

1. 实例化一个XML对象

var http = new XMLHttpRequest();

2. 规划一条http请求

http.open(method, url, false); sync/async 同异步 false 同步 true 异步 默认值为 true

3. 发送http请求

http.send();

4. 接收服务器返回的数据

http.responseText

异步写法

1. 实例化一个XML对象

var http = new XMLHttpRequest();

2. 利用监听事件,监听当前http请求的进度

http.onreadystatechange = function(){

http.readyState 准备状态

http.status 状态码


准备状态分为五个:

0 实例化了XMLHttpRequest()对象

1 调用了open,没有send

2 调用了send,服务器没有给出响应

3 正在解析响应内容

4 响应内容解析完毕,客户端可以使用


状态码常见的有:

200 OK

304 有缓存,服务器没有返回新数据

404 Not Found

403 服务器拒绝

503 服务器关闭


if(http.readyState == 4){

if(http.status == 200){

http.response; 拿到相应数据

}

}

}

3. 规划一条http请求

http.open(method, url, true); sync/async 同异步 false 同步 true 异步 默认值为 true

4. 发送http请求

http.send();

```

#### 18.1 同源组策略(跨域)

浏览器内部有这么一个机制用来检查这条HTTP请求是否符合规范。

检查的是:协议,域名,端口 三者都相同就不会发生跨域报错

跨域解决方案:

​ 1. JSONP

​ 2. CORS(跨域资源访问)

​ 3. 服务器代理

### 18.2 JSON

[JSON](
https://baike.baidu.com/item/JSON)([JavaScript](
https://baike.baidu.com/item/JavaScript) Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。

JSON支持几种数据类型:

​ String Number Boolean Object Array null

javascript内置对象JSON

​ JSON.parse() 将JSON数组/对象 转换为 JS数组/对象

​ JSON.stringify() 将JS对象/数组 转换为 JSON数组/对象

### 18.3 JSONP解决跨域

事先声明一个回调函数,利用script标签向服务端发送一个http请求,该回调函数的函数名通过请求地址的callback参数传递给服务端,服务端接收到该请求以后,解析callback参数的参数值,返回一段调用该函数的JS代码,服务端将返回的数据传递到函数的实参中。

注意事项:

​ 1. JSONP 不是AJAX

​ 2. JSONP 支持GET请求,不支持POST请求

​ 3. JSONP需要前后端共同来完成,请求参数必须统一(默认为callback)

​ 4. JSONP不是一个标准的技术,是一个黑科技

#### 18.4 jQuery AJAX

```javascript

var option = {

url: 请求地址,

type: 请求方式 GET POST,

data: {

传递给后端的参数

},

dataType: 返回的数据类型 (jsonp),

success: function(data, textStatus, XHR){

请求成功以后的回调函数

},

error: function(XHR, textStatus, error){

请求失败后的回调函数

},

complete: function(){

请求发送完毕以后触发的回调函数

}

}

$.ajax(option);

$.get(url, data, success)

$.post(url, data, success)

var result = $.ajax();

result.success(function(){

成功后的回调函数

})

result.error(function(){

失败后的回调函数

})

result.done(function(){

成功后的回调

})

result.then(function(){

成功后的回调函数

}, function(){

失败后的回调函数

})

```

# 十九、cookie、localStorage、sessionStorage(本地存储)

```javascript

cookie 大小限制最大为4KB 必须在http\https协议上才可以运行

在发送http请求的时候 cookie 可以传递给后端

后端也可以给浏览器写 cookie

cookie的设置,读取,删除必须由前端工作人员自己封装

cookie 有生命周期

cookie 一般浏览器限制50条

localStorage 大小大约为5MB,也可以更大

发请求的时候 不会附加在 http\https请求上

永久存储在客户端上

sessionStorage 大小大约为5MB,也可以更大

发请求的时候 不会附加在 http\https请求上

浏览器||当前页面 关闭以后就会清除

function setCookie(key, value, expires){

var date = new Date();

date.setDate(date.getDate() + expires);

document.cookie = key + '=' + value + ';expires=' + date.toUTCString();

}

function removeCookie(key){

setCookie(key, 1, -1);

}

function getCookie(key){

var data = document.cookie;

if(data.length == 0){

return undefined;

}else{

var result = new Object();

data = data.replace(/\s/g, '');

if(/;/.test(data)){

var arr = data.split(';');

arr.forEach(function(item, index){

var arr = item.split('=');

result[arr[0]] = arr[1];

})

}else{

var arr = data.split('=');

result[arr[0]] = arr[1];

}

return result[key];

}

}

localStorage.setItem()

localStorage.getItem()

localStorage.removeItem()

localStorage.clear()

sessionStorage.setItem()

sessionStorage.getItem()

sessionStorage.removeItem()

sessionStorage.clear()

```

# 二十、ES five

#### 1.严格模式

```javascript

开启方法:

在执行的代码顶部写一个字符串 'use strict'

函数内部顶端也可以开启 同上

严格模式

为了消除JavaScript语法的不合理不严谨之处,减少怪异行为

消除代码运行的不安全之处,保证代码安全执行

提高编译效率,增加运行速度

为未来新版本的JavaScript做好铺垫

1. 必须使用 var 关键字声明变量

2. eval()函数有独立的作用域

3. 对象下不能存在相同的属性名

4. 禁止this指向 window

函数内部也可以开始严格模式

```

#### 2. eval()

将字符串转换为JS代码并执行

#### 3. Object.defineProperty()

```javascript

给目标对象扩展属性描述

描述默认为false

var obj = {};

Object.defineProperty(obj, 'litwo', {

value: 'cxk', 属性值

writable: true, 是否可以修改内容

enumerable: true, 是否可以被for in 枚举

configurable: true 是否可以被 delete 删除

});

```

# 二十一、ES Six

## 1. let const

```javascript

1. 没有变量提升

2. 不能重复声明变量

3. 块级作用域

const

4. 声明的常量不能被修改

```

## 2. 解构赋值

```javascript

数组(字符串)的解构赋值 [] = Array

对象的解构赋值 {key: 自定义名字} = Object

函数形参的解构赋值

let arr = [1, 2, 3];

let [a, b, c] = arr;

let obj = {name: 1};

let {name: n} = obj;

```

## 3. 函数扩展

```javascript

name 属性 返回函数的函数名

函数形参的默认值

rest参数 剩余的实参

***箭头函数 this的指向发生改变 this指向定义的作用域中的this

匿名函数可以改写为 箭头函数

let fn = () => {

console.log(this);

}

形参只有一个的时候 可以省略掉小括号

返回语句只有一条的时候 可以省略掉代码块

```

## 4. 模板字符串

```javascript

``

模板字符串中拼接变量 使用 ${}

let str = 'china';

let str1 = 'No.1';

console.log('say${str}${str1}'); --> saychinaNo.1

```

## 5. 对象的扩展

```javascript

let name = 'abc';

let obj = {

name,

obj(){

// 方法可以省略掉: function

}

}

Object.assign() 将多个对象整合到一个对象中


Object.getOwnPropertyDescriptor() 获取对象下其中一个属性的 所有描述


Object.getOwnPropertyDescriptors() 获取对象下所有属性的描述


Object.getOwnPropertySymbols() 获取对象下所有symbol属性

```

## 6. 数组的扩展

```javascript

扩展运算符 ...

展开数组、伪数组

let arr = document.querySelectorAll('ul > li');

let newarr = [...arr];

```

## 7. Symbol 函数

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入`Symbol`的原因。

```javascript

不能用 new 关键字生成

const sym = Symbol(描述);

sym.description 获取symbol的描述字符串

一般会使用在 对象的属性中

在对象中使用 symbol 必须使用中括号语法

let obj = {

[sym]: 1

}

obj[sym];

```

## 8. Set容器

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set容器不接收重复的值

```javascript

let set = new Set();

set.add(); 向set容器中添加新元素

set.delete(); 删除set容器中指定的元素(通过value来删除)

set.has(); 检查set容器中是否含有这个值

set.clear(); 清空set容器

```

## 9. Map容器

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

```javascript

let map = new Map([[key, value], [key, value]]);

map.set(key, value); 向map容器中加入新的键值对

map.get(key); 读取map容器中key的value

map.has(key); 检查map容器中是否含有这个键值对

map.delete(key); 删除map容器中的键值对

map.clear(); 清空map容器

```

## 10. Class 类

Class 类 就是 构造函数的另外一种写法

可以解决构造函数继承的问题

继承用到的是 extends 关键字以及super函数

```javascript

class Person {

constructor(name, age){

this.name = name;

this.age = age;

this.hi = function(){

console.log(1);

}

}

sayHi(){ // 写在原型对象上的方法

console.log(this.name);

}

}

let p = new Person('yj', 22);

console.log(p);

p.sayHi();

// 继承 Person 类

class Son extends Person {

constructor(name, age, gender){

super(name, age); // 调用Person类的constructor

this.gender = gender;

}

sayHi(){ // 给子类原型对象添加一个方法

console.log(this.age);

}

}

let p1 = new Son('a', 22,'xxx');

console.log(p1);

p1.sayHi();

```

## 11. Promise对象

解决 callback hell 回调地狱

用同步的流程 展示 异步的操作

回调函数的代码 是层层嵌套

promise 可以将 层层嵌套的代码 展开成一条直线(同步)

promise 的状态:

pending 初始化状态

fulfilled 成功

rejected 失败

状态只能发生一次改变 一旦改变为其中一个以后 就不能切换其他状态

```javascript

function getJson(url){

return new Promise((resolve, reject) => {

let xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) {

if(xhr.status == 200){

resolve(xhr.response);

}else {

reject('error');

}

}

}

xhr.open('GET', url);

xhr.send();

})

}

getJson('https://pujie1213.top:423/rcGame').then((data) => {

console.log(data);

}).catch((err) => {

console.log(err);

})

promise.then(成功的回调, 失败的回调)

promise.then(成功的回调)

promise.then(成功的回调).catch(失败的回调)

then的返回值就是成功回调函数的返回值 是一个 promise 对象

在调用一次then 就是 上一次返回的promise对象的值

promise.finally() 链式调用执行完毕以后,就会执行finally

```

## 12. Proxy对象 和 Reflect对象

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

```javascript

let obj = {

name: 'yj666',

age: 22

}

let pro = new Proxy(obj, {

set(target, key, value){

console.log(`监听到改变属性${key}的值为${value}`);

Reflect.set(target, key, value);

},

get(target, key){

console.log(`监听到获取属性${key}`);

return Reflect.get(target, key);

}

})

console.log(pro);

pro.name = 'lzx';

console.log(obj.name);

Reflect.set(target, key, value); 给目标对象添加属性和值

Reflect.get(target, key); 获取目标对象的属性值

```

## 13. iterator接口机制 和 for...of循环

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令`for...of`循环,Iterator 接口主要供`for...of`消费。

Iterator 的遍历过程是这样的。

(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

(2)第一次调用指针对象的`next`方法,可以将指针指向数据结构的第一个成员。

(3)第二次调用指针对象的`next`方法,指针就指向数据结构的第二个成员。

(4)不断调用指针对象的`next`方法,直到它指向数据结构的结束位置。

每一次调用`next`方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含`value`和`done`两个属性的对象。其中,`value`属性是当前成员的值,`done`属性是一个布尔值,表示遍历是否结束。

```javascript

function iterator(...values){

let index = 0;

return {

next(){

return {value: values[index++],done: index > values.length ? true : false}

}

}

}

let iter = iterator('赵四', '刘能', '广坤', '李泽欣', '超星空', '巧碧螺');

console.log(iter.next());

console.log(iter.next());

console.log(iter.next());

console.log(iter.next());

console.log(iter.next());

console.log(iter.next());

console.log(iter.next());

let arr = ['赵四', '刘能', '广坤', '李泽欣', '超星空', '巧碧螺'];

for(let i of arr){

console.log(i);

}

// 给对象添加iterator接口

let obj = {

name: 1,

age: 22,

[Symbol.iterator]: function(){

let index = 0;

let arr = Object.keys(this);

return {

next: () => {

return {value: this[arr[index++]],done: index > arr.length ? true : false};

}

}

}

}

for(let i of obj){

console.log(i);

}

```

## 14. Generator 函数

Generator 函数是一个状态机,封装了多个内部状态。

执行Generator函数是会返回一个遍历器对象,通过调用遍历器对象下的next方法来去改变函数内部的状态,

函数内部的yield语句执行完毕以后再去调用next方法就会一直返回{value: undefined, done: true}

Generator 函数就是一个普通函数,不同的是 函数 与 函数名之间加了一个 * 号,普通函数只会 被调用 或者 定义,generator函数可以暂停。

```javascript

function* cxk(){

let a = yield 'A';

console.log(`a:${a}`);

let b = yield 'B';

console.log(`b:${b}`);

let c = yield 'C';

console.log(`c:${c}`);

}

let iter = cxk();

iter.next(); --> {value: yield后的表达式的返回值,done: false}

```

## 15. async 函数 ES2017

Generator的语法糖

await 关键字的作用 暂停当前async函数等待 表达式的返回结果 拿到表达式的返回结果后 接着执行async函数 如何再一次遇到await 就会进行上一次的操作

```javascript

function getJson(url){

return new Promise((resolve, reject) => {

let xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) {

if(xhr.status == 200){

resolve(xhr.response);

}else {

reject('error');

}

}

}

xhr.open('GET', url);

xhr.send();

})

}

async function get(){

let a = await getJson('https://pujie1213.top:424/rcGame');

console.log(`a:${a}`);

let b = await getJson('https://pujie1213.top:424/rcGame');

console.log(`b:${b}`);

}

get();

```

# 二十二、模块化开发

## 1.AMD(异步模块定义)

AMD主要用于浏览器端,require.JS 就是它的实现

异步加载模块不会造成页面加载的阻塞

RequireJS是一个工具库,主要用于客户端的模块管理。它可以让客户端的代码分成一个个模块,实现异步或动态加载,从而提高代码的性能和可维护性。它的模块管理遵守[AMD规范](
https://github.com/amdjs/amdjs-api/wiki/AMD)(Asynchronous Module Definition)。

语法:

​ 定义模块

```javascript

//定义没有依赖的模块

define(function () {

return {

method1: function() {},

method2: function() {},

};

})

//定义有依赖的模块

define([module1,module2],function (module1,module2) {

return 模块

})

```

​ 引入模块

```javascript

require([module1,module2],function (module1,module2) {

//使用module1,module2

})

```

## 2.ES6 Module

```javascript

暴露模块

export const a = 10;

export const obj = {};

const obj1 = {};

export {obj1};

暴露默认模块

export default {


}

export default function(){


}

引入

按需引入

import {a,obj} from 模块路径

引入所有

import 自定义名字 from 模块路径

script标签使用ES6 Module 要注意 type="module"

ES6 Module 是异步的 下载完毕后就执行

```

## 3. CommenJS规范(Nodejs)

```javascript

引入模块

require(模块名);

暴露模块

exports.属性名 = 属性值

module.exports = {


}

exports 就是 module.exports 的引用

require引入模块是同步的 必须是模块引入成功以后才会执行下面的代码

```

## 4.CMD 规范

需要的时候 require 引入进来 延迟加载

```javascript

定义模块

define(function(require, exports, module){

require() 引入其他模块

exports 暴露属性

module.exports = {} 暴露

module 当前模块的详情信息 以及依赖模块的信息

})

引入模块

seajs.use(模块路径, function(模块名){


})

```