JavaScript基础(自用)

184 阅读23分钟

JavaScript基础

1.JS的编写位置

1.可以将js代码编写到标签的onclick属性中,当我们点击按钮时,js代码才会执行(不推荐使用)
<button onclick="alert('讨厌,你点我干嘛~~');">点我一下</button>
2.可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码
<a href="javascript:alert('让你点你就点!!');">你也点我一下</a>
3.如果需要超链接点完没有反应,则可以使用“javascript:;”
<a href="javascript:;">你也点我一下</a>

2.基本语法

1.JS中严格区分大小写
2.JS中每一条语句以分号(;)结尾。 
    如果不写分号,浏览器会自动添加,但是会消耗一些系统资源,
    而且有些时候,浏览器会加错分号,所以在开发中分号必须写。
3.JS中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化

3.字面量和变量

(1)字面量

字面量,都是一些不可改变的值
比如 :1 2 3 4 5 
字面量都是可以直接使用,但是我们一般都不会直接使用字面量

(2)变量

定义:
变量可以用来保存字面量,而且变量的值是可以任意改变的,变量更加方便我们使用,所以在开发中都是通过变量去保存一个字面量,而很少直接使用字面量,可以通过变量对字面量进行描述
声明变量:
在js中使用var关键字来声明一个变量: var a;	

4.标识符

在JS中所有的可以由我们自主命名的都可以称为是标识符
例如:变量名、函数名、属性名都属于标识符
命名一个标识符时需要遵守如下的规则:
1.标识符中可以含有字母、数字、_、$
2.标识符不能以数字开头
3.标识符不能是ES中的关键字或保留字
4.标识符一般都采用驼峰命名法
- 首字母小写,每个单词的开头字母大写,其余字母小写
helloWorld xxxYyyZzz 
- JS底层保存标识符时实际上是采用的Unicode编码,
所以理论上讲,所有的utf-8中含有的内容都可以作为标识符

5.数据类型

数据类型指的就是字面量的类型,在JS中一共有六种数据类型
其中Object是引用数据类型,其他五种则是基本数据类型
中文名类型
字符串String
数值Number
布尔值Boolean
空值Null
未定义Undefined
对象Object

(1)String(字符串)

- 在JS中字符串需要使用引号引起来
- 使用双引号或单引号都可以,但是不要混着用
- 引号不能嵌套,双引号不能放双引号,单引号不能放单引号

转义符

在字符串中我们可以使用\作为转义字符,当表示一些特殊符号时可以使用\进行转义
\" 表示 "
\' 表示 '
\n 表示换行
\t 制表符
\\ 表示\

(2)Number(数值)

1.JS中所有的数值都是Number类型,包括整数和浮点数(小数)
2.JS中可以表示的数字的最大值:Number.MAX_VALUE
3.大于0的最小值:Number.MIN_VALUE 
4. 如果使用Number表示的数字超过了最大值,则会返回一个
		 Infinity 表示正无穷
 		-Infinity 表示负无穷
5. 如果使用JS进行浮点运算,可能得到一个不精确的结果,所以千万不要使用JS进行对精确度要求比较高的运算。
	在JS0.1 + 0.2 != 0.3

关于 Number 类型的 typeof

可以使用一个运算符 typeof 来检查一个变量的类型(语法:typeof 变量)
检查字符串时,会返回string。检查数值时,会返回number1.typeof Infinity 会返回 number
2.typeof NaN 会返回 numberNaN 是一个特殊的数字,表示Not A Number

(3)Boolean 布尔值

布尔值只有两个,主要用来做逻辑判断
true  表示真
false 表示假
使用typeof检查一个布尔值时,会返回 boolean

(4)Null(空值)

Null(空值)类型的值只有一个,就是null
null这个值专门用来表示一个为空的对象
使用typeof检查一个null值时,会返回object

(5)Undefined(未定义)

Undefined(未定义)类型的值只有一个,就undefind
当声明一个变量,但是并不给变量赋值时,它的值就是undefined
使用typeof检查一个undefined时也会返回undefined

6. 强制类型转换

指将一个数据类型强制转换为其他的数据类型。
类型转换主要指,将其他的数据类型,转换为: String Number Boolean

(1)将其他的数据类型转换为String

方式一:调用被转换数据类型的toString()方法
1.该方法不会影响到原变量,它会将转换的结果返回
2.但是注意:null和undefined这两个值没有toString()方法,如果调用他们的方法,会报错

方式二:调用String()函数,并将被转换的数据作为参数传递给函数
1.使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法。
2.但是对于null和undefined,就不会调用toString()方法。
 - 它会将 null 直接转换为 "null"
 - 将 undefined 直接转换为 "undefined"

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

方式一:使用Number()函数
1.字符串 --> 数字
    (1) 如果是纯数字的字符串,则直接将其转换为数字
    (2) 如果字符串中有非数字的内容,则转换为NaN
    (3) 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0
2 布尔 --> 数字
    (1) true 转成 1
    (2) false 转成 0
2.null --> 数字 0
3.undefined --> 数字 NaN

方式二:这种方式专门用来对付字符串
1.parseInt() 把一个字符串转换为一个整数:
	(1)可以将一个字符串中的有效的整数内容去出来,然后转换为Number
2.parseFloat() 把一个字符串转换为一个浮点数
	(2)parseFloat()作用和parseInt()类似,不同的是它可以获得有效的小数
*注意:如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后在操作。

其他类型的数字

在js中,如果需要表示16进制的数字,则需要以0x开头
如果需要表示8进制的数字,则需要以0开头
如果要要表示2进制的数字,则需要以0b开头
但是不是所有的浏览器都支持

(3)将其他的数据类型转换为Boolean

方法:使用Boolean()函数
1. 数字 ---> 布尔
 - 除了0和NaN,其余的都是true
2.字符串 ---> 布尔 :
 — 除了空串,其余的都是true
3.null和undefined都会转换为false
4.对象也会转换为true

7.运算符

(1)定义

运算符也叫操作符。通过运算符可以对一个或多个值进行运算,并获取运算结果
比如:typeof就是运算符,可以来获得一个值的类型,会将该值的类型以字符串的形式返回
number string boolean undefined object

(2)算数运算符

1.当对非Number类型的值进行运算时,会将这些值转换为Number然后在运算
2.任何值和NaN做运算都得NaN
3.加法运算 “+”
(1)“+” 可以对两个值进行加法运算,并将结果返回。
(2)如果对两个字符串进行加法运算,则会做拼串。
(3)任何的值和字符串做加法运算,都会先转换为字符串,然后再和字符串做拼串的操作。
	注:- 我们可以利用这一特点,来将一个任意的数据类型转换为String
       - 我们只需要为任意的数据类型 + 一个 "" 即可将其转换为String
       - 这是一种隐式的类型转换,由浏览器自动完成,实际上它也是调用String()函数
4.减法运算“-”:- 可以对两个值进行减法运算,并将结果返回。
5.乘法运算 "*":* 可以对两个值进行乘法运算
6.除法运算 “/”:/ 可以对两个值进行除法运算
7.求余数 “%”:% 取模运算(取余数)
8.任何值做“-”, “*” , “/” 运算时都会自动转换为Number
 	注:- 我们可以利用这一特点做隐式的类型转换
	   - 可以通过为一个值  “-0” , “*1” , “/1”  来将其转换为Number
	   - 原理和Number()函数一样,使用起来更加简单
9.Number+StringNumber-String 会把String转换成Number在做运算。
	例如:100 - "1" = 99100 + “1” = 101

(3)一元运算符

一元运算符,只需要一个操作数
1. + 正号:正号不会对数字产生任何影响
2. - 负号:- 负号可以对数字进行负号的取反
3. 对于非Number类型的值,
(1)它会将先转换为Number,然后在运算
(2)可以对一个其他的数据类型使用+,来将其转换为number3)它的原理和Number()函数一样

(4)自增 ++ 自减 --

自增 ++
1.通过自增可以使变量在自身的基础上增加1,对于一个变量自增以后,原变量的值会立即自增12.自增分成两种:后++(a++) 和 前++(++a)	
     无论是a++ 还是 ++a,都会立即使原变量的值自增1
     不同的是a++ 和 ++a的值不同
     a++的值等于原变量的值(自增前的值)
     ++a的值等于新值 (自增后的值)

