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 语句。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值