Javascript基础学习

* JavaScript诞生于1995年,主要用于前端验证,比如用户名的长度 密码的长度 邮箱的格式等

* ECMAScript是一个标准,这个标准需要各厂商去实现; 一般认为和JS一个意思;

包括 ECMAScript    DOM(文档对象模型 通过Js操作网页)   BOM(浏览器对象模型  通过JS操作浏览器)

不同浏览器实现方式
浏览器js实现方式
Firefox

Spidemonkey

Internet ExplorerJScript/Chakra
SafariJavascriptCore
ChromeV8
CarakanCarakan

目录

JS 的 helloworld

JS编写的位置

JS的基本语法

一、字面量和变量

     1. 基本含义  

      2.   数据类型-字面量的类型(6种)

二、标识符

三、运算符 

 1、算数运算符(主要适用于Number)

2、一元运算符(适用于任意数据类型)

3、逻辑运算符 (非 与 或)

4、赋值运算符 

5、关系运算符

6. 相等运算符(也属于关系运算符)

7. 条件运算符(也叫三元运算符)

8. 运算符的优先级

四、流程控制语句(if switch while for)

1. if 语句(条件判断语句)

2. switch语句(条件分支语句)

3. while语句(循环语句)

4. for循环(循环语句)

5. 嵌套的for循环 

附加break和continue

JS 对象—object

一、对象及其语法

1.  对象分类:

2. 自定义对象语法:

3. 对象属性值和属性名

4. in 运算符

二、基本数据类型和引用数据类型区别

三、函数function

1. 对象自变量

2. 函数function

3. 函数的参数

4. 函数返回值 

5. 实参可以是任何值

6. 返回值的类型 

7. 立即执行函数

8. 对象--方法

9. 作用域(变量作用的范围)

10. this

11. 使用工厂方法创建对象

12. 构造函数 ?

13. 构造函数修改+原型对象

四、tostring 

1. tostring ?

2. 垃圾回收(GC) ?

五、数组

1. 内建对象 数组(array)也是一个对象

2. 数组字面量

3. 数组的四个方法

4. 数组的遍历(将数组中所有元素都取出来)

5. foreach--遍历数组(只支持IE8以上的浏览器)    

6. slice和splice

7. 数组的剩余方法

六、函数对象的方法 

七、arguments实参的对象

八、date对象

九、math对象 

十、包装类

 十一、正则表达式

1. 正则表达式的介绍

2. 正则的语法

3. 字符串和正则相关的方法

4. 正则表达式的语法

5. 其他语法:特殊字符

6. 练习--检查手机号

7. 练习-- 邮件正则

JS-DOM (Document Object Model)

一、DOM概述

二、DOM文档节点:构成HTML的基本单元

1. 文档节点:HTML文档

2. 元素节点:

3. 属性节点:

4. 文本节点:

5. DOM文档方法介绍(常用)

三、使用DOM操作CSS

1.  通过JS修改元素的样式   

2. 获取元素的样式 

四、DOM文档事件

1.  事件对象

2. 鼠标事件(拖拽事件)

3. 冒泡事件

4. 事件的绑定

5. 事件的传播(了解) 

6. 滚轮的事件

7. 键盘事件

8. 键盘移动div方向 练习

JS-BOM (Browser Object Model)

一、BOM概述

1. BOM 浏览器对象模型

2. BOM对象: 

二、BOM对象属性及方法

1. Navigator 对象

2、History 对象

3. Location 对象

4. 定时器

5. 类的操作

6. JSON


JS 的 helloworld

-第一条第一条代码(3个输出语句):记住 alert   document.write  console.log

* console 用户看不到

#代码①

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>

	<!-- JS代码需要写到script标签中 -->
	<script type="text/javascript">

		alert("Hello World!我是弹出框");
        document.write("把我写在body里啦~~");
        console.log("我在控制台呢,body里看不到哦");

	</script>

</head>
<body>
	
</body>
</html>

JS编写的位置

* 写在body标签中(不方便维护,不推荐)

* 写在内部script标签中

* 写在外部JS文件中,然后在html中引用(推荐!)

注:JS代码是按照从上到下一步步执行的

JS的基本语法

* 注释 (多行注释&单行注释)

* 区分大小写

#代码②

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">

		/*
		多行注释 JS注释
		注释内容不会被执行,可以在源代码中查看*/

		// 单行注释

		/* 
			1. JS中严格区分大小写
			2. JS中每条语句以分号结尾;如果不写浏览器会添加上,消耗系统资源
			3. JS中自动忽略多个空格和代码
		*/
		alert("我区分大小写 Wo Qu");

        // 字面量和变量演示:
        var age=27;
        console.log(age);
	</script>
</head>
<body>
	
</body>
</html>