自减 --
1.通过自减可以使变量在自身的基础上减1
2.自减分成两种:后--(a--) 和 前--(--a)
     无论是a-- 还是 --a 都会立即使原变量的值自减1
     不同的是a-- 和 --a的值不同
     a-- 是变量的原值 (自减前的值)
     --a 是变量的新值 (自减以后的值)	  	

(5)逻辑运算符

! 非

1.“!” 可以用来对一个值进行非运算,所谓非运算就是值对一个布尔值进行取反操作,truefalsefalsetrue2.如果对一个值进行两次取反,它不会变化。
3.如果对非布尔值进行元素,则会将其转换为布尔值,然后再取反
    所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值
    可以为一个任意数据类型取两次反,来将其转换为布尔值,原理和Boolean()函数一样

&& 与

1.&& 可以对符号两侧的值进行与运算并返回结果
2. 运算规则
(1)  两个值中只要有一个值为false就返回false,
(2)  只有两个值都为true时,才会返回true
(3) 代码运行规则:JS中的“与”属于短路的与,如果第一个值为false,则不会看第二个值

|| 或

1.||可以对符号两侧的值进行或运算并返回结果
2. 运算规则:
(1) 两个值中只要有一个true,就返回true2) 如果两个值都为false,才返回false3) 代码运行规则: JS中的“或”属于短路的或,如果第一个值为true,则不会检查第二个值

(6)赋值运算符

可以将符号右侧的值赋值给符号左侧的变量
1. "+="  a += 5 等价于 a = a + 5
2. "-="	 a -= 5 等价于 a = a - 5
3. "*="	 a *= 5 等价于 a = a * 5
4. "/="  a /= 5 等价于 a = a / 5
5. "%="  a %= 5 等价于 a = a % 5

(7)关系运算符

通过关系运算符可以比较两个值之间的大小关系,如果关系成立它会返回true,如果关系不成立则返回false。
1. > 大于号:判断符号左侧的值是否大于右侧的值,如果关系成立,返回true,如果关系不成立则返回false。
2. >= 大于等于:判断符号左侧的值是否大于或等于右侧的值。
3. < 小于号
4. <= 小于等于
5.非数值的情况
(1)对于非数值进行比较时,会将其转换为数字然后在比较
(2)如果符号两侧的值都是字符串时,不会将其转换为数字进行比较,而会分别比较字符串中字符的Unicode编码。
	* 比较字符编码时是一位一位进行比较。

(8)相等运算符

1.使用 == 来做相等运算
(1)相等运算符用来比较两个值是否相等,如果相等会返回true,否则返回false2)当使用 == 来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较。
2. 使用 != 来做不相等运算:
(1)不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false。
(2)不相等也会对变量进行自动的类型转换,如果转换后相等它也会返回false
3.=== 全等:
用来判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回false4.!== 不全等
用来判断两个值是否不全等,和不等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回true

* undefined 衍生自 null,所以这两个值做相等判断时,会返回true。
* NaN不和任何值相等,包括他本身。
* 可以通过isNaN()函数来判断一个值是否是NaN,如果该值是NaN则返回true,否则返回false

(9)三元运算符

条件运算符也叫三元运算符
1.语法:条件表达式 ? 语句1 : 语句2 ;
2.执行的流程:
(1)条件运算符在执行时,首先对条件表达式进行求值,
(2)如果该值为true,则执行语句1,并返回执行结果
(3)如果该值为false,则执行语句2,并返回执行结果
(4)如果条件的表达式的求值结果是一个非布尔值,会将其转换为布尔值然后在运算

(10)运算符的优先级

1.使用,可以分割多个语句,一般可以在声明多个变量时使用,
(1)使用,运算符同时声明多个变量 var a , b , c;
(2)可以同时声明多个变量并赋值 var a=1 , b=2 , c=3;
2. 就和数学中一样,在JS中运算符也有优先级,比如:先乘除 后加减
   * 在JS中有一个运算符优先级的表,在表中越靠上优先级越高,优先级越高越优先计算,
   * 如果优先级一样,则从左往右计算。但是这个表我们并不需要记忆,如果遇到优先级不清楚,可以使用()来改变优先级

8.流程控制语句

JS中的程序是从上到下一行一行执行的。
通过流程控制语句可以控制程序执行流程,使程序可以根据一定的条件来选择执行
语句的分类:
1.条件判断语句
2.条件分支语句
3.循环语句		 

(1)条件判断语句

if语句

if(条件表达式){
	语句...
}
(1)if语句在执行时,会先对条件表达式进行求值判断,
(2)如果条件表达式的值为true,则执行if后的语句,如果条件表达式的值为false,则不会执行if后的语句。
(3)if语句只能控制紧随其后的那个语句,如果希望if语句可以控制多条语句,可以将这些语句统一放到代码块中。

if...else...语句

if(条件表达式){
	语句...
}else{
	语句...
}
(1)当该语句执行时,会先对if后的条件表达式进行求值判断。
(2)如果该值为true,则执行if后的语句,如果该值为false,则执行else后的语句。

if ... else if ... else 语句

if(条件表达式){
	语句...
}else if(条件表达式){
	语句...
}else if(条件表达式){
	语句...
}else{
	语句...
}
(1)当该语句执行时,会从上到下依次对条件表达式进行求值判断
(2)如果值为true,则执行当前语句。如果值为false,则继续向下判断。
(3)如果所有的条件都不满足,则执行最后一个else后的语句
(4)该语句中,只会有一个代码块被执行,一旦代码块执行了,则直接结束语句
(5)if语句后的代码块不是必须的,但是在开发中尽量写上代码块,即使if后只有一条语句

(2)条件分支语句

switch...case..语句

switch(条件表达式){
    case 表达式:
        语句...
        break;
    case 表达式:
        语句...
        break;
    default:
    	语句...
    	break;
}

执行流程:
1.在执行时会依次将case后的表达式的值和switch后的条件表达式的值进行全等比较,
2.如果比较结果为true,则从当前case处开始执行代码。当前case后的所有的代码都会执行,我们可以在case的后边跟着一个break关键字,这样可以确保只会执行当前case后的语句,而不会执行其他的case3.如果比较结果为false,则继续向下比较。如果所有的比较结果都为false,则只执行default后的语句
4.switch语句和if语句的功能实际上有重复的,使用switch可以实现if的功能,同样使用if也可以实现switch的功能。

(3)循环语句

while循环

while(条件表达式){
	语句...
}
(1) while语句在执行时,先对条件表达式进行求值判断。
(2) 如果值为true,则执行循环体,循环体执行完毕以后,继续对表达式进行判断,如果为true,则继续执行,以此类推。
(3) 如果值为false,则终止循环。

do...while循环

do{
	语句...
}while(条件表达式)

(1)do...while语句在执行时,会先执行循环体;
(2)循环体执行完毕以后,在对while后的条件表达式进行判断;
(3)如果结果为true,则继续执行循环体,执行完毕继续判断以此类推;
(4)如果结果为false,则终止循环;
(5)实际上这两个语句功能类似,不同的是while是先判断后执行,而do...while会先执行后判断;
   do...while可以保证循环体至少执行一次,而while不能。

for循环

1.在for循环中,为我们提供了专门的位置用来放三个表达式:
(1).初始化表达式
(2).条件表达式
(3).更新表达式

for(①初始化表达式;②条件表达式;④更新表达式){
	③语句...
}

2.for循环的执行流程:
(1)执行初始化表达式,初始化变量(初始化表达式只会执行一次)
(2)执行条件表达式,判断是否执行循环。如果为true,则执行循环(3);如果为false,终止循环
(3)执行更新表达式,更新表达式执行完毕继续重复(2)

3.for循环中的三个部分都可以省略,也可以写在外部。
  如果在for循环中不写任何的表达式,只写两个;此时循环是一个死循环会一直执行下去,慎用
  for(;;){
  	alert("hello");
  }

嵌套for循环

/* 
1.打印99乘法表
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16	
....9*9=81
*/		
//创建外层循环,用来控制乘法表的高度
for(var i=1 ; i<=9 ; i++ ){
    //创建一个内层循环来控制图形的宽度
    for(var j=1 ; j<=i ; j++){
        document.write("<span>"+j+"*"+i+"="+i*j+"</span>");
    }
    //输出一个换行
    document.write("<br />");
}

break 和 continue

1.break
(1)break关键字可以用来退出switch或循环语句
(2)不能在if语句中使用breakcontinue
(3)break关键字,会立即终止离他最近的那个循环语句

2.可以为循环语句创建一个label,来标识当前的循环:
(1)"label:循环语句"
(2)使用break语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的
outer:
for(var i=0 ; i<5 ; i++){
    console.log("@外层循环"+i)
    for(var j=0 ; j<5; j++){
        break outer;
        console.log("内层循环:"+j);
    }
}

3.continue
(1)continue关键字可以用来跳过当次循环
(2)同样continue也是默认只会对离他最近的循环循环起作用

9.对象

(1)对象分类

对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。
对象的分类:
1.内建对象
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math String Number Boolean Function Object....

2.宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
- 比如 BOM DOM

3.自定义对象
- 由开发人员自己创建的对象

(2)创建对象

创建对象

//使用new关键字调用的函数,是构造函数constructor,构造函数是专门用来创建对象的函数
var obj = new Object();

向对象添加属性

//语法:对象.属性名 = 属性值;
obj.name = "孙悟空";

读取对象中的属性

//语法:对象.属性名
obj.name

修改对象的属性值

//语法:对象.属性名 = 新值
obj.name = "tom";

删除对象的属性

//语法:delete 对象.属性名
delete obj.name;

(3)属性名和属性值

属性名

1.对象的属性名不强制要求遵守标识符的规范, 但是我们使用是还是尽量按照标识符的规范去做
2.如果要使用特殊的属性名,不能采用.的方式来操作
  - 需要使用另一种方式:	
  - 对象["属性名"] = 属性值	 例:obj["123"] = 789;
  - 读取时也需要采用这种方式.

属性值

//JS对象的属性值,可以是任意的数据类型,甚至也可以是一个对象。
var obj2 = new Object();
obj2.name = "猪八戒";
obj.test = obj2;

in 运算符

通过该运算符可以检查一个对象中是否含有指定的属性,
如果有则返回true,没有则返回false。
- 语法: "属性名" in 对象
  "test2" in obj

(4)基本数据类型 和 引用数据类型

image-20220104163424864.png

JS中的变量都是保存到栈内存中的。
(1)基本数据类型的值直接在栈内存中存储,值与值之间是独立存在,修改一个变量不会影响其他的变量
(2)对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,
(3)而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响
(4)当比较两个基本数据类型的值时,就是比较值。而比较两个引用数据类型时,它是比较的对象的内存地址,
	如果两个对象是一摸一样的,但是地址不同,它也会返回false

(5)对象字面量

使用对象字面量来创建一个对象

var obj = {};

使用对象字面量,可以在创建对象时,直接指定对象中的属性

语法:{属性名:属性值,属性名:属性值....}
1.对象字面量的属性名可以加引号也可以不加,建议不加,
2. 如果要使用一些特殊的名字,则必须加引号
var obj2 = {			
    name:"猪八戒",
    age:13,
    gender:"男",
    test:{
        name:"沙僧"
    }
};

(6)枚举对象中的属性

使用for ... in 语句

语法:
for(var 变量 in 对象){

}
for...in语句 对象中有几个属性,循环体就会执行几次。
每次执行时,会将对象中的一个属性的名字赋值给变量。

例:
for(var n in obj){
    console.log("属性名:"+n);
    console.log("属性值:"+obj[n]);
}

10.函数

(1)创建函数

使用构造函数来创建一个函数对象(一般不用)

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

使用 函数声明 来创建一个函数

function 函数名([形参1,形参2...形参N]){
	语句...
}

使用 函数表达式 来创建一个函数

var 函数名  = function([形参1,形参2...形参N]){
	语句....
}

(2)函数的参数

1.可以在函数的()中来指定一个或多个形参(形式参数)。
2.多个形参之间使用,隔开,声明形参就相当于在函数内部声明了对应的变量,但是并不赋值。
3.在调用函数时,可以在()中指定实参(实际参数),实参将会赋值给函数中对应的形参
4.调用函数时解析器不会检查实参的类型,
5.调用函数时,解析器也不会检查实参的数量,多余实参不会被赋值

(3)函数的返回值

可以使用 return 来设置函数的返回值

1.如果return语句后不跟任何值就相当于返回一个undefined2.如果函数中不写return,则也会返回undefined

break continue return 作用

1.使用break可以退出当前的循环
  break;
2.continue用于跳过当次循环
  continue;
3.使用return可以结束整个函数
  return;

(4)立即执行函数

函数定义完,立即被调用,这种函数叫做立即执行函数。 立即执行函数往往只会执行一次。

(function(a,b){
    console.log("a = "+a);
    console.log("b = "+b);
})(123,456);

(5)函数的方法

call ( ) 和 apply ( )

/* 1. 这两个方法都是函数对象的方法,需要通过函数对象来调用
 * 2. 当函数调用call()和apply()时,都会调用函数本身
 * 3. 可以将一个对象指定为第一个参数(obj)
 * 4. 此时这个对象将会成为函数执行时的this
 * 5. call()方法可以将实参在对象之后依次传递
 * 6. apply()方法需要将实参封装到一个数组中统一传递
 */
function fun(a,b) {
    console.log("a = "+a);
    console.log("b = "+b);
    //alert(this);
}

var obj = {
    name: "obj",
    sayName:function(){
        alert(this.name);
    }
};

fun.call(obj,2,3);
fun.apply(obj,[2,3]);

11.作用域

在JS中一共有两种作用域:
1.全局作用域
2.函数作用域(局部作用域)

(1)全局作用域

1.编写位置:直接编写在script标签中的JS代码,都在全局作用域。
2.生命周期:全局作用域在页面打开时创建,在页面关闭时销毁。
3.关于window对象:在全局作用域中有一个全局对象window,
(1)它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用
(2)在全局作用域中,创建的变量都会作为window对象的属性保存;
(3)在全局作用域中,创建的函数都会作为window对象的方法保存;
4.关于变量:全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到

变量声明提前

1.使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),
2.但是如果声明变量时不用var关键字,则变量不会被声明提前

函数的声明提前

//1.使用函数声明形式创建的函数 function 函数(){},它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数
function fun(){
	console.log("我是一个fun函数");
}
//2.使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用	
var fun2 = function(){
	console.log("我是fun2函数");
};

变量与函数都要提前声明,哪个优先级更高?

当变量声明时没有赋值或初始化,函数声明的优先级高于变量,否则变量优先级高于函数

(2)函数作用域(局部作用域)

1.生命周期:
(1)调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。
(2)每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的。
2.访问方式:
(1)在函数作用域中可以访问到全局作用域的变量。
(2)在全局作用域中无法访问到函数作用域的变量。
3.执行规则:
(1)当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用。
(2)如果没有则向上一级作用域中寻找,直到找到全局作用域。
(3)如果全局作用域中依然没有找到,则会报错ReferenceError4.关于window对象:在函数中要访问全局变量可以使用window对象。
5. 在函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明,函数声明也会在函数中所有的代码执行之前执行。
6.在函数中,不适用var声明的变量都会成为全局变量

12.this

解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是thisthis指向的是一个对象,这个对象我们称为函数执行的=>上下文对象。
根据函数的调用方式的不同,this会指向不同的对象:
1.当以函数的形式调用时,this是window
2.当以方法的形式调用时,谁调用方法this就是谁
3.当以构造函数的形式调用时,this就是新创建的那个对象
4.使用call和apply调用时,this是指定的那个对象(第一个参数)
5.事件的响应函数中,响应函数是给谁绑定的this就是谁

13.构造函数

构造函数就是一个普通的函数,创建方式和普通函数没有区别。

1.区别:
(1)不同的是构造函数习惯上首字母大写
(2)构造函数和普通函数的区别就是调用方式的不同。普通函数是直接调用,而构造函数需要使用new关键字来调用。

2.构造函数的执行流程:
(1)立刻创建一个新的对象
(2)将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
(3)逐行执行函数中的代码
(4)将新建的对象作为返回值返回

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

示例:

function Person(name , age , gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = function(){
        alert(this.name);
    };
}