一、字面量和变量

     1. 基本含义  

         -- 字面量就是1234....写什么输出什么;

        -- 变量用来保存字面量,比如 a=1234;

        -- 声明变量使用var关键字声明一个变量,比如 var a;     

           为变量赋值a=1234;

        -- 声明和赋值同时进行: var a=1234;   var age=27;

          console.log(age);     27就会在控制台显示了(如上#代码②

      2.   数据类型-字面量的类型(6种)

        Ⅰ.  String  字符串

                * 字符串需要用单引或双引引起来,引号不能同类嵌套 

                         var str= '我说:“今天天气真不错!”’;  console.log(str);

                * 在字符串中可以使用\作为转义字符,表示特殊符号时可以用\转义

                        \"   表示 "

                        \'   表示 ‘

                        \n   表示换行

                        \t   制表符 相当于按了table

                        \\   表示 \   

            var str= '我说:“今天天气真不错!”’;  console.log(str);

            str="我说:\“今天\t天气真不错!\”";   (注意上一行已经给str声明了,这一行不用再写var了)

            输出字符串:   alert("str");         输出变量str:   alert(str);

        Ⅱ.  Number 数值

                在JS中所有的数值都是number类型,包括整数和小数 

                        var a=123.456; (数字)   var b="123.456";(字符串)

                可以用typeof来检查变量的类型,比如 console.log(typeof a);

        

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">        
        // JS中可以表示数字的最大值 Number.MAX_VALUE
		console.log(Number.MAX_VALUE);
		// JS中可以表示数字的最小正值 Number.MIN_VALUE
		console.log(Number.MIN_VALUE);

		// 如果使用Number表示的数字超过了最大值,会返回一个
		// (-)Infinity,表示(负)正无穷。
		var a=-Number.MAX_VALUE * Number.MAX_VALUE;
		console.log(a);

		// NON  not a number

		// 在JS中整数的运算基本可以保证精确,但浮点数(小数)可能不精确
		var b=1+2;
		console.log(b);
		var c=0.1+0.2;
		console.log(c);
</script>
</head>
<body>
	
</body>
</html>

        Ⅲ. Boolean  布尔值

                只有2个,true false

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Boolean布尔值</title>
	<script type="text/javascript">
		/* Boolean布尔值只有两个: true(真)  false(假)*/
		var bool=true;
		console.log(bool);
		console.log(typeof bool);

		var a=true;
		console.log(a);
		console.log(typeof a);
	</script>
</head>
<body>
	
</body>
</html>

        Ⅳ. Null  空值

                只有1个值 null 空对象  检查为object

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		/* Null类型的值只有一个,就是null,专门表示空对象*/
		var a=null;
		console.log(a);
		// 使用typeof检查时会返回object
		console.log(typeof a);

		// Undefined类型的值只有一个,就是undefined,当声明一个对象,但不给对象赋值时,它的值就是undefined
		var b;
		console.log(b);
		// 使用typeof检查时也会返回undefined
		console.log(typeof b);
	</script>
</head>
<body>
	
</body>
</html>

        Ⅴ. Undefined  未定义 (见上html)

                不给对象赋值时,值为undefined

        Ⅵ. Object  对象(Object为引用数据类型,其他均为基本数据类型)

        附加1:强制类型转换  

        1. 强制将其他数据类型转换为String

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		/*强制类型转换:
			--将一个数据强制转换为其他类型数据
			--主要指将其他数据类型转换为 String Number Boolean*/

		/*其他数据转为String,
		方式一:调用被转换数据类型的toString()方法;
		该方法不会影响原变量;但有局限性,对null和undefined会报错
		*/
		var a=123;
		a=a.toString();
		console.log(a);
		console.log(typeof a);

		var b=true;
		b=b.toString();
		console.log(b);
		console.log(typeof b);
		// 调用xxx的yyy()方法,就是xxx.yyy();

		// var c=null;
		// c=c.toString();
		// console.log(c);
		// console.log(typeof c);

		// var d;
		// d=d.toString();
		// console.log(d);
		// console.log(typeof d);

		/*其他数据转为String,
		方式二:调用String()函数
		*/

		var e=null;
		e=String(e);
		console.log(e);
		console.log(typeof e);
	</script>
</head>
<body>
	
</body>
</html>

        2. 强制将其他数据类型转换为Number

               var a="abc";   转换  a=Number(a);   

                ①String转Number:转换方式1:

                *纯数字的字符串直接转化为数字;

                * 字符串中有非数字内容,转换为NAN;

                * 字符串是空的,或是全为空格的字符串

                        转换方式2:(也可以转换Boolean等)

                       整数  a="123px";    转化ParseInt(a);      小数 a="123.456px";  ParseFloat(a);

                       可以将一个字符串的有效数字内容取出来转换为Number,后面的字母不变

                ② Boolean转Numbe    rtrue→1    false→0

                ③ Null转Number   数字 0

                ④ Undefined转Number  数字 NAN

        3. 强制将其他数据类型转换为Boolean

                数字转Boolean,除了0和NAN是false,其余都是true;

                字符串转Boolean,除了空串是false,其余都是true;

                null和undefined都会转成false;

                对象也会转换为true

                

        附加2:其它进制的数字

                        在JS中,表示16进制数字,需要0x开头; a=0x10   16   a=0xff   a=0xCafe

                        8进制的数字,以0开头; a=070 

                        2进制的数字,以0b开头;a=0b10

        注:a="070";转化为Number,用a=parseint(a);转化时,有的浏览器当成8进制解析为56,有的当成10进制解析为70,因此用 a=ParseInt(a,10);

二、标识符

        --  在JS中所有的可以自主命名的都可以称为标识符,例:变量名、函数名、属性名;

        --  命名规则:

                * 标识符中只可以含有 字母、数字、_、$

                * 标识符不能以数字开头

                * 标识符不能是ES中的关键字或保留字(下图)

                * 一般采用驼峰命名法:首字母小写,其他每个单词首字母大写,其余小写 helloWorld

                举例:var d3=打比方;   

                           console.log(d3);

        -- JS底层标识符实际采用的是Unicode编码,理论上讲utf-8的所有内容都可以作为标识符,

                文字也可以,但一般不采用。

 

三、运算符 

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

 1、算数运算符(主要适用于Number)

        对非Number类型的值进行运算时,会将这些值转换为Number,然后再进行运算;任何值和NAN运算都得NAN; + - * / %

        1. + 两个值加法运算,并返回结果;如果两个字符进行加法运算,则会拼串,并返回,

        任何值和字符串做加法,都会先转化为字符串然后做拼串,举例:

        

        可以利用这一特点,将任意数据类型转换为String,只需为任意类型数据 + 一个 “”即可,这是一种隐士的类型转换,浏览器会自动完成,实际上也是调用 String()函数,举例:

        c=123;   c=c+"";  console.log("c= " + c);  →  c=123   console.log(typeof c)是String

        2. 任何值做 - * / 运算时都会自动转化为NUmber,利用这一特点也可做隐式转化,通过一个值 -0  *1  /1  将其转化为Number,原理和Number()函数一样,使用起来更简单。

        3. %  取模取余数  举例: 

                                        result = 9 % 3; console.log("result= " + result) → 0

                                        result = 9 % 4; console.log("result= " + result) → 1

2、一元运算符(适用于任意数据类型)

        1. 只需操作一个数   

        + 正号不会对数字产生任何影响;- 负号可以对数字进行取反;

       对于非Number类型的值,它会先将其转化为Number再运算,可以使用+号转换,原理和Number()一样,举例: var a=123; a=-a; a=true; a="18"; a=+a; console.log("a= " + a) 

        2. 自增和自减

       * 自增:通过自增使变量在自身基础上增加1,即自增之后原变量的值会立即增加1;

                自增分两种:a++  和  ++a;无论哪一种都会使原变量的值自增1

                不同的是 a++ 和 ++a的值不同:a++的值等于自增前的值, ++a的值等于自增后的值。

        * 自减:通过自减使变量在自身基础上减1;

                自减分两种:a--  和  --a;无论哪一种都会使原变量的值自减1

                不同的是 a-- 和 --a的值不同:a--的值等于自减前的值, --a的值等于自减后的值。

                练习:条件  var n1=10, n2=20;

                

3、逻辑运算符 (非 与 或)

        1. 非运算 ! 对布尔值进行取反操作 true变false false变true

        --如果对一个值进行两次取反则该值不会变化 a=!!a;

        --如果对非布尔值非运算,会将其先转换为布尔值再取反;可以了利用这一特点将其他数据类型转换为布尔值,为任意数据类型取两次反即可,原理和Boolean()函数一样 var b=10;  b=!!b;

        2. 与运算 &&  找false

        --两个值中只要有一个值为false就会返回false,只有两个值都为true时才会返回true;

        --JS中的“与”属于短路的与,如果第一个值为false就不会看第二个了

        3. 或运算 ||  找true

        --两个值中只要有一个值为true就会返回true,只有两个值都为false时才会返回false;

        --JS中的“或”属于短路的或,如果第一个值为true就不会看第二个了

        4. 非布尔值的与或运算  (返回原值)

        --与运算  先将其转化为布尔值再运算并返回原值

                如果第一个值为true,则必然返回第二个值;

                如果第一个值为false,必然返回第一个值;

                如果两个值都为true,则返回后边的  var result = 5 && 6;→ 6

        --或运算  

                如果第一个值为true,则直接返回第一个值; result = 2 || 1;→ 2

                如果第一个值为false,必然返回第二个值; result = NAN || 1; →1

4、赋值运算符 

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

                +=    a += 5  等价于 a = a + 5

                -=    a -= 5  等价于 a = a - 5

                *=    a += 5  等价于 a = a * 5

                /=    a /= 5  等价于 a = a / 5

                %=    a %= 5  等价于 a = a % 5

5、关系运算符

        通过关系符比较两个值的大小  关系成立返回true,不成立返回false;

                > 大于号    >= 大于等于   < 小于   <=小于等于

                var result = 5 > 10; → false   var result = 5 > 4; → true

                console.log(1 > true); → false    console.log(1 >= true); → true

                console.log(1 > "0"); → true     console.log(10 > null); → true

                console.log(10 <= "hello"); → false

                任何值和NAN做任何比较都是false

        非数值情况: 会将其转换为数字然后比较;如果两侧都是字符串,不会转换为数字,而是会比较字符串中Unicode编码,一个一个比

6. 相等运算符(也属于关系运算符)

        a. 相等    --使用==做相等运算,相等返回true,否则返回false;

                       --如果值的类型不同会自动转为相同类型再比较;console.log("1" == 1);→true

                       --NaN不和任何值相等,包括它本身 console.log(NaN==NaN);→false

                       --可以通过isNaN() 函数来判断一个值是否为NaN,是返回true,否则返回false

                                   var b = NaN;   console.log(isNaN(b));

        b. 不相等  --使用 != 做不相等运算 不相等返回false,相等返回true  也会做类型的自动转换

        c. 全等     --使用 ===表示全等,和相等类似,但它不做自动转化,必须两个值完全一样

                                   console.log("123" === 123);→false    console.log("123" ==== 123);→true

        d. 不全等   --使用  !== 表示  和不等类似   如果两个值的类型不同,直接返回true

7. 条件运算符(也叫三元运算符)

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

        -- 执行流程: 首先对条件表达式求值,true执行语句1并返回结果,false语句2返回结果

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

        --如果条件表达式的求值结果是一个非布尔值,则会将其转化为布尔值再运算

8. 运算符的优先级

        --  , 运算符   使用 , 可以分割多个语句,一般可以在声明多个变量时使用  var a=1, b=2, c=3;

        --  运算符优先级:  a. 先乘除  后加减

                                        b. 有一个运算符优先级的表,位置越靠上优先级越高

                                        c.  如果遇到优先级不确定,可以用()来改变优先级

                  举例:var result = 1+2*3;    var result = 1 || (2 && 3);    console.log("result= " +result);

        

四、流程控制语句(if switch while for)

        --流程控制语句从上到下逐行执行,并控制程序流程,根据一定条件选择执行

        --代码块:

        在JS中可以使用{}来为语句进行分组,一个大括号代表一个代码块,

        代码块里的语句要么都执行,要么都不执行;

        JS中的代码块只有分组的作用,不会把内部和外部的内容隔离。

1. if 语句(条件判断语句)

        --  可以在执行某个语句之前判断,条件成立执行,不成立不执行;

        --语法1:  if (条件表达式)

                                        语句

        -- if 语句执行时先对条件表达式求值判断,值为true则执行if后的语句,false不会执行

        -- if 语句只能控制紧随其后的那个语句,如果希望控制多条,则统一放到代码块中

        举例:var a=15;  if(a>10 && a<=20){alert("a大于10,并且a小于等于20");}

        --语法2:  if(条件表达式){语句} 

                                else{语句}

        --执行时先对条件表达式求值判断,值为true则执行if后的语句,false执行else语句

        --语法3:  if (条件表达式){语句} 

                                else if(条件表达式) {语句}

                                else if(条件表达式) {语句}

                                else{语句}

        --语句执行时,会从上至下依次对条件表达式进行求值判断,true执行当前语句,false继续向向下判断, 如果都不满足,则执行else;   该语句中只有一个代码会被执行,一旦代码执行,就不会往下执行了

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		/*从键盘输入小明的期末成绩
		当成绩为100时,"奖励一辆BMW"
		当成绩为80-90时,"奖励一台iphone15s"
		当成绩为60-80时,"奖励一本参考书"
		其他时,什么奖励也没有*/

		/*prompt()可以弹出一个提示框,该提示框带有一个文本框
		在文本框输入一段内容,该函数需要一个字符串作为参考,该字符串将会作为提示框的提示文字。
		用户输入的内容将会作为函数的返回值返回,可以定义一个变量来接收该内容*/

	
		var score = prompt("请输入小明的期末成绩(0-100):");
		// 判断值是否合法
		if(score>100 || score<0 || isNaN(score)){alert("别瞎写~~");
		}else{
			// 根据score来判断给小明什么奖励

		if(score == 100){
			alert("奖励一辆BMW");
		}else if (score>=80) {alert("奖励一台iphone15s")
			
		}else if (score>=60) {alert("奖励一本参考书")
			
		}else{alert("挨打")}
	}
		
	</script>
</head>
<body>
	
</body>
</html>

2. switch语句(条件分支语句)

        --语法:   switch(条件表达式){   case表达式:语句   break;

                                                                case表达式:语句   break;

                                                                default: 语句  break;} 

        -- 执行流程: 执行时会依次将case后表达式的值和switch后条件表达式的值进行全等比较

            结果为true,则从当前case处开始执行代码(默认执行其后的所有代码,可用break终止)

            结果为false,则继续向下执行,如果所有结果都为false,就只执行default后的语句

        -- switch和if语句功能上是重复的,双方功能可以实现,使用时根据自己习惯

       

3. while语句(循环语句)

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

        -- 语法1:   while(条件表达式){ 语句 }

        -- 执行时先对条件表达式进行求值判断,如果值为true,则执行循环体,循环体执行完毕,继续对表达式判断,为true在接着执行循环体,以此类推;如果为false,则终止循环。

        --创建一个循环:1. 创建一个初始化变量  var i = 1;

                                     2. 在循环中设置一个条件表达式    while(i<11){}

                                     3. 定义一个更新表达式,每次更新初始化变量 document.write(i++ +"br/>")

        -- 语法2:  do....while语句在执行时,会先执行循环体再判断,如果为true再继续执行,如果为false,则终止循环

        注:实际上两个功能相似,只是一先一后,do...while 可以保证至少执行一次,while不能

4. for循环(循环语句)

        提供了专门的位置来放三个表达式:初始化表达式  条件表达式  更新表达式

        -- 语法:for(初始化表达式;条件表达式; 更新表达式;){语句}

        -- 执行流程: ①初始化表达式,初始化变量;

                               ②执行条件表达式,判断是否执行循环  true执行,false终止

                               ③执行更新表达式,执行完毕后重复②

                   for循环中的三个部分都可以省略,也可以写在外部 ,如果不写任何表达式就是死循环

                        

5. 嵌套的for循环 

——————记得补上代码和练习

        通过for循环输出图形,外部循环可以控制高度,内部循环控制宽度

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

                        for(var j=0; j<5; j++){ document.write(" * "); }

                        document.write(" <br/> ");

                                           }

附加break和continue

        break:用来退出switch或循环语句,不能在if语句中使用break和continue

        可以为循环创建一个lable,来识别当前的循环,lable:循环语句  使用break时,在break后面后跟一个lable,这样break就会结束指定的循环,而不是最近的

        continue:跳过当此循环,只对最近的循环起作用

        测试程序性能,执行前开启计时器console.time("计时器的名字");需要一个计时器的名字作为参数  console.time("test");   执行后用Console.timeEnd("test"); 来停止一个计时器

        加上break可以提升性能  Math.sart()  开方

JS 对象—object

内建对象  宿主对象  自定义对象

对象也是数据类型的一种,上一篇有写到6中数据类型,对象object是一种引用数据类型,其他string、number、Boolean、null、undefined是基本数据类型;

-- 基本数据类型都是单一的值,值和值之间没有联系,不能成为一个整体;

-- 对象属于复合的数据类型,可以保存多个不同数据类型的属性;

一、对象及其语法

1.  对象分类:

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

        自定义对象:创建对象,使用new关键字调用的函数,是构造函数constructor,构造函数是专门用来创建对象的函数。

2. 自定义对象语法:

        ① 创建对象 var obj = new object();

        ② 向对象中添加属性  属性名:不强制要求遵守标识符规范,尽量遵守   对象.属性名=属性值

                obj.name="孙悟空";

                obj.gender="男";

                obj.age="18";

        ③ 读取对象中的属性(如果读取对象中没有的属性,不会报错而会返回undefined)

                console.log(obj);   console.log(obj.gender);   console.log(obj.hello)没有则会返回defined

        ④ 修改对象的属性名: 对象.属性名=新属性值  obj.name="tom";  console.log(obj.name);

        ⑤ 删除对象的属性: delete 对象.属性名    delete obj.name;