var per = new Person("孙悟空",18,"男");

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

console.log(per instanceof Person);

所有的对象都是Object的后代,所以任何对象和Object左instanceof检查时都会返回true

console.log(dog instanceof Object);

14.原型 prototype

原型对象

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,
这个属性对应着一个对象,这个对象就是我们所谓的原型对象。

访问原型对象

1.只有当函数以构造函数的形式调用时(用new关键字调用),它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过 __proto__ 来访问该属性。
2.原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
3.以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
4.代码执行逻辑:
(1)当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
(2)如果没有则会去原型对象中寻找,如果找到则直接使用。如果原型对象中有,则使用。
(3)如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。(一般来说最多找两层原型)

使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

function MyClass(){}
MyClass.prototype.name = "我是原型中的名字";
var mc = new MyClass();
mc.age = 18;
console.log("name" in mc);//返回true

可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性

console.log(mc.hasOwnProperty("age"));

在原型中添加toString

function Person(name , age , gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}
//修改Person原型的toString
Person.prototype.toString = function(){
    return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};
//创建一个Person实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");
//此时打印出来的就不是[Obiect obiect]
console.log(per2);
console.log(per);

15.垃圾回收(GC)

程序运行过程中会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢。
所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾。

什么是程序的垃圾?

当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象。
此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。

JS中的垃圾回收机制

在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁。我们不需要也不能进行垃圾回收的操作。
我们需要做的只是要将不再使用的对象设置null即可。

原理

当我们将不再使用的对象设置为null时,栈内存中会将指向堆内存的对象的地址替换为null。
此时,原本储存在堆内存中的对象,就与外界失去了联系,变成了程序垃圾,js会定期清理这些垃圾。

16.数组 Array

(1)数组的创建及操作

数组也是一个对象,它和我们普通对象功能类似,也是用来存储一些值的。
不同的是普通对象是使用字符串作为属性名的,而数组时使用数字来作为索引操作元素。

创建数组对象

var arr = new Array();

使用typeof检查一个数组时,会返回object

console.log(typeof arr);

向数组中添加元素

arr[0] = 10;
arr[1] = 33;
arr[2] = 22;
arr[3] = 44;

读取数组中的元素

//如果读取不存在的索引,他不会报错而是返回undefined
console.log(arr[3])

(2)数组的length属性

①可以使用length属性来获取数组的长度

语法:数组.length	
1.对于连续的数组,使用length可以获取到数组的长度(元素的个数)
2.对于非连续的数组,使用length会获取到数组的最大的索引。(尽量不要创建非连续的数组)

示例

console.log(arr.length);

②修改数组length

1.如果修改的length大于原长度,则多出部分会空出来
2.如果修改的length小于原长度,则多出的元素会被删除

示例

arr.length = 10;

③向数组的最后一个位置添加元素

arr[arr.length] = 70;

(3)字面量

使用字面量来创建数组

var arr = [];

使用 typeof 判断数组类型,是Object

console.log(typeof arr);

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

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

使用构造函数创建数组时,也可以同时添加元素

var arr2 = new Array(10,20,30);

创建数组时,只添加一个元素

//创建一个数组数组中只有一个元素10(字面量)
var arr = [10];
//创建一个长度为10的数组(构造函数)
var arr2 = new Array(10);

数组中的元素可以是任意的数据类型也可以是对象,或者一个函数

var arr = ["hello",1,true,null,undefined];

数组中也可以放数组,如下这种数组我们称为二维数组

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

(4)数组的方法

序号方法描述
1concat()连接两个或多个数组,并返回已连接数组的副本。
2copyWithin()将数组中的数组元素复制到指定位置或从指定位置复制。
3entries()返回键/值对数组迭代对象。
4every()检查数组中的每个元素是否通过测试。
5fill()用静态值填充数组中的元素。
6filter()使用数组中通过测试的每个元素创建新数组。
7find()返回数组中第一个通过测试的元素的值。
8findIndex()返回数组中通过测试的第一个元素的索引。
9forEach()为每个数组元素调用函数。
10from()从对象创建数组。
11includes()检查数组是否包含指定的元素。
12indexOf()在数组中搜索元素并返回其位置。
13isArray()检查对象是否为数组。
14join()将数组的所有元素连接成一个字符串。
15keys()返回 Array Iteration 对象,包含原始数组的键.
16lastIndexOf()在数组中搜索元素,从末尾开始,并返回其位置。
17map()使用为每个数组元素调用函数的结果创建新数组。
18pop()删除数组的最后一个元素,并返回该元素。
19push()将新元素添加到数组的末尾,并返回新的长度。
20reduce()将数组的值减为单个值(从左到右)。
21reduceRight()将数组的值减为单个值(从右到左)。
22reverse()反转数组中元素的顺序。
23shift()删除数组的第一个元素,并返回该元素。
24slice()选择数组的一部分,并返回新数组。
25some()检查数组中的任何元素是否通过测试。
26sort()对数组的元素进行排序。
27splice()从数组中添加/删除元素。
28toString()将数组转换为字符串,并返回结果。
29unshift()将新元素添加到数组的开头,并返回新的长度。
30valueOf()返回数组的原始值。

push()

/*1.该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度
 *2.可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾
 *3.该方法会将数组新的长度作为返回值返回
 */
var result = arr.push("唐僧","蜘蛛精","白骨精","玉兔精");

pop()

//该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
result = arr.pop();

unshift()

/* 向数组开头添加一个或多个元素,并返回新的数组长度
 * 向前边插入元素以后,其他的元素索引会依次调整
 */
arr.unshift("牛魔王","二郎神");

shift()

//可以删除数组的第一个元素,并将被删除的元素作为返回值返回
result = arr.shift();

forEach()

//*这个方法只支持IE8以上的浏览器*
//创建一个数组
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];

/* 1.forEach()方法需要一个回调函数作为参数(回调函数由浏览器调用)
 * 2.数组中有几个元素函数就会执行几次,
 * 3.每次执行时,浏览器会将遍历到的元素,以实参的形式传递进来
 * 4.我们可以来定义形参,来读取这些内容
 */
//浏览器会在回调函数中传递三个参数:
//1.当前正在遍历的元素(value)2.当前正在遍历的元素的索引(index)3.正在遍历的数组(obj)
arr.forEach(function(value , index , obj){
    console.log(value);
});

slice()

/* 可以用来从数组提取指定元素,该方法将截取到的元素封装到一个新数组中返回。
 * 参数:
 * 1.截取开始的位置的索引,包含开始索引
 * 2.截取结束的位置的索引,不包含结束索引
 * 3.第二个参数可以省略不写,此时会截取从开始索引往后的所有元素
 * 4.索引可以传递一个负值,如果传递一个负值,则从后往前计算(-1 => 倒数第一个)
 */
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result = arr.slice(1,4);

splice()

/* 使用splice()会将指定元素从原数组中删除,并将被删除的元素作为返回值返回。
 * 参数:
 * 1.第一个,表示开始位置的索引
 * 2.第二个,表示删除的数量
 * 3.第三个及以后,可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
 */
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result = arr.splice(3,0,"牛魔王","铁扇公主","红孩儿");

concat()

//可以连接两个或多个数组,并将新的数组返回,该方法不会对原数组产生影响
var arr = ["孙悟空","猪八戒","沙和尚"];
var arr2 = ["白骨精","玉兔精","蜘蛛精"];
var arr3 = ["二郎神","太上老君","玉皇大帝"];
var result = arr.concat(arr2,arr3,"牛魔王","铁扇公主");

join()

//1.该方法可以将数组转换为一个字符串
//2.该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
//3.在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
//4.如果不指定连接符,则默认使用,作为连接符
var arr = ["孙悟空","猪八戒","沙和尚","唐僧"];	
var	result = arr.join("@-@");

reverse()

// 该方法用来反转数组(前边的去后边,后边的去前边)- 该方法会直接修改原数组
var arr = ["孙悟空","猪八戒","沙和尚","唐僧"];
arr.reverse();

sort()