3. 对象属性值和属性名

        1. 属性名: 如果要使用特殊的属性名,不能用 . 的方式,语法:  对象["属性名"]=属性值;

                        obj["123']=789; obj["你好"]="你好";   console.log(obj["123"]);

        2. 属性值:JS对象的属性值可以是任意的数据类型,甚至可以是一个对象

                        obj.test = true;   obj.test  = null;   obj.test = undefined;

                        var obj2 = new object();     obj2.name = "猪八戒";  

                        obj.test = obj2;    console.log(obj.test.name);

4. in 运算符

        通过该运算符可以检查一个对象中是否含有指定的属性  有则返回true,无则返回false

        语法:  "属性名" in 对象

        举例: console.log("test2" in obj);     console.log("name" in obj); 

                

二、基本数据类型和引用数据类型区别

        基本数据类型保存的是值,引用数据类型保存的是地址

        1. 基本数据的变量都是保存到栈内存的,基本数据类型的值直接在栈内存中存储,值与值之间独立存在,修改一个变量的值不会影响其他变量;

            

        2. 对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个对象保存的是同一对象引用的地址,当通过一个变量修改属性时,另一个也受影响。

        

        3. 当比较两个基本数据类型的值时,就是比较值;而比较两个引用数据类型时,比较的时内存地址,如果两个对象(属性值)是一模一样的,但地址(属性名)不同,也会返回false

        例: console.log(obj3 == obj4);  就会返回false

三、函数function

1. 对象自变量

        Var obj={} ; obj.name="孙悟空”;

        Var obj2={name:"zbj",age:28,gender:"nan"  test:{name:"shs"}};

        Console.log(obj2);

2. 函数function

函数也是一个对象,函数中可以封装一些功能(代码),在需要时可以调用或执行这些功能(代码),使用typeof检查一个函数对象时,会返回function

        

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

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

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

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

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">		
		/*使用函数声明创建一个函数
		function fun2(){
			console.log("这是我的第二个函数~~");
			alert("哈哈哈哈");
			document.write("笑笑不说话");
		}
		console.log(fun2);
		// 调用函数fun2
		fun2();
		*/

		//使用函数表达式创建一个函数
		var fun3 = function(){
			console.log("我是匿名函数中封装的代码");
		}
		// 调用函数fun3
		fun3();		
	</script>
</head>
<body>
	
</body>
</html>

3. 函数的参数

函数的参数可以是任意的数据类型

定义一个用来求和的函数:可以在函数的()中指定一个或多个形参(形式参数),多个形参之间用,隔开,声明形参就相当于在函数的内部声明了对应的变量,但是并不赋值。

        

 调用函数时,可以在()中指定实参,会赋值给对应的形参,下图

 调用函数解析时不会检查实参的类型,注意检查

        --多余实参不会被赋值

        --实参如果比形参少,则多的形参是undefined

        

4. 函数返回值 

-- return后的值将作为函数的执行结果返回,可以定义一个变量来接受结果

-- 变量result的值就是函数的执行结果,函数返回什么,result的值就是什么

-- 在函数中,return后的语句不会执行 

        

5. 实参可以是任何值

        

        -- 实参可以是任意的数据类型,包括对象

        -- 当参数过多时,可以将参数封装到一个对象中,通过对象传递  

        

6. 返回值的类型 

        返回值可以是任意的数据类型,包括对象和函数,可以在函数里再声明一个函数

       

7. 立即执行函数

语法:函数对象()   函数定义完立即被调用,则叫立即执行函数,立即执行函数往往只执行一次

        例: ( function(){ alert("我是一个立即执行函数"); } )();

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

8. 对象--方法

对象的属性值可以是任意数据类型 包括函数;

如果一个函数作为对象的属性保存,我们称这个函数是这个对象的方法

调用这个函数就是调用对象的方法(method) 除了名称没其他区别

赋值:        

9. 作用域(变量作用的范围)

        ①全局作用域 :

        -- 直接写在script标签中的JS代码都在全局作用域,页面打开时创建关闭时销毁

        -- 全局作用域中有个全局对象Window,代表浏览器窗口,由浏览器创建可以直接使用

        -- 在全局作用域中创建的变量都会作为window对象的属性保存,函数都会作为window对象的放法保存;全局作用域中的变量都是全局变量,在页面的任意部分可以访问到

        

        声明提前:

        a. 变量的声明提前:使用var关键字声明的变量,会在代码执行前被声明,但不会赋值

                例: console.log("a="+a);  var a=123;   (此时a被提前声明但没有赋值a=undefined)

        b. 函数的提前声明:使用函数声明形式创建的  function 函数(){}   会在代码执行前被创建,所以我们可以在函数声明前来调用函数;

         注意:使用函数表达式创建的函数,不会被提前声明,不能声明前调用 否则报错

        

        ②函数作用域: 

        a. 调用函数作用域,函数执行完毕,函数作用域销毁;

        b. 每调用一次函数会创建一个新的函数作用域,他们之间相互独立;

        c. 函数作用域中可以访问到全局作用域,反之不可以;

        d. 在函数作用域中操作一个变量时,会在自身作用域中寻找,有就用,没有则会向上一级寻找,直到全局作用域,如果依然没有找到,直接报错referenceerror。

        e. 要在函数中直接访问全局变量可以使用window对象

        

        声明提前:

        函数声明也会在函数中所有的代码执行前执行 

        

         

        ③debug   在浏览器--检查--source---进行调试 

10. this

解析器调用函数每次都会向函数内部传递一个隐含的参数this,指向的是一个对象,这个对象称为函数执行的上下文对象;根据函数的调用方式不同,this指向不同的对象

                                        -- 以函数形式调用  this永远是window

                                        -- 以方法形式调用  this是调用方法的那个对象

        

11. 使用工厂方法创建对象

       ? 通过该方法可以大批量创建对象 

        

12. 构造函数 ?

        构造函数就是一个普通的函数,创建方式和普通函数无区别,不同的是构造函数习惯上首字母大写;

        构造函数和普通函数的区别是调用方式不同,普通函数直接调用,构造函数需要使用new关键字调用;

        构造函数的执行流程:

        ① 立刻创建一个新的对象

        ② 将新建的对象设置为函数中this,在构造函数中使用this来引用新建的对象

        ③ 逐行执行函数中的代码

        ④ 将新建的对象作为返回值返回

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

        

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

13. 构造函数修改+原型对象

        方法在构建函数内创建的,那么构造函数每执行一次就会创建一个新的sayName方法,也就是所有实例的sayName都是唯一的,这样导致执行一万次就要一万个新的放大且一模一样,没必要,可以进行修改,使所有对象共享一个方法。

        

        但该方法有局限性和问题,函数定义在全局,污染了全局作用域的命名空间,也很不安全

解决方法:原型对象

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

        ②普通函数调用prototype没有任何作用,当以构造函数形式调用时,可以通过__proto__来访问该属性;

        ③原型对象相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,可以将对象中共有的内容统一设置到原型对象中,这样不用分别为每个对象添加,也不影响全局;

        ④当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,有直接使用,没有就会去原型对象中找,找到直接使用,如果还没有再去原型对象的原型中去找,直到找到object对象的原型,依然没有找到则返回undefined。

        

        注:使用in检查对象中是否含有某个属性

        

四、tostring 

1. tostring ?

        

2. 垃圾回收(GC) ?

        程序运行久了会产生垃圾,积攒过多导致运行速度慢,利用垃圾回收机制处理垃圾;

        当一个对象没有任何变量或属性对它引用时无法操作该对象,这种对象就是垃圾,JS有自动的垃圾回收机制会自动清除销毁,我们需要做的只是将不再使用的对象设置为null即可

五、数组

1. 内建对象 数组(array)也是一个对象

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

索引:从0开始的整数就是索引,数组的存储性能比普通对象摇号,开发中常用来存储数据

  

2. 数组字面量

数组中的元素可以是任意数据类型,包括对象和函数

    

3. 数组的四个方法

①push(数组末尾添加一个或多个元素)

        -- 该方法将添加的元素作为方法的参数传递,这些元素会自动添加至数组的末尾

        -- 会将数组的长度作为返回值返回

②pop(删除数组的最后一个元素)

        -- 该方法将被删除的元素作为返回值返回

③unshift(数组开头添加元素)

        -- 会将新的数组长度作为返回值返回

④shift(删除数组第一个元素)

        -- 该方法将被删除的元素作为返回值返回

4. 数组的遍历(将数组中所有元素都取出来)

        

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		// 练习
		function Person(name, age){
			this.name=name;
			this.age=age;
		}
		// 修改Person原型中的tostring
		Person.prototype.toString=function(){
			return "Person[name="+this.name+",age="+this.age+"]"
		}
		var per=new Person("孙悟空",18);
		var per2=new Person("猪八戒",28);
		var per3=new Person("红孩儿",8);
		var per4=new Person("蜘蛛精",16);
		var per5=new Person("二郎神",38);
		var perArr=[per,per2,per3,per4,per5];
		// 创建一个函数,将perArr中满18岁的Person提取出来,然后封装到一个新的数组中并返回   arr 形参,要提取的数组
		function getAdult(arr){
			var newArr=[];
			for(var i=0; i<arr.length; i++){
			var p=arr[i];
			if(p.age>=18){
				newArr.push(p);
			}		 	
		}
		return newArr;
	}
		var result=getAdult(perArr);
		console.log(result);
	</script>
</head>
<body>
	
</body>
</html>

5. foreach--遍历数组(只支持IE8以上的浏览器)    

--这种函数由我们创建的,但不由我们调用,称为回调函数

--数组中有几个元素函数会执行几次,每次执行浏览器会将遍历到的元素以实参的形式传递出来,我们可以来定义形参读取这些内容

6. slice和splice

① slice 从数组中提取指定元素

        -- 参数:

        截取开始位置的索引,包括开始索引

        截取结束为止的索引,不包含结束索引

        索引可以传递负值,表示倒数第几个

② splice 删除数组中的指定元素,会影响原数组,指定元素从原数组删除,并将被删除的元素作为返回值返回

        -- 第一个表示开始位置的索引,

           第二个表示删除的数量,

           第三个及以后可以传递新元素,自动插入开始位置索引的前面

        

③练习:去除数组中重复的数字(使用嵌套for循环)

        var arr = [1,2,3,2,1,3,4,2,5];   (JS-7)

7. 数组的剩余方法

① concat() 可以连接两个或多个数组,并将新的数组返回;不会对原数组产生影响;既可以传输组,也可以传元素;

② join() 可以将数组转换为一个字符串,不对原数组产生影响;将转换后的字符串返回;可以指定一个字符串作为参数,这个字符串会成为连接符,如果不指定连接符,则默认使用,作为连接符

③ reverse() 直接修改原数组,反转前后颠倒

④ sort() 对数组中元素排序,也影响原数组,默认按Unicode编码排序  对纯数字也一样

⑤ 可以利用回调函数和sort指定排序规则

        回调函数中需要定义两个形参,浏览器将分别使用数组中的元素作为实参去调用回调函数,使用的元素不确定,但肯定在数组中,a一定在b前面,浏览器会根据与回调函数的返回值决定元素的排序

        返回大于0的值,元素交换位置;

        返回小于0 等于0的值,位置不变

                

六、函数对象的方法 

        call和apply  函数对象的方法,通过函数对象来调用

        

七、arguments实参的对象

        调用函数时,浏览器每次都会传递两个隐含的参数:

                ① 函数的上下文对象this,② 封装实参的对象arguments

        arguments是一个类数组对象,可以通过索引来操作数据,也可以获取长度;在调用函数时,所传递的实参都会在arguments中保存;arguments.length 获取实参的长度;

        即使不定义形参,也可以通过arguments来使用实参,arguments[0] 表示第一个实参  arguments[1]表示第二个实参

        


八、date对象

date表示时间

创建当前时间:如果直接使用构造函数创建date对象,则会封装为当前代码执行的时间

var d=newDate();

Console.log(d);

创建指定的时间对象,构造函数时传递一个表示时间的字符串作为参数

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

        -- getDate() 获取当前对象是几日   getDay() 当前是周几   getMonth() 当前月份  

        -- getTime() 获取当前日期对象的时间戳(指格林威治标准时间1970年1月1日,0时0分0秒到当前时间所花费的毫秒数(1秒=1000毫秒))  计算机底层保存时间时用的都是时间戳

        

九、math对象 

Math 不是构造函数,属于工具类,不用创建对象,里面封装了数学运算相关的方法

Math.PI 圆周率

Abs() 计算绝对值

Math.cile() 向上取整 小数进一

Math.floor()  向下取整小数舍去

Math.round()  四舍五入取整

 

Math.random()生成0-1之间的随机数,不包括0和1

max() min()获取最大值和最小值

Math.pow(x,y) 返回x的y次幂

Math sqrt 开方

十、包装类

        三个包装类将基本数据类型转换为对象,但实际应用中不会使用基本数据类型的对象,容易出不可预料的问题,主要用于浏览器将基本数据类型转化为对象。

        String() 基本数据类型转换为String对象   Number()   Boolean() 同

         字符串string的方法

        --Length 可以用来获取字符串的长度

        -- charAt() 返回字符串中指定位置的字符,根据索引获取

        -- charCodeAt() 获取字符串中指定位置字符的编码,返回Unicode编码

        -- formCharCode() 可以根据字符编码去获取字符

        -- concat() 链接两个或多个字符串,和+一样作用

        -- indexof() 检索字符串中是否含有指定内容。如果含有该内容,则会返回第一次出现的索引,如果没有找到指定内容,则返回-1;可以在第二个参数指定开始查找的位置

        -- slice() 从字符串中截取指定内容,不影响原字符串,将截取内容返回

        参数:第一个开始的索引位置包括开始、

                第二个结束的位置不包括结束位置

                省略第二个参数就会截取后面所有,可以负数-1倒数第一个、、、

        -- substring() 也是截取字符串  和slice相似,不同的是这个方法不能接收负值,负值默认为0,自动调整参数位置,如果小于第一个参数,俩参数交换位置,比如(1,0)会自动调整为(0,1)

        -- substr()  用来截取字符串,第一个参数截取开始位置的索引,第二个截取的长度

        -- split() 将一个字符串拆分为一个数组

                参数:需要一个字符串作为参数,将会根据该字符串拆分数组

                           如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素

        -- toUpperCase() 将一个字符串转化为大写并返回

        -- toLowerCase() 将一个字符串转化为小写并返回

注:后面记得跟练习和代码

十一、正则表达式

1. 正则表达式的介绍

        用于定义一些字符串的规则,计算机可以根据正则表达式检查一个字符串是否符合规则,将字符串中符合规则的内容提取出来,正则表达式也是对象object,使用typeof检查正则对象,返回object

        -- 创建正则表达式 语法: var 变量 = newRegExp("正则表达式","匹配模式");

        -- 正则表达式的方法: test() 检查一个字符串是否符合正则表达式的规则,符合true,反之false

        -- Var reg = new RegExp("a"); 检查字符串中是否含有a,大A也不行;在构造函数中可以传递一个匹配模式作为第二个参数:  i 忽略大小写       g 全局匹配模式

                 

2. 正则的语法

使用字面量创建正则表达式,语法: var 变量=/正则表达式/匹配模式

构造函数方式  Var reg=new RegExp("a", "i");  灵活

字面量方式 Reg=/ a / i;   简单

3. 字符串和正则相关的方法

-- split() 根据任意字母拆分字符串,即使不指定全局匹配,也会全部拆分 

-- Search() 搜索字符串中是否含有指定内容;搜到返回第一次出现的索引,没搜到返回-1,只能查找到第一个,不能全局查找

-- Match() 根据正则表达式,从一个字符串中将符合条件的内容提取出来,默认match找到第一个符合要求的内容就停止;

可以设置正则表达式为全局匹配模式g,这样可以匹配到所有内容;

会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果

-- replace() 可将字符串中指定内容替换成新的内容

参数: 被替换的内容,新的内容

默认只替换第一个被替换的内容可以接收一个正则表达式作为参数

4. 正则表达式的语法

① 量词: --通过量词可以设置一个内容连续出现的次数 

                -- 量词支队它前边的一个内容起作用

5. 其他语法:特殊字符

 

6. 练习--检查手机号

 

7. 练习-- 邮件正则

JS-DOM (Document Object Model)

一、DOM概述

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

HTML DOM 模型被结构化为对象树

JS中通过DOM对HTML操作

Document文档:整个HTML网页文档

Object 对象:将网页中的每个部分转换为一个对象

Model模型:表示对象之间的关系,方便我们获取对象

二、DOM文档节点:构成HTML的基本单元

浏览器加载页面时自上而下读取,一行行运行,如果将script写在页面上面,执行代码时页面还没有加载,需如图将script写在body内容的下面

我们可以为window绑定一个onload事件,这个onload事件会在整个页面加载完成后才触发,其对应的响应函数会在页面加载完成后执行,可以确保代码执行时所有的DOM对象已经加载完毕了。如下:

1. 文档节点:HTML文档

2. 元素节点:

HTML标签,浏览器会将页面中所有的标签都转换为一个元素节点, 我们可以通过document的方法来获取元素节点。

①获取元素节点

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">		
		window .onload=function(){	

		//通过id获取元素节点 
		var btn01=document.getElementById("btn01");
		console.log(btn01.innerHTML);
		// 通过标签名获取一组元素节点
		var btn=document.getElementsByTagName("button");
		console.log(btn.length);
		// 通过类名class获取元素节点
		var btn03=document.getElementsByClassName("btn03");
		console.log(btn03);
		// 通过CSS选择器获取 该方法总会返回唯一的元素,即使满足条件的有多个也只会返回一个
		 var btn04 = document.querySelector(".btn04");
   		 console.log(btn04);
   		 // 创建一个无序列表,通过CSS选择器选择该列表的所有li
   		 var list=document.querySelectorAll(".list li");
   		 console.log(list);
	};
	</script>
</head>
<body>
	<button id="btn01">通过id获取元素节点</button>
	<button>通过标签名获取一组元素节点</button>
	<button class="btn03">通过类名class获取元素节点</button>
	<button class="btn04">通过CSS选择器获取元素节点</button>

<ul class="list">
    <li>列表项1</li>
    <li>列表项2</li>
    <li>列表项3</li>
    <li>列表项4</li>
</ul>

</body>
</html>

 ②获取元素子节点

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">		
		window .onload=function(){	
			// 通过具体的元素节点调用 语法: 当前元素节点.后代节点标签名
			var btnlist=document.getElementById("btnlist");
			// 获取btnlist下的所有button节点
			var btn=btnlist.getElementsByTagName("button");
			console.log(btn.length);
			for (var i=0; i<btn.length; i++){
				console.log(btn[i].innerHTML);
			}

			// childNodes属性 获取包括文本节点、、空白等在内的所有节点
			var btn=btnlist.childNodes;
			console.log(btn.length);
			// children属性获取当前元素的所有子元素,不包括文本节点
			var btn2=btnlist.children;
			console.log(btn2.length);

			// firstChild 获取当前元素的第一个节点,也叫文本节点
			var fir=btnlist.firstChild;
			console.log(fir);
			// firstElementChild  获取当前元素的第一个子元素
			var fir2=btnlist.firstElementChild;
			console.log(fir2);
	};
	</script>
</head>
<body>
	<div id="btnlist">
		<button id="btn01">我是按钮01</button>
		<button id="btn02">我是按钮02</button>
		<button id="btn03">我是按钮03</button>
		<button id="btn04">我是按钮04</button>
		<button id="btn05">我是按钮05</button>
	</div>
	
</body>
</html>

 ③获取元素的父节点和兄弟节点

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">		
		window .onload=function(){	
			// parentNode 获取id为bj的元素父节点
			var bj=document.getElementById("bj");
			var pn=bj.parentNode;
			// 和innerHTML相似,但它会获取元素内部的内容
			console.log(pn.innerText);
			// previousSibling 获取bj的前一个兄弟节点,包括文本节点
			var pre=bj.previousSibling;
			console.log(pre);
			// previousElementSibling 获取bj的前一个兄弟元素
			var pre1=bj.previousElementSibling;
			console.log(pre1.innerText);
	};
	</script>
</head>
<body>	
<ul class="city">
	<li id="js">江苏</li>
    <li id="bj">北京</li>
    <li>上海</li>
    <li>广州</li>
    <li>深圳</li>
</ul>
</body>
</html>

3. 属性节点

元素的属性,属性节点并非是元素节点的子节点,而是元素节点的一部分。可以通过元素节点来获取指定的属性节点。

例如:元素节点.getAttributeNode("属性名"),根据元素节点的属性名获取一个属性节点对象

4. 文本节点:

HTML标签中的文本内容

文本节点一般是作为元素节点的子节点存在的。获取文本节点时,一般先要获取元素节点,在通过元素节点获取文本节点。

例如:元素节点.firstChild;,获取元素节点的第一个子节点,一般为文本节点。

5. DOM文档方法介绍(常用)

获取HTML元素节点值
方法描述
元素节点.innerText获取 HTML 元素的 inner Text  内部内容
元素节点.innerHTML获取 HTML 元素的 inner HTML
元素节点.属性获取HTML的属性值
元素节点.getAttribute(attribute)获取 HTML 元素的属性值
元素节点.style.样式获取 HTML 元素的行内样式值
添加和删除元素
方法描述
document.createElement(element)创建元素节点,需要一个标签名作为参数,根据该标签名创建元素节点对象
.removeChild(element)删除子节点  语法: 父节点.removeChild(子节点);
.appendChild(element)添加子节点,语法: 父节点.appendChild(子节点);
.replaceChild(element)替换子节点 语法: 父节点.replaceChild(新节点,旧节点);
document.write(text)写入 HTML 输出流
document.createAttribute(attribute)创建属性节点
document.createTextNode(text)创建文本节点
元素节点.insertBefore(element)在指定的子节点前面插入新的子节点

三、使用DOM操作CSS

1.  通过JS修改元素的样式   

语法:  元素.style.样式名=样式值

注意:如果CSS样式名中含有-,在JS中是不合法的,要修改为驼峰命名法,去掉-,-后的首字母大写,比如background-color  应写作 backgroundColor

通过style属性设置的样式都是内链样式,优先级高,可以立即显示,如果CSS样式中设置 !important,此时样式是最高优先级,JS也不能覆盖,导致JS样式失效,所以尽量不要添加。

2. 获取元素的样式 

用getComputedStyle() 来获取元素样式,是window的方法,可以直接使用,需要两个参数

第一个: 要获取样式的元素

第二个:可以传一个元素,一般都传null ?

该方法会返回一个对象,对象中封装了当前元素对应的样式,如果获取的样式没有设置,则会获取真实的值而不是默认值,比如:没有设置width,他不会获取到auto,而是一个长度。

Var obj=getComputedStyle(box1,null);

Alert(obj.width);

或者Alert(getComputedStyle(box1,null).width);

定义一个函数来获取指定元素当前的样式

参数:Obj 要获取的元素    Name 要获取的样式名

Function getStyle(obj,name){Return getComputedStyle(obj,null)[name];}

其他样式属性: 

属性描述
clientWidth  clientHeight获取元素的可见宽度和高度,包括内容区和内边距,属性不带px 
offsetWidth offsetHeight 获取元素整个的宽度和高度,包括内容区、内边距和边框
offsetParent获取离当前元素最近的开启了定位的父元素,如果所有祖先元素都没有开启已定位,则返回body
offsetLeft  offsetTop当前元素对于其定位父元素的水平和垂直偏移量

scrollWidth scrollHeight 

scrollLeft 

scrollTop

获取整个滚动区域的宽度和高度

获取水平和垂直滚动条滚动的距离

四、DOM文档事件

1.  事件对象

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

2. 鼠标事件(拖拽事件)

鼠标在div移动时  显示鼠标的坐标  onmousemove  该事件会在鼠标在元素中移动时被触发

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		#areaDiv{
			width: 100px;
			height: 100px;
			background-color: red;
		}
		#showMsg{
			width: 100px;
			height: 20px;
			border: 1px solid;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var areaDiv=document.getElementById("areaDiv");
			var showMsg=document.getElementById("showMsg");
			areaDiv.onmousemove=function(event){
				// 在IE8中,响应函数被触发时,浏览器不会传递事件对象,而是将事件对象作为window对象的属性保存
				if(!event){
					event=window.event;
				}
				var x=event.clientX;
				var y=event.clientY;
				showMsg.innerHTML= "x=" +x+ ",y="+y;
			}

		}
		
	</script>