//可以用来对数组中的元素进行排序。也会影响原数组,默认会按照Unicode编码进行排序
//即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序
var arr = [5,4,2,1,3,6,8,7];
arr.sort();
/* 我们可以在sort()添加一个回调函数,来指定排序规则
 * 1.回调函数中需要定义两个形参
 * 2.浏览器将会分别使用数组中的元素作为实参去调用回调函数
 * 3.使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边
 * 4.浏览器会根据回调函数的返回值来决定元素的顺序
 *   (1)如果返回一个大于0的值,则元素会交换位置
 *	 (2)如果返回一个小于0的值,则元素位置不变
 *	 (3)如果返回一个0,则认为两个元素相等,也不交换位置
 *	 (4) 如果需要升序排列,则返回 a-b ; 如果需要降序排列,则返回b-a
 */
arr.sort(function(a,b){
    return b - a;
});

(5)数组的遍历

var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
for(var i=0 ; i<arr.length ; i++){
	console.log(arr[i]);
}

17.arguments

/*
 *  在调用函数时,浏览器每次都会传递进两个隐含的参数:
 * 	1.函数的上下文对象 this
 * 	2.封装实参的对象 arguments
 * 		- arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
 * 		- 在调用函数时,我们所传递的实参都会在arguments中保存
 * 		- arguments.length可以用来获取实参的长度
 * 		- 我们即使不定义形参,也可以通过arguments来使用实参,
 * 			只不过比较麻烦
 * 			arguments[0] 表示第一个实参
 * 			arguments[1] 表示第二个实参 。。。
 *		- 它里边有一个属性叫做callee,
 * 			这个属性对应一个函数对象,就是当前正在指向的函数的对象
 * 		
 */
function fun(a,b){
    console.log(arguments instanceof Array);
    console.log(Array.isArray(arguments));
    console.log(arguments[1]);
    console.log(arguments.length);
    console.log(arguments.callee == fun);
}

fun("hello",true);

18.Date

JS中使用Date对象来表示一个时间

创建一个Date对象

//如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
var d = new Date();

创建一个指定的时间对象

//需要在构造函数中传递一个表示时间的字符串作为参数,日期的格式  月份/日/年 时:分:秒
var d2 = new Date("2/18/2011 11:10:30");

getDate()

//获取当前日期对象是几日
var date = d2.getDate();

getDay()

//获取当前日期对象时周几,返回数字0-6(周一至周日:1,2,3,4,5,6,0)
var day = d2.getDay();

getMonth()

//获取当前时间对象的月份,返回数字0-11(1月到12月:0,1,2,3,4,5,6,7,8,9,10,11)
var month = d2.getMonth();

getFullYear()

//获取当前日期对象的年份
var year = d2.getFullYear();

getTime()

//获取当前日期对象的时间戳
//时间戳,指的是从格林威治标准时间的1970年1月1日,0时0分0秒,
//到当前日期所花费的毫秒数(1秒 = 1000毫秒)
var time = d2.getTime();

利用时间戳来测试代码的执行的性能

//获取当前的时间戳
var start = Date.now();

for(var i=0 ; i<100 ; i++){
    console.log(i);
}

var end = Date.now();
console.log("执行了:"+(end - start)+"毫秒");

19.Math

Math和其他的对象不同,它不是一个构造函数,它属于一个工具类不用创建对象,
它里边封装了数学运算相关的属性和方法

圆周率

Math.PI

计算一个数的绝对值

Math.abs(-1)

向上取整

Math.ceil(1.1)

向下取整

Math.floor(1.99)

四舍五入取整

Math.round(1.4)

生成随机数

1.可以用来生成一个0-1之间的随机数
Math.random()
2.生成一个0-x之间的随机数
Math.round(Math.random()*x)
3.生成一个x-y之间的随机数
Math.round(Math.random()*(y-x)+x)

获取多个数中的最大值

var max = Math.max(10,45,30,100);

获取多个数中的最小值

var min = Math.min(10,45,30,100);

返回x的y次幂

Math.pow(x,y)

对一个数进行开方运算

Math.sqrt()

20.包装类

在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象

1.String()  可以将基本数据类型字符串转换为String对象
2.Number()  可以将基本数据类型的数字转换为Number对象
3.Boolean() 可以将基本数据类型的布尔值转换为Boolean对象

* 但是注意:我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果

方法和属性之能添加给对象,不能添加给基本数据类型

当我们对一些基本数据类型的值去调用属性和方法时,
浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法
调用完以后,在将其转换为基本数据类型

21.String

创建一个字符串

var str = "Hello Atguigu";

在底层字符串是以字符数组的形式保存的

["H","e","l",......]

length属性 => 可以用来获取字符串的长度

str.length

charAt()

//可以返回字符串中指定位置的字符,根据索引获取指定的字符	
var result = str.charAt(6);

charCodeAt()

//获取指定位置字符的字符编码(Unicode编码)
var result = str.charCodeAt(0);

String.formCharCode()

var result = String.fromCharCode(0x2692);

concat()

var result = str.concat("你好","再见");

indexof()

/* 1.该方法可以检索一个字符串中是否含有指定内容
 * 	- 如果字符串中含有该内容,则会返回其第一次出现的索引
 * 	- 如果没有找到指定的内容,则返回-1
 * 2.可以指定一个第二个参数,指定开始查找的位置
 */
var	str = "hello hatguigu";
var	result = str.indexOf("h",1);

lastIndexOf()

//该方法的用法和indexOf()一样,不同的是indexOf是从前往后找,而lastIndexOf是从后往前找
//也可以指定开始查找的位置
var result = str.lastIndexOf("h",5);

slice()

/* 1.可以从字符串中截取指定的内容,不会影响原字符串,而是将截取到内容返回。
 * 2.参数:
 * 	(1)第一个,开始位置的索引(包括开始位置)
 * 	(2)第二个,结束位置的索引(不包括结束位置)
 *  (3)如果省略第二个参数,则会截取到后边所有的
 * 3.也可以传递一个负数作为参数,负数的话将会从后边计算
 */
var str = "abcdefghijk";
var result = str.slice(1,4);
var result1 = str.slice(1,-1);

substring()

//1.可以用来截取一个字符串,可以slice()类似,不同的是这个方法不能接受负值作为参数,
//2.如果传递了一个负值,则默认使用0
//3.而且他还自动调整参数的位置,如果第二个参数小于第一个,则自动交换
var result = str.substring(0,1);

substr()

// 用来截取字符串
// 参数:1.截取开始位置的索引 2.截取的长度
var str = "abcdefg";
var result = str.substr(3,2);

split()

//1.可以将一个字符串拆分为一个数组
var str = "abcbcdefghij";
var result = str.split("d");
//2.如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
var result1 = str.split("");

toUpperCase()

//将一个字符串转换为大写并返回
var str = "abcdefg";
var result = str.toUpperCase();

toLowerCase()

var result = str.toLowerCase();

22.正则表达式

(1)用途

正则表达式用于定义一些字符串的规则,
计算机可以根据正则表达式,来检查一个字符串是否符合规则,
获取将字符串中符合规则的内容提取出来。

(2)创建正则表达式对象

语法:var 变量 = new RegExp("正则表达式","匹配模式");

1. 使用typeof检查正则对象,会返回object
2. var reg = new RegExp("a"); 
   这个正则表达式可以来检查一个字符串中是否含有a
3. 在构造函数中可以传递一个匹配模式作为第二个参数:
   可以是 (1) i 忽略大小写 ;  (2) g 全局匹配模式

(3) test() 方法

//使用这个方法可以用来检查一个字符串是否符合正则表达式的规则,如果符合则返回true,否则返回false
var reg = new RegExp("ab","i");
var result = reg.test(str);

(4)使用字面量来创建正则表达式

语法:var 变量 = /正则表达式/匹配模式
示例:
1.使用构造函数创建正则表达式:var reg = new RegExp("a","i");
2.使用字面量来创建正则表达式:var reg = /a/i;

使用 | 表示或者的意思

//创建一个正则表达式,检查一个字符串中是否有a或b
reg = /a|b/;

[ ] 里的内容也是或的关系

[ab] == a|b

创建一个正则表达式检查一个字符串中是否有字母

1. [a-z] 任意小写字母
2. [A-Z] 任意大写字母
3. [A-z] 任意字母
4. [0-9] 任意数字
示例:
var reg = /[A-z]/;

检查一个字符串中是否含有 abc 或 adc 或 aec

var reg = /a[bde]c/;