</head>
<body>
	<div id="areaDiv"></div>
	<br/>
	<div id="showMsg"></div>
</body>
</html>

2.2 鼠标拖拽事件

 拖拽流程:

  1. 当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
  2. 当鼠标移动时被拖拽元素跟随鼠标移动  onmousemove
  3. 当鼠标松开时被拖拽元素固定在当前位置  onmouseup
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
		#box1{
			width: 100px;
			height: 100px;
			background-color: red;
			position: absolute;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var box1=document.getElementById("box1");
			// 为box1绑定一个鼠标按下事件
			box1.onmousedown=function(event){
				event=event||window.event;
				// 解决鼠标总是跳回box1左上角的问题
				var ol=event.clientX-box1.offsetLeft;
				var ot=event.clientY-box1.offsetTop;
				// 当鼠标按下并且为document绑定鼠标移动的事件
				document.onmousemove=function(event){
					// 当鼠标你按下且在页面中移动时 box1坐标随鼠标的坐标而定,但此时松开鼠标移动鼠标依然会动
					var left=event.clientX-ol;
					var top=event.clientY-ot;
					box1.style.left=left+"px";
					box1.style.top=top+"px";					
				}

				// 在鼠标按下事件执行后,为document绑定鼠标松开事件,鼠标在页面中松开时,鼠标移动事件取消,box1停止移动
				document.onmouseup=function(){
				document.onmousemove=null;
				// 要进行下次鼠标按下移动事件,则还要再取消鼠标松开事件
				document.onmouseup=null;	
				}
			}			
		}
	</script>
</head>
<body>
	我是一段文字
	<div id="box1"></div>
	<div id="box2"></div>
</body>
</html>

设置两个div 都可以被拖拽:重点  drag  setCapture  releaseCapture 

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
		#box1{
			width: 100px;
			height: 100px;
			background-color: red;
			position: absolute;
		}
		#box2{
			width: 100px;
			height: 100px;
			background-color: yellow;
			position: absolute;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var box1=document.getElementById("box1");
			var box2=document.getElementById("box2");
			// 给box1和box2开启拖拽
			drag(box1);
			drag(box2);

			// 提取一个专门用来设置拖拽的函数,参数:开启拖拽的元素
			function drag(obj){
			//当鼠标被在拖拽元素上按下时,开始拖拽
			obj.onmousedown=function(event){
				// 解决事件兼容性问题
				event=event||window.event;

				// 设置obj捕获所有鼠标按下的事件
				// setCapture() 只有IE支持,在火狐中调用不会报错,但谷歌会报错
				obj.setCapture && obj.setCapture();

				// obj的偏移量 鼠标.clentX - 元素.offsetLeft
            	// obj的偏移量 鼠标.clentY - 元素.offsetTop
				var ol=event.clientX-obj.offsetLeft;
				var ot=event.clientY-obj.offsetTop;

				// 当鼠标按下并且为document绑定鼠标移动的事件
				document.onmousemove=function(event){
					// 解决事件兼容性问题
					event=event||window.event;

					// 被拖拽元素跟随鼠标的移动而移动
					var left=event.clientX-ol;
					var top=event.clientY-ot;

					// 修改obj的位置
					obj.style.left=left+"px";
					obj.style.top=top+"px";					
				}

				// 在鼠标按下事件执行后,为document绑定鼠标松开事件,鼠标在页面中松开时,鼠标移动事件取消,停止移动
				document.onmouseup=function(){
				document.onmousemove=null;
				// 要进行下次鼠标按下移动事件,则还要再取消鼠标松开事件
				document.onmouseup=null;	
				// 鼠标松开时取消对事件的捕获
				obj.releaseCapture && obj.releaseCapture();
				}

			/*
             当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
             此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
             如果不希望发生这个行为,则可以通过return false来取消默认行为,
             但是这招对IE8不起作用
             */
				return false;
			}			
		}
	}
	</script>
</head>
<body>
	<div id="box1"></div>
	<div id="box2"></div>
</body>
</html>

3. 冒泡事件

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

3.1 演示和取消事件冒泡

取消冒泡:将事件对象的cancelBubble设置为true即可

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
		#box1{
			width: 200px;
			height: 200px;
			background-color: yellowgreen;
		}
		#s1{
			background-color: yellow;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var s1=document.getElementById("s1");
			s1.onclick=function(event){
				event=event||window.event;
				alert("我是span的单击响应函数");

				// 取消冒泡:将事件对象的cancelBubble设置为true即可
				event.cancelBubble=true;
			};
			var box1=document.getElementById("box1");
			box1.onclick=function(){
				alert("我是box1的单击响应函数");
			}
			document.body.onclick=function(){
				alert("我是body的单击响应函数");
			}
		}
	</script>
</head>
<body>
	<div id="box1">
		我是box1
		<span id="s1">我是span</span>
	</div>
</body>
</html>

3.2 事件的委派

指将一件事统一绑定给元素的共同祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件;

事件委派利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。

target  event中的target表示触发事件的对象

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			// var allA=document.getElementsByTagName("a");
			// for(var i=0; i<allA.length; i++){
			// 	allA[i].onclick=function(){
			// 		alert("我是a的单击响应函数");
			// 	}
			// }

			// 需求:只绑定一次事件即可应用到多个元素上,即使元素是后添加的,尝试将其绑定给元素的共同祖先元素,即 事件委派
			var ul=document.getElementById("ul");
			ul.onclick=function(event){
				event=event||window.event;

				// target  event中的target表示触发事件的对象
				// alert(event.target);
				// 如果触发事件的对象是我们期望的元素则执行,否则不执行
				if(event.target.className=="link"){
					alert("我是ul的单击响应函数");
				}
			}
			
		}
	</script>
</head>
<body>
	<button id="btn01">添加超链接</button>
	<ul id="ul" style="background-color: #bfa;">
		<li>
			<p>我是p元素</p>
		</li>
		<li><a href="javascript:;" class="link" >超链接1</a></li>
		<li><a href="javascript:;" class="link" >超链接2</a></li>
		<li><a href="javascript:;" class="link" >超链接3</a></li>
	</ul>
</body>
</html>

4. 事件的绑定

① 对象.事件=函数  

此形式绑定响应函数,只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,后面的会覆盖前面的,如下:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			// 点击按钮以后弹出一个内容
			var btn01=document.getElementById("btn01");

			// 为btn01绑定第一个响应函数
			btn01.onclick=function(){
				alert(1);
			}
			// 为btn01绑定第二个响应函数
			btn01.onclick=function(){
				alert(2);
			}

		}
	</script>
</head>
<body>
	<button id="btn01">我是个按钮</button>
</body>
</html>

② addEventListener() 中的this是指绑定事件的对象,可以同时为一个元素的相同事件绑定多个响应函数,这样事件被触发时,响应函数将会按照函数绑定顺序执行。

语法:addEventListener(参数1,参数2,参数3);

参数1:事件的字符串,不要on,比如click,而不是onclick;

参数2:回调函数,当事件被触发时,该函数会被调用;

参数3:一个布尔值,一般传false,是否在捕获阶段触发事件

但此方法不支持IE8,在IE8要用attachEvent() 中的this是指window,但火狐和chrome不支持

语法: attachEvent(参数1,参数2);

参数1:事件的字符串,要on,比如onclick

参数2:回调函数

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			// 点击按钮以后弹出一个内容
			var btn01=document.getElementById("btn01");

			// addEventListener 同时为一个元素的相同事件绑定多个响应函数,这样事件被触发时,响应函数将会按照函数绑定顺序执行
			btn01.addEventListener("click",function(){
				alert(1);
			},false);
			btn01.addEventListener("click",function(){
				alert(2);
			},false);

	        // IE8版本绑定
			btn01.attachEvent("onclick",function(){
				alert(3);
			})
			btn01.attachEvent("onclick",function(){
				alert(4);
			})
		}
	</script>
</head>
<body>
	<button id="btn01">我是个按钮</button>
</body>
</html>

 ③ bind绑定函数完成两个方法this的统一

语法:bind(boj,eventStr,callback)

参数1:obj  要绑定的事件的对象

参数2:eventStr  事件的字符串(不要on)

参数3:callback  回调函数

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			// 点击按钮以后弹出一个内容
			var btn01=document.getElementById("btn01");
            bind(btn01,"click",function(){
				alert(1)
			});

			function bind(obj,eventStr,callback){
				if(obj.addEventListener){
					obj.addEventListener(eventStr,callback,false);
				}else{
					obj.attachEvent("on"+ eventStr,callback);
				}
			}
		}
	</script>
</head>
<body>
	<button id="btn01">我是个按钮</button>
</body>
</html>

5. 事件的传播(了解) 

事件的传播:关于事件的传播网景公司和微软公司有不同的理解

-- 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。

-- 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后在向内传播给后代元素。

W3C综合了两个公司的方案,将事件传播分成了三个阶段:

-- 捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
-- 目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件
-- 冒泡阶段:事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件

注:如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下我们不希望在捕获阶段触发事件,所以这个参数一般都是false

IE8以下的浏览器中没有捕获阶段

 

6. 滚轮的事件

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
			#box1{
			width: 100px;
			height: 100px;
			background-color: red;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			// 鼠标向上滚动时,box1变长,向下时,box1变短
			var box1=document.getElementById("box1");
			// box1.onmousewheel=function(){
			// 	alert("滚~~");
			// };
			// 火狐不支持onmousewheel属性,需要使用DOMMouseScroll来绑定滚动事件,该事件需要通过addEventListener()函数来绑定

			
			box1.onmousewheel=function(event){
				event=event||window.event;
				// alert(event.detail);
				// wheelDelta 判断鼠标滚动的方向 ,这个值不看大小,只看正负,上正下负
				// 火狐中用 detail获取滚动的方向,上负下正
				if(event.wheelDelta>0 || event.detail<0){
					box1.style.height=box1.clientHeight-10+"px";
				}else{
					box1.style.height=box1.clientHeight+10+"px";
				}

				// 滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,可以取消,如下
				event.preventDefault && event.preventDefault();
				return false;
			}

			// 使用addEventListener()来绑定响应函数,取消默认行为时不能使用return false;  需要用event来取消默认行为event.Default(); 但是IE8不支持,直接调用会报错
			bind(box1,"DOMMouseScroll",box1.onmousewheel);
			function bind(obj,eventStr,callback){
				if(obj.addEventListener){
					obj.addEventListener(eventStr,callback,false);
				}else{
					obj.attachEvent("on"+ eventStr,callback);
				}
			}			
		}
	</script>
</head>
<body>
	<div id="box1"></div>
</body>
</html>

7. 键盘事件

-- 键盘事件onkeydown 按键被按下,对于onkeydown来说,如果一直按着某个按键不松手,则事件会一直触发;如果连续触发,第一次和第二次之间会间隔稍长一些,其他的会非常快,这种设计是为了防止误操的发生。

-- onkeyup按键被松开

键盘事件一般都会绑定给一些可以获取到焦点的对象或是document

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			// document.onkeydown=function(){
			// 	console.log("按键按下");
			// };

			document.onkeydown=function(event){
				event=event||window.event;
				// console.log(event.keyCode);
				if(event.keyCode===89 && event.ctrlKey){
					console.log("y和Ctrl键都被按下了");
				}
			}

			// document.onkeyup=function(){
			// 	console.log("按键松开啦");
			// }

			var input =document.getElementsByTagName("input")[0];
			input.onkeydown=function(event){
				event=event||window.event;
				console.log("xingbuxinga");
				//使文本框中不可以输入数字 数字 48-57 
				if(event.keyCode >=48 && event.keyCode<=57){
					return false;
				}
			}
		}
	</script>
</head>
<body>
	<input type="text">
</body>
</html>

除了keyCode,还有其他按键判断,  altKey ctrlKey shiftKey 判断alt ctrl shift 键是否被按下,按下返回true,否则返回false

8. 键盘移动div方向 练习

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			var box1=document.getElementById("box1");
			document.onkeydown=function(event){
				event=event||window.event;
				var speed=10;
				// 按了Ctrl以后速度变为50
				if (event.ctrlKey) {
					speed=50;
				}

				// 条件分支语句,把表达式的值与每个 case 的值进行对比,如果存在匹配,则执行关联代码
				// 37-40  左上右下
				switch(event.keyCode){
					case 37:
					box1.style.left=box1.offsetLeft-speed+"px";
					break;
					case 39:
					box1.style.left=box1.offsetLeft+speed+"px";
					break;
					case 38:
					box1.style.top=box1.offsetTop-speed+"px";
					break;
					case 40:
					box1.style.top=box1.offsetTop+speed+"px";
					break;
				};		
			}
		}
	</script>
</head>
<body>
	<div id="box1" style="width: 100px; height: 100px; background-color: red; position: absolute;"></div>
</body>
</html>

JS-BOM (Browser Object Model)

一、BOM概述

1. BOM 浏览器对象模型

通过JS操作浏览器,BOM为我们提供了一组对象,来完成对浏览器的操作。

2. BOM对象: 

  • ● Window 代表整个浏览器的窗口,同时window也是网页中的全局对象

● Navigator 当前浏览器的信息,通过该对象识别不同的浏览器

● Location 当前浏览器的地址栏信息,操作浏览器跳转页面

● History 浏览器的历史记录,操作浏览器的历史记录,隐私原因,该对象不能获取具体的历史记录,只能操作浏览器向前或向后翻页,该操作只在当次访问有效

● Screen 用户的屏幕信息,获取用户显示器相关的信息

这些BOM对象都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用,比如:  console.log(location);   console.log(history);

二、BOM对象属性及方法

1. Navigator 对象

Navigator 代表当前浏览器的信息,通过该对象可以识别不同的浏览器;由于历史原因,Navigator对象中的大部分属性已经不能帮我们识别浏览器了,一般我们会用userAgent懒判断浏览器的信息,userAgent是一个字符串,包含用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent

如果通过UserAgent不能判断,还可以通过一些浏览器特有的对象来判断浏览器的信息,比如: ActiveXObject

2、History 对象

History 对象可以操作浏览器向前或向后翻页

length 属性: 获取当前访问的链接数量   alert(history.length);

back()  可以退回上一个页面,作用和浏览器的回退按钮一样

forward()  可以跳到下一个页面,作用和浏览器的前进按钮一样

go()  跳到指定的页面,需要一个整数作为参数;1 表示向前跳一个页面,相当于forward();  2表示向前跳两个; -1表示向后跳一个;  -2表示向后跳两个

3. Location 对象

直接打印location,可以获取地址栏的信息(当前页面的完整路径)  alert(location);

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

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

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

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

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			var btn=document.getElementById("btn");
			btn.onclick=function(){
				alert(location);
				location="http://www.baidu.com";
				location.assign("http://www.baidu.com");
				location.reload(true);
				// 下面这个是我自己建的一个HTML文件,测试能否跳转
				location.replace("48-BOM History.html");
			}			
		}
		
	</script>
</head>
<body>
	<button id="btn">Location</button>
</body>
</html>

4. 定时器

4.1 定时调用setInterval() 使程序可以每间隔一段时间执行一次 

setInterval() 参数:1. 回调函数,该函数每隔一段时间被回调一次; 2. 每次调用间隔的时间,单位是毫秒

返回值: 返回一个Number类型的数据, 这个数字用来作为定时器的唯一标识

clearInterval() 关闭定时器, 方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		window.onload=function(){
			var count=document.getElementById("count");
			var num=1;
			var timer=setInterval(function(){
				count.innerHTML=num++;
				if(num==8){
					clearInterval(timer);
				}
			}, 1000);

            var timer=setTimeout(function(){
				console.log(num++);
		     },3000);
			        clearTimeout(timer);
		}
	</script>
</head>
<body>
	<h1 id="count"></h1>
</body>
</html>

4.2 延时调用 setTimeout() 函数不马上执行,隔一段时间执行,只执行一次; 

与定时调用的区别:定时调用会执行多次,延时调用只会执行一次,两者可以互相代替的,开发中根据需要选择,用定时的比较多。 clearTimeout() 关闭延时调用

4.3 练习定时器

getStyle(obj,name) obj要获取样式的元素 name样式名 

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
		*{
			margin: 0;
			padding: 0;
		}
		#box1{
			width: 100px;
			height: 100px;
			background-color: red;
			position: absolute;
			left: 0;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var box1=document.getElementById("box1");
			var btn01=document.getElementById("btn01");
			var timer;
			btn01.onclick=function(){
				clearInterval(timer);				
				timer=setInterval(function(){
					var oldValue=parseInt(getStyle(box1,"left"));
					var newValue=oldValue+20;
					if(newValue>800){
						newValue=800;
					}
					box1.style.left=newValue+"px";
					if(newValue==800){
						clearInterval(timer);
					}
				},100);
			}

			// 定义一个函数,来获取指定元素的当前样式
			// getStyle(obj,name) obj要获取样式的元素 name样式名
			function getStyle(obj,name){
				if(window.getComputedStyle){
					return getComputedStyle(obj,null)[name];
				}else{
					return obj.currentStyle[name];
				}
			}	
			
		}

	</script>

</head>
<body>
	<button id="btn01">点击按钮以后box1向右移动</button>
	<br/>	<br/>
	<div id="box1"></div>
</body>
</html>

5. 类的操作

通过style 每修改一个样式浏览器就需要重新渲染一次页面,执行性能比较差,而且当我们要修改多个样式时也不太方便

5.1   addClass(obj,cn)  向元素中添加指定的class属性值
        obj:要添加class属性的元素,cn:要添加的class属性值

5.2   removeClass() 删除一个元素中指定的class属性

5.3   toggleClass() 切换一个class属性 如果元素中有这个类删除,没有则添加

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style type="text/css">
		.b1{
			width: 100px;
			height: 100px;
			background-color: red;
		}
		.b2{
			width: 200px;
			height: 200px;
			background-color: yellow;
		}
	</style>
	<script type="text/javascript">
		window.onload=function(){
			var box1=document.getElementById("box1");
			var btn01=document.getElementById("btn01");
			var b1=document.getElementsByClassName("b1");	
			btn01.onclick=function(){
                // 方法1:style 每修改一个样式浏览器就需要重新渲染一次页面,执行性能比较差,而且当我们要修改多个样式时也不太方便
				// box1.style.width="150px";
				// 通过一行代码,同时修改多个样式 修改box的class属性
				// box1.className +=" b2";
				
				// addClass(box1, " b2");
				// removeClass(box1,"b2");
				toggleClass(box1,"b2");
			}

				// addClass(obj,cn)  向元素中添加指定的class属性值
				// obj:要添加class属性的元素,cn:要添加的class属性值
				function addClass(obj, cn){	
					if(!hasClass(obj,cn)){
					obj.className += "" +cn;
				}	
			}

				// 判断obj中有没有cn class 有true,无false
				function hasClass(obj,cn){
					// 创建一个正则表达式
					var reg=new RegExp("\\b"+cn+"\\b");
					return reg.test(obj.className);
				}

				// removeClass() 删除一个元素中指定的class属性
				function removeClass(obj,cn){
					var reg=new RegExp("\\b"+cn+"\\b");
					obj.className = obj.className.replace(reg, "");
				}				
			

				// toggleClass() 切换一个class属性 如果元素中有这个类删除,没有则添加				
				function toggleClass(obj,cn){
					if(hasClass(obj,cn)){
						removeClass(obj,cn);
					}else{
						addClass(obj,cn);
					}
				}
	}

	</script>
</head>
<body>
	<button id="btn01">点击按钮以后修改box1的样式</button>
	<div id="box1" class="b1 b2"></div>
</body>
</html>

6. JSON

JSON:JavaScript Object Notation(JS对象标记法),是一种存储和交换数据的语法。

数据在浏览器和服务器进行交换是,这些数据只能是文本,JSON就是文本,且可以把任何JS对象转换为JSON,将JSON发送到服务器,同样我们可以性服务器接收任何JSON转换为JS。

JSON和JS对象格式一样,不过JSON字符串中的属性名必须加双引号

JSON.parse()     JSON转换为JS

JSON.stringify() JS转换为JSON字符串

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script type="text/javascript">
		// 创建一个对象(加引号的)
		var obj='{"name":"孙悟空", "age":18, "gender":"男"}';
		// 创建一个数组(加引号的)
		var arr='[1,2,3,"hello",true]';
		console.log(obj);
		var obj2={name:"猪八戒", age:28, gender:"男"};

		// JSON.parse()  JSON转换为JS  
		var o=JSON.parse(obj);
		var o2=JSON.parse(arr);
		console.log(o.gender);

		// JSON.stringify() JS转换为JSON字符串
		var str=JSON.stringify(obj2);
		console.log(str);
	</script>
</head>
<body>
	
</body>
</html>

JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。

JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。

由于这种相似性,无需解析器,JavaScript 程序能够使用内建的 eval() 函数,用 JSON 数据来生成原生的 JavaScript 对象。

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。如果参数是一个表达式,eval() 函数将执行表达式。如果参数是Javascript语句,eval()将执行Javascript 语句。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值