[^... ] 除了

var reg1 = /[^ab]/;
var reg2 = /[^0-9]/;

量词{}

通过量词可以设置一个内容出现的次数,量词只对它前边的一个内容起作用
1. {n} 正好出现n次
2. {m,n} 出现m-n次
3. {m,} m次以上
4. + 至少一个,相当于{1,}
5. * 0个或多个,相当于{0,}
6. ? 0个或1个,相当于{0,1}

开头与结尾 (^ 表示开头 ,$ 表示结尾)

//^ 表示开头 ,$ 表示结尾
var reg = /^a/; //匹配开头的a
var reg = /a$/; //匹配结尾的a

创建一个正则表达式,用来检查一个字符串是否是一个合法手机号

手机号的规则: 1 3 56789012311位)
1.1开头
2. 第二位3-9任意数字
3. 三位以后任意数字9var phoneReg = /^1[3-9][0-9]{9}$/;
console.log(phoneReg.test(phoneStr));

(5)正则表达式相关的方法

split()

/* 1.可以将一个字符串按照一定规则拆分为一个数组
 * 2.方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
 * 3.这个方法即使不指定全局匹配,也会全都插分
 */
//根据任意字母来将字符串拆分
var result = str.split(/[A-z]/);

search()

1.可以搜索字符串中是否含有指定内容	
2.如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1
3.它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
4.serach()只会查找第一个,即使设置全局匹配也没用

var str = "hello abc hello aec afc";
//搜索字符串中是否含有abc 或 aec 或 afc
var result = str.search(/a[bef]c/);

match()

1. 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
2. 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索	
3. 我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
4. 可以为一个正则表达式设置多个匹配模式,且顺序无所谓
5. match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果	

var str = "1a2a3a4a5e6f7A8B9C";
var result = str.match(/[a-z]/ig);

replace()

1.可以将字符串中指定内容替换为新的内容
2. 参数:(1)被替换的内容,可以接受一个正则表达式作为参数。(2)新的内容。
3. 默认只会替换第一个

var str = "1a2a3a4a5e6f7A8B9C";
var	result = str.replace(/[a-z]/gi , "");

(6)正则表达式中的转义字符 \

1.\. 检查一个字符串中是否含有.
(1) . 表示任意字符
(2) 在正则表达式中使用\作为转义字符
2.\\ 表示\
(1) 使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符
(2) 如果要使用\则需要使用\\来代替
var reg = /\./;		
var	reg1 = /\\/;
var	reg2 = new RegExp("\\.");
var	reg3 = new RegExp("\\\\");
3. \w 任意字母、数字、_  [A-z0-9_]
4. \W 除了字母、数字、_  [^A-z0-9_]
5. \d 任意的数字 [0-9]
6. \D 除了数字 [^0-9]
7. \s 空格
8. \S 除了空格
9. \b 单词边界
10. \B 除了单词边界

创建一个正则表达式检查一个字符串中是否含有单词child

var reg = /\bchild\b/;

去除掉字符串中的前后的空格

var str = str.replace(/^\s*|\s*$/g,"");

(7)邮件的正则

// hello  .nihao          @     abc  .com.cn
// 任意字母数字下划线   .任意字母数字下划线  @   任意字母数字    .任意字母(2-5位)  .任意字母(2-5位)
// \w{3,}  (\.\w+)*  @  [A-z0-9]+  (\.[A-z]{2,5}){1,2}
var emailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
var email = "abc.hello@163.com";
console.log(emailReg.test(email));

23.DOM

(1)DOM简介

什么是DOM?

DOM,全称 Document Object Model文档对象模型。JS中通过DOM来对HTML文档进行操作。
1.文档:文档表示的就是整个的HTML网页文档
2.对象:对象表示将网页中的每一个部分都转换为了一个对象。
3.模型:使用模型来表示对象之间的关系,这样方便我们获取对象。

微信图片_20220207165120.png

(2)节点(Node)

节点是构成网页的最基本的组成部分,网页中的每一个部分都可以称为是一个节点。
比如:html标签、属性、文本、注释、整个文档等都是一个节点。
虽然都是节点,但具体类型是不同的。节点的类型不同,属性和方法也都不尽相同。
常用节点分为四类:
1.文档节点:整个HTML文档
2.元素节点:HTML文档中的HTML标签
3.属性节点:元素的属性
4.文本节点:HTML标签中的文本内容

文档节点(document)

1.文档节点document,代表的是整个HTML文档,网页中的所有节点都是它的子节点。
2.document对象作为window对象的属性存在的,我们不用获取可以直接使用。
3.通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。

元素节点(Element)

1.HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。
2.浏览器会将页面中所有的标签都转换为一个元素节点,我们可以通过document的方法来获取元素节点。
  比如:document.getElementById() -- 根据id属性值获取一个元素节点对象。

文本节点(Text)

1.文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。
2.文本节点一般是作为元素节点的子节点存在的。
3.获取文本节点时,一般先要获取元素节点。在通过元素节点获取文本节点。
例如:元素节点.firstChild; – 获取元素节点的第一个子节点,一般为文本节点

属性节点(Attr)

1.属性节点表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。
2.可以通过元素节点来获取指定的属性节点。
 例如:元素节点.getAttributeNode("属性名"); 注意:我们一般不使用属性节点。

(3)文档的加载

浏览器在加载一个页面时,是按照自上向下的顺序加载的,读取到一行就运行一行,如果将script标签写到页面的上边,
在代码执行时,页面还没有加载,页面没有加载DOM对象也没有加载,会导致无法获取到DOM对象。

onload事件

1.onload事件会在整个页面加载完成之后才触发
2.window绑定一个onload事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了
window.onload = function(){
    //获取id为btn的按钮
    var btn = document.getElementById("btn");
    //为按钮绑定一个单击响应函数
    btn.onclick = function(){
        alert("hello");
    };
};

(4)DOM查询

获取元素节点

通过document对象调用
1. getElementById() 	  – 通过id属性获取一个元素节点对象
2. getElementsByTagName() – 通过标签名获取一组元素节点对象(类数组)
3. getElementsByName()    – 通过name属性获取一组元素节点对象(类数组)

getElementById()

//为id为btn01的按钮绑定一个单击响应函数
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
    //查找#bj节点
    var bj = document.getElementById("bj");
    //打印bj
    //innerHTML 通过这个属性可以获取到元素内部的html代码
    alert(bj.innerHTML);
};

getElementsByTagName()

//为id为btn02的按钮绑定一个单击响应函数
var btn02 = document.getElementById("btn02");
btn02.onclick = function(){
    //查找所有li节点
    //getElementsByTagName()可以根据标签名来获取一组元素节点对象
    //这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中
    //即使查询到的元素只有一个,也会封装到数组中返回
    var lis = document.getElementsByTagName("li");
    //变量lis
    for(var i=0 ; i<lis.length ; i++){
        alert(lis[i].innerHTML);
    }
};

getElementsByName()

//为id为btn03的按钮绑定一个单击响应函数
var btn03 = document.getElementById("btn03");
btn03.onclick = function(){
    //查找name=gender的所有节点
    var inputs = document.getElementsByName("gender");
    for(var i=0 ; i<inputs.length ; i++){
        alert(inputs[i].className);
    }
};

innerHTML

innerHTML用于获取元素内部的HTML代码的,对于自结束标签,这个属性没有意义

读取元素节点属性

如果需要读取元素节点属性,直接使用 元素.属性名
例子:元素.id 元素.name 元素.value
*注意:class属性不能采用这种方式,读取class属性时需要使用 元素.className

获取元素节点的子节点

• 通过具体的元素节点调用
1. getElementsByTagName() 	
– 方法,返回当前节点的指定标签名后代节点
2. childNodes				
– 属性,表示当前节点的所有子节点。childNodes属性会获取包括文本节点在呢的所有节点,根据DOM标签标签间空白也会当成文本节点。 * 注意:在IE8及以下的浏览器中,不会将空白文本当成子节点。
3. firstChild				
– 属性,表示当前节点的第一个子节点
4. lastChild				
– 属性,表示当前节点的最后一个子节点

获取父节点和兄弟节点

• 通过具体的节点调用
1. parentNode
– 属性,表示当前节点的父节点
2. previousSibling
– 属性,表示当前节点的前一个兄弟节点
3. nextSibling
– 属性,表示当前节点的后一个兄弟节点

元素节点的属性

• 获取,元素对象.属性名
例:element.value、element.id、element.className
• 设置,元素对象.属性名=新的值
例:element.value = “hello”、element.id = “id01”、element.className = “newClass”

其他属性

• nodeValue
– 文本节点可以通过nodeValue属性获取和设置文本节点的内容
• innerHTML
– 元素节点通过该属性获取和设置标签内部的html代码

使用CSS选择器进行查询

querySelector()
• querySelectorAll()
这两个方法都是用document对象来调用,两个方法使用相同,都是传递一个选择器字符串作为参数,方法会自动根据选择器
字符串去网页中查找元素。
不同的地方是querySelector()只会返回找到的第一个元素,而querySelectorAll()会返回所有符合条件的元素。

其他查询方法

1.document.bodydocument中有一个属性body,它保存的是body的引用。
2.document.documentElement  保存的是html根标签。
3.document.all				代表页面中所有的元素。

(5)DOM增删改

document.createElement()

//可以用于创建一个元素节点对象,它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,
//并将创建好的对象作为返回值返回.
例: var li = document.createElement("li");

document.createTextNode()

//可以用来创建一个文本节点对象,需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回。
例: var gzText = document.createTextNode("广州");

appendChild()

//向一个父节点中添加一个新的子节点,用法:父节点.appendChild(子节点);
li.appendChild(gzText);

insertBefore()

//可以在指定的子节点前插入新的子节点
//语法:父节点.insertBefore(新节点,旧节点);
city.insertBefore(li , bj);

replaceChild()

//可以使用指定的子节点替换已有的子节点
//语法:父节点.replaceChild(新节点,旧节点);
city.replaceChild(li , bj);

removeChild()

//可以删除一个子节点
//语法:父节点.removeChild(子节点); 子节点.parentNode.removeChild(子节点);
city.removeChild(bj);
bj.parentNode.removeChild(bj);

innerHTML

//使用innerHTML也可以完成DOM的增删改的相关操作,一般我们会两种方式结合使用
//创建一个li
var li = document.createElement("li");
//向li中设置文本
li.innerHTML = "广州";
//将li添加到city中
city.appendChild(li);	

//如果直接使用innerHTML,相当于把整个ul节点全部替换一遍,会降低效率
city.innerHTML += "<li>广州</li>";

(6)使用DOM操作CSS

通过JS修改元素内联样式

1.语法:元素.style.样式名 = 样式值
2.注意:如果CSS的样式名中含有-,这种名称在JS中是不合法的比如background-color。需要将这种样式名修改为驼峰命名法,去掉-,然后将-后的字母大写
3.我们通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
4.如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效。尽量不要为样式添加!important
例:
box1.style.width = "300px";
box1.style.height = "300px";
box1.style.backgroundColor = "yellow";

读取元素的内联样式

语法:元素.style.样式名
例:box1.style.width

读取当前元素正在显示的样式

1.元素.currentStyle.样式名:
(1)currentStyle只有IE浏览器支持,其他的浏览器都不支持
2.getComputedStyle()
(1)这个方法是window的方法,可以直接使用
(2) 需要两个参数:第一个:要获取样式的元素。第二个:可以传递一个伪元素,一般都传null
(3)该方法会返回一个对象,对象中封装了当前元素对应的样式。可以通过对象.样式名来读取样式,如果获取的样式没有设置,则会获取到真实的值,而不是默认值。比如:没有设置width,它不会获取到auto,而是一个长度
(4)但是该方法不支持IE8及以下的浏览器
(5)通过currentStyle和getComputedStyle()读取到的样式都是只读的不能修改,如果要修改必须通过style属性

如何兼容所有浏览器以及其版本

/* 定义一个函数,用来获取指定元素的当前的样式
 * 参数:1.obj 要获取样式的元素;2.name 要获取的样式名
 */
function getStyle(obj , name){
    //需要通过window找到这个方法
    if(window.getComputedStyle){
        //正常浏览器的方式,具有getComputedStyle()方法
        return getComputedStyle(obj , null)[name];
    }else{
        //IE8的方式,没有getComputedStyle()方法
        return obj.currentStyle[name];
    }
}
var w = getStyle(box1,"width");

(7)其他样式操作的属性

1. clientWidth、clientHeight
(1)这两个属性可以获取元素的可见宽度和高度
(2)这些属性都是不带px的,返回都是一个数字,可以直接进行计算
(3)会获取元素宽度和高度,包括内容区和内边距
(4)这些属性都是只读的,不能修改
2.offsetWidth、offsetHeight
(1)获取元素的整个的宽度和高度,包括内容区、内边距和边框
3.offsetParent
(1)可以用来获取当前元素的定位父元素
(2)会获取到离当前元素最近的开启了定位的祖先元素(定位:position=relative)
(2)如果所有的祖先元素都没有开启定位,则返回body
4. offsetLeft、offsetTop
(1)offsetLeft:当前元素相对于其定位父元素的水平偏移量
(2)offsetTop: 当前元素相对于其定位父元素的垂直偏移量
5. scrollWidth、 scrollHeight
(1)可以获取元素整个滚动区域的宽度和高度
6.scrollLeft、scrollTop
(1)可以获取水平滚动条滚动的距离
(2)可以获取垂直滚动条滚动的距离
7.当满足 scrollHeight - scrollTop  == clientHeight  说明垂直滚动条滚动到底了
8.当满足 scrollWidth  - scrollLeft == clientWidth 说明水平滚动条滚动到底
9.disabled属性可以设置一个元素是否禁用,
(1)如果设置为true,则元素禁用
(2)如果设置为false,则元素可用

24.事件

事件,就是用户和浏览器之间的交互行为,比如:点击按钮,鼠标移动、关闭窗口。
可以为按钮的对应事件绑定处理函数的形式来响应事件,这样当事件被触发时,其对应的函数将会被调用。

(1)事件对象

当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,
在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标  键盘哪个按键被按下  鼠标滚轮滚动的方向。。。

onmousemove(该事件将会在鼠标在元素中移动时被触发)

//获取鼠标坐标
areaDiv.onmousemove = function(event){
    //在IE8中,响应函数被触发时,浏览器不会传递事件对象,
	//在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的
    //解决事件对象的兼容性问题(兼容IE8以下浏览器)
    event = event || window.event;
    // clientX可以获取鼠标指针的水平坐标 
    var x = event.clientX;
    // cilentY可以获取鼠标指针的垂直坐标
    var y = event.clientY;
    //在showMsg中显示鼠标的坐标
    showMsg.innerHTML = "x = "+x + " , y = "+y;
};

获取到鼠标的坐标

1.clientX和clientY
(1)用于获取鼠标在当前的可见窗口的坐标div的偏移量,是相对于整个页面的
2.pageX和pageY
(1)可以获取鼠标相对于当前页面的坐标
(2)但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
3.获取滚动条滚动的距离
(1)chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取 
(2)火狐等浏览器认为浏览器的滚动条是html的,
兼容性解决方法:
var st = document.body.scrollTop  || document.documentElement.scrollTop;
var sl = document.body.scrollLeft || document.documentElement.scrollLeft;

(2)事件的冒泡(Bubble)

所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡

取消冒泡

var s1 = document.getElementById("s1");
s1.onclick = function(event){
    event = event || window.event;
    //取消冒泡:可以将事件对象的cancelBubble设置为true,即可取消冒泡
    event.cancelBubble = true;
};

(3)事件的委派

我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的。
事件的委派是指将事件统一绑定给元素的共同的祖先元素,
这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。

(4)事件的绑定

//使用 对象.事件 = 函数 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,
//不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
    alert(1);
};
//此时上面的onclick事件会被覆盖
btn01.onclick = function(){
    alert(1);
};

addEventListener()

1. 使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照函数的绑定顺序执行
2. 参数:
(1)事件的字符串,不要on
(2)回调函数,当事件触发时该函数会被调用
(3)是否在捕获阶段触发事件,需要一个布尔值,一般都传false
3.这个方法不支持IE8及以下的浏览器
例:btn01.addEventListener("click",function(){ alert(1)},false);

attachEvent()

1.IE8中可以使用attachEvent()来绑定事件,这个方法也可以同时为一个事件绑定多个处理函数。
2.不同的是它是后绑定先执行,执行顺序和addEventListener()相反
3.参数:(1)事件的字符串,要on (2)回调函数
例:btn01.attachEvent("onclick",function(){alert(1);});

定义一个函数,用来为指定元素绑定响应函数

// addEventListener()中的this,是绑定事件的对象,attachEvent()中的this,是window
// 需要统一两个方法this
// 参数:1.obj 要绑定事件的对象;2.eventStr 事件的字符串(不要on);3.callback 回调函数		
function bind(obj , eventStr , callback){
    if(obj.addEventListener){
        //大部分浏览器兼容的方式
        obj.addEventListener(eventStr , callback , false);
    }else{
        //IE8及以下
        obj.attachEvent("on"+eventStr , function(){
            //在匿名函数中调用回调函数,this是谁由调用方式决定
            callback.call(obj);
        });
    }
}

(5)事件的传播

1.关于事件的传播网景公司和微软公司有不同的理解
(1)微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。
(2)网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,
然后在向内传播给后代元素。
2. W3C综合了两个公司的方案,将事件传播分成了三个阶段
(1)捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
(2)目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件
(3)冒泡阶段:事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
3.如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
4.IE8及以下的浏览器中没有捕获阶段

(6)滚轮事件

//1. onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,但是火狐不支持该属性
//2.在火狐中需要使用 DOMMouseScroll 来绑定滚动事件,注意该事件需要通过addEventListener()函数来绑定
box1.onmousewheel = function(event){
    //兼容IE8
    event = event || window.event;
    //判断鼠标滚轮滚动的方向
    if(event.wheelDelta > 0 || event.detail < 0){
        //向上滚,box1变短
        box1.style.height = box1.clientHeight - 10 + "px";
    }else{
        //向下滚,box1变长
        box1.style.height = box1.clientHeight + 10 + "px";
    }
    //1.使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
	//2.需要使用event来取消默认行为event.preventDefault()(IE8不支持);
    event.preventDefault && event.preventDefault();
    //取消浏览器默认行为
    return false;
};
//为火狐绑定滚轮事件
bind(box1,"DOMMouseScroll",box1.onmousewheel);

function bind(obj , eventStr , callback){
    if(obj.addEventListener){
        //大部分浏览器兼容的方式
        obj.addEventListener(eventStr , callback , false);
    }else{
        //IE8及以下
        obj.attachEvent("on"+eventStr , function(){
            //在匿名函数中调用回调函数
            callback.call(obj);
        });
    }
}

(7)键盘事件

onkeydown 和 onkeyup

1. onkeydown
(1) 按键被按下
(2) 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发
(3) 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快(防止误操作)
2. onkeyup
(1) 按键被松开
(2) 不会连续触发
注:键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

通过代码判断同时按下 CTRL + Y

//1.可以通过keyCode来获取按键的编码,通过它可以判断哪个按键被按下
//2.除了 keyCode,事件对象中还提供了几个属性:altKey,ctrlKey,shiftKey(判断是否按下,是true否false)
document.onkeydown = function(event){
    event = event || window.event;
    //判断y和ctrl是否同时被按下
    if(event.keyCode === 89 && event.ctrlKey){
        console.log("ctrl和y都被按下了");
    }
};

控制input中不能输入数字

//获取input的dom节点
var input = document.getElementsByTagName("input")[0];
//当在input中按下按键时触发
input.onkeydown = function(event){
    event = event || window.event;
    //使文本框中不能输入数字(数字1-9的Unicode编码是48-57)
    if(event.keyCode >= 48 && event.keyCode <= 57){
        //在文本框中输入内容,属于onkeydown的默认行为,如取消默认行为,则输入的内容不会出现在文本框中
        return false;
    }
};

使div可以根据不同的方向键向不同的方向移动

//为document绑定一个按键按下的事件
document.onkeydown = function(event){
    event = event || window.event;
    //定义一个变量,来表示移动的速度
    var speed = 10;
    //当用户按了ctrl以后,速度加快
    if(event.ctrlKey){
        speed = 500;
    }

    switch(event.keyCode){
        case 37:
            //alert("向左"); left值减小
            box1.style.left = box1.offsetLeft - speed + "px";
            break;
        case 39:
            //alert("向右");
            box1.style.left = box1.offsetLeft + speed + "px";
            break;
        case 38:
            //alert("向上");
            box1.style.top = box1.offsetTop - speed + "px";
            break;
        case 40:
            //alert("向下");
            box1.style.top = box1.offsetTop + speed + "px";
            break;
    }

};

25.BOM(浏览器对象模型)

BOM可以使我们通过JS来操作浏览器,在BOM中为我们提供了一组对象,用来完成对浏览器的操作.
1. Window 	 
   代表的是整个浏览器的窗口,同时window也是网页中的全局对象
2. Navigator 
   代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
3. Location  
   代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
4. History   
   代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录。由于隐私原因,该对象不能获取到具体的历史记录,    只能操作浏览器向前或向后翻页。而且该操作只在当次访问时有效
5.Screen
   代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息(一般用于手机端开发)

注:这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用。

(1)Navigator

1. 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
2. 由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
3. 一般我们只会使用userAgent来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent
(1)火狐:firefox
(2)谷歌:Chrome
(3)IE10及以下:msie
(4)IE11:"ActiveXObject" in window === true

(2)History

1.length 	属性,可以获取到当成访问的链接数量
2.back() 	可以用来回退到上一个页面,作用和浏览器的回退按钮一样
3.forward() 可以跳转下一个页面,作用和浏览器的前进按钮一样
4.go() 		可以用来跳转到指定的页面,它需要一个整数作为参数
(11:表示向前跳转一个页面 相当于forward()
(2)-1:表示向后跳转一个页面

(3)Location

1.如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
console.log(location);

2.如果直接将location属性修改为一个完整的路径,或相对路径,则我们页面会自动跳转到该路径,并且会生成相应的历史记录。
location = "http://www.baidu.com";

3.assign() 	用来跳转到其他的页面,作用和直接修改location一样
location.assign("http://www.baidu.com");

4.reload()	用于重新加载当前页面,作用和刷新按钮一样,如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面。
location.reload(true);

5.replace()	可以使用一个新的页面替换当前页面,调用完毕也会跳转页面,不会生成历史记录,不能使用回退按钮回退
location.replace("01.BOM.html");

26.定时器

(1)定时调用

setInterval()

1.定时调用,可以将一个函数,每隔一段时间执行一次
2.参数:
(1)回调函数,该函数会每隔一段时间被调用一次
(2)每次调用间隔的时间,单位是毫秒
3.返回值:
(1)返回一个Number类型的数据
(2)这个数字用来作为定时器的唯一标识
4.在开启定时器之前,需要将当前元素上的其他定时器关闭

var num = 1;
var timer = setInterval(function(){
    count.innerHTML = num++;
    if(num == 11){
        //关闭定时器
        clearInterval(timer);
    }
},1000);

(2)延时调用

setTimeout()

1.延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次
2.延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
3.延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

var timer = setTimeout(function(){
    console.log(num++);
},3000);
//使用clearTimeout()来关闭一个延时调用
clearTimeout(timer);

27.JSON

为什么用JSON?

1. JS中的对象只有JS自己认识,其他的语言都不认识
2. JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互。

JSON

1.JSON:JavaScript Object Notation JS对象表示法
2.JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,其他的和JS语法一致
3.JSON分类:
(1)对象 {}   
(2)数组 []
4.JSON中允许的值:
(1)字符串
(2)数值
(3)布尔值
(4)null
(5)对象
(6)数组

json --> js对象

 JSON.parse()
- 可以将以JSON字符串转换为js对象
- 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回
var json = '{"name":"孙悟空","age":18,"gender":"男"}';
var o = JSON.parse(json);

JS对象 ---> JSON

JSON.stringify()
- 可以将一个JS对象转换为JSON字符串
- 需要一个js对象作为参数,会返回一个JSON字符串
var str = JSON.stringify(obj3);

eval()

1.这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
2.如果使用eval()执行的字符串中含有{},它会将{}当成是代码块
3.如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
4.eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,
5.但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患