JS基础(含DOM、BOM)

JavaScript学习笔记


一、JavaScript是什么

二、JavaScript有什么作用

三、JavaScript在HTML中的引用方式

四、JavaScript的一些误区

五、JavaScript基础

  1. 注释
  2. 输入输出语句
  3. JS数据结构
  4. JS数据类型
  5. 变量
  6. 运算符
  7. 流程控制分支结构
  8. 数组
  9. 函数
  10. 作用域
  11. JS预解析
  12. JS对象
  13. 简单、复杂数据类型

六、DOM

  1. DOM简介
  2. 获取元素
  3. 事件
  4. 操作元素
  5. 节点
  6. DOM核心
  7. 事件高级

七、BOM

  1. BOM概述
  2. window对象的常见事件
  3. 定时器
  4. JS执行机制
  5. location对象
  6. history对象

一、JavaScript是什么?

1、HTML是网页的结构,CSS是网页的外观,而JavaScript是页面的行为。

2、HTML页面是静态的,平常我们所见到的各种网页特效就是使用JavaScript实现的。

二、JavaScript有什么作用?

1、动态的改变页面内容
HTML是网页的骨架,一旦编写,内容是无法改变的。JavaScript可以弥补这个不足,可以将内容动态地显示在网页中。

2、动态改变网页的外观
JavaScript通过修改网页元素的CSS样式,达到动态地改变网页的外观。(改的是css的样式)

3、验证表单数据
各大网站中的注册中的验证功能,就是JavaScript实现的。

4、响应事件
JavaScript是基于事件的语言。例如点击一个按钮弹出一个对话框,就是鼠标点击触发的事件。

对于JavaScript的理解,就一句话:如果没有使用JavaScript,网页就是静态的,仅仅是给用户浏览的。加入了JavaScript,网页的功能增加了。

三、JavaScript在HTML中的引用方式(有三种)

(1)内嵌式(head标签内);

<head>
<script type="text/javascript">
			alert("我是内部的JS代码");
</script>

(2)行内式(body标签内,在某个元素内);

<body>
    <!-- 行内式的js,直接写到元素的内部 -->
      <input type="button" value="你好世界" onclick="alert('helloWorld')">
</body>

(3)引入外部JS文件;

<head>
 <!-- 3. 外部js script 双标签 -->
    <script src="my.js"></script>   //注意在引用外部js文件时,在script标签里不能再写其他东西
</head>

四、JavaScript的一些误区             回到顶部

(1)JavaScript往往都是在网页中使用,而Java却可以在软件、网页、手机App等各个领域中使用;

(2)Java是一门面向对象的语言,而从本质上讲,JavaScript更像是一门函数式编程语言;

五、JavaScript基础               回到顶部

1、注释(两种,与java相同)

 			 1. 单行注释  ctrl + /   	// 单行注释
      		 2、多行注释  默认的快捷键 shift +  alt  + a     	 /* */
      	

2、 JS输入输出语句(三种)

		<script>
 		// 这是一个输入框,“Are you ok?”这个会出现在输入框的上面
        prompt('Are you ok?');
        // alert 弹出警示框 输出的 展示给用户的
        alert('Hello,world!');
        // console 控制台输出 给程序员测试用的 ,网页F12调出开发者模式可进行查看
        console.log('我是程序员能看到的');
        </script>

3、JS数据结构                     回到顶部

注意点:
1、标识符:
(1)第一个字符必须是字母、下划线(_)或美元符号这3种其中之一,其后的字符可以是字母、数字或下划线、美元符号;
(2)变量名不能包含空格、加号、减号等符号;
(3)标识符不能和JavaScript中用于其他目的的关键字同名;
2、关键词:
与JAVA一样,关键词有特定含义,不能乱定义

4、JS数据类型

JS里的数据类型有2大分类:一是“基本数据类型”,二是“特殊数据类型”。

基本数据类型包括以下3种:

  • 1)数字型(Number型):如整型10,浮点型6.23;
  • 2)字符串型(String型):如"你好";
  • 3)布尔型(Boolean型):true或fasle;

特殊数据类型有3种:

  • 1)空值(null型);
  • 2)未定义值(undefined型);
  • 3)转义字符;

5、变量                        回到顶部

5.1 定义:就是存放数据的、内疗可以存储任意数据

<script>
//var 变量名称 = 存储的数据;   	(variable 变量)
        var age =2333;
</script>

5.2 变量命名规范:(驼峰命名法)

1.	只能由字母、数字、_(下划线)、$(美元符号)组成。
2.	不能以数字开头。
3.	命名中不能出现-(js会理解成减号进行减法的操作),不能和关键字冲突。
js是弱类型语言,不重视类型的定义,但js会根据为变量赋值的情况自定判断该变量是何种类型:
数值型:var i = 1;	var d = 2.35;
字符串:var str = "用心学习";
布尔型:var b = true;   //这三种都为简单数据类型

5.3 isNaN()方法
isNaN() 方法用来判断非数字 并且返回一个值
》如果是数字,返回的是 false ;
》如果不是数字,返回的是true;

    <script>
        console.log(isNaN(99)); // false
        console.log(isNaN('我是个好人')); // true
    </script>

5.4数字型Number

    // 1. 八进制  0 ~ 7  我们程序里面数字前面加0 表示八进制
     var num1 = 010;
     console.log(num1); //  010  八进制 转换为 10进制 就是  8 
     var num2 = 012;
     console.log(num2);
     // 2. 十六进制  0 ~ 9  a ~ f    #ffffff  数字的前面加 0x 表示十六进制
     var num3 = 0x9;
     console.log(num3);
     var num4 = 0xa;
     console.log(num4);
     // 3. 数字型的最大值
     console.log(Number.MAX_VALUE); 	//和Java一样都是XXX.XXX  (这是一个常量)
     // 4. 数字型的最小值
     console.log(Number.MIN_VALUE);		//同上
     // 5. 无穷大
     console.log(Number.MAX_VALUE * 2); // Infinity 无穷大  
     // 6. 无穷小
     console.log(-Number.MAX_VALUE * 2); // -Infinity 无穷大
     // 7. 非数字
     console.log('我是一个好人' - 100); // NaN

5.5 字符串型String

 <script>
     var str = 'Hello,world';
     console.log(str);
     // 字符串转义字符  都是用 \ 开头
     var str1 = "你好\n世界";
     console.log(str1);
     
 	 //1. 获取字符串的长度 length 
     var str = 'Hello world';
     console.log(str.length); // 11
     // 2. 字符串的拼接 +  只要有字符串和其他类型相拼接 最终的结果都是字符串类型
     console.log('沙漠' + '骆驼'); // 沙漠骆驼 字符
     console.log('人人' + 18); // '人人18' 字母
     console.log(12 + 12); // 24,数字
     console.log('24' + 12); // '36'
 	//字符串的拼接(与java一样,用“+”号)
 	var age = 666;
 	console.log('我今年' + age + '岁'); //我今年666岁
 </script>

5.6 布尔类型 Bollean

<script>
     var abc = false; // abc 布尔型
     var abc1 =true; // abc1 布尔型
     //1. true 参与加法运算等于1
     console.log(abc +233);  //233
     //2. false 参与加法运算等于0
     console.log(abc1 +666); //667
     // 如果一个变量声明未赋值 就是 undefined 未定义数据类型
     var str;   
     console.log(str);  // undefined
     var variable = undefined;
     console.log(variable + 1); // NaN    undefined+数字 =NaN
     // null 空值,在加法运算中等于0
     var space = null;
     console.log(space + 1); // 1
 </script>

5.7 typeof用法(检测数据类型)
typeof运算符用于判断变量类型,返回的是当前变量的数据类型,这对于判断一个变量是否已被定义特别有用。

		var num = 10;
        console.log(typeof num); // number
        var str = 'abc';
        console.log(typeof str); // string
        var flag = true;
        console.log(typeof flag); // boolean
        var vari = undefined;
        console.log(typeof vari); // undefined
        var timer = null;
        console.log(typeof timer); // object

5.8数据之间的转化

 		// 1. 数字型-->字符串型  变量.toString()
        var num = 10;
        var str = num.toString(); 
        console.log(str);//'10'
        console.log(typeof str);//'String' 
        console.log(123+' ');//隐式转化:字符串拼接加空格
//-------------------------------------------------------------------------------
        // 2. parseInt(变量)/Number(变量) 字符型-->数字型
        console.log(parseInt('3.64')); // 3 取整
        console.log(parseInt('120px')); // 120 会去到这个px单位
        var str = '123';
        console.log(Number(str));
        console.log(Number('12'));
        // 2. parseFloat(变量) 字符型-->数字型(float型)
        console.log(parseFloat('3.14')); // 3.14
        console.log(parseFloat('120px')); // 120 会去掉这个px单位
        // 4. 利用算数运算 -  *  /  (隐式转换)-->转为数字型的
        console.log('12' - 0); // 12
        console.log('123' - '120');//3
        console.log('123' * 1);//123
//-------------------------------------------------------------------------------
//其他类型--->Bollean型
		console.log(Boolean('')); // false  
        console.log(Boolean(0)); // false
        console.log(Boolean(NaN)); // false
        console.log(Boolean(null)); // false
        console.log(Boolean(undefined)); // false
        console.log('------------------------------');
        console.log(Boolean('123'));

6、运算符                       回到顶部

6.1算术运算符

常用的几种:
+	-	*	/	%	++	--

具体用法:

		//1.加减乘除:
		console.log(1 + 1); // 2
        console.log(1 - 1); // 0
        console.log(1 * 1); // 1
        console.log(1 / 1); // 1
        // 2. % 取余 (取模,取得余数)  
        console.log(4 % 2); // 0
        console.log(5 % 3); // 2
        console.log(3 % 5); // 3
		//自增自减(++、--):一般用于循环中
		// 变量自增/减  ++i先自加后参与运算; i++先参与运算后自加
        var num = 1;
        var num1 = ++num; //先自加后参与运算
        var num2 = num++
        console.log(num1); // 2
        console.log(num2); // 2
        console.log(num); // 3

6.2 比较运算符
–》 返回true/false
种类:

>		>=		<		<=  	!=	
 console.log(3 >= 5); // false
        console.log(2 <= 4); // true
        //1. ==  默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以
      	  // ==	等于(只比较内容)
        console.log(3 == 5); // false
        console.log(18 == 18); // true
        console.log(18 == '18'); // true
        console.log(18 != 18); // false
        // 2. ===	恒等于(比较内容的同时还要比较数据类型)
        console.log(18 === 18); // true 
        console.log(18 === '18'); // false	

6.3 逻辑运算符

&&|| 		或	
! 		非	
//------------------------------------
 console.log(3 > 5 && 3 > 2); // false
 console.log(3 > 5 || 3 > 2); // true 
  console.log(!true); // false
//------------------------------------
  // 逻辑与短路运算&&  如果表达式1 结果为真-则返回表达式2  如果表达式1为假-则返回表达式1
        console.log(123 && 456); // 456
        console.log(0 && 456); //  0
        console.log(0 && 1 + 2 && 456 * 56789); // 0
        console.log('' && 1 + 2 && 456 * 56789); // ''
        // 如果有空的或者否定的为假 其余是真的  0  ''  null undefined  NaN
        // 4. 逻辑或短路运算  如果表达式1 结果为真 则返回的是表达式1 如果表达式1 结果为假 则返回表达式2
        console.log(123 || 456); // 123
        console.log(123 || 456 || 456 + 123); // 123
        console.log(0 || 456 || 456 + 123); // 456
        // 逻辑中断很重要 它会影响我们程序运行结果思密达
        var num = 0;
        console.log(123 || num++);
        console.log(num); // 0

6.4 赋值运算符
“=”

  <script>
        var num = 10;
        console.log(num);
        var age = 2;
        console.log(age);
    </script>

6.5 运算符优先级
小括号() >一元运算符(++、–、!)> 算数运算符(先* / % 后 + - ) > 相等运算符(== != === !==)>逻辑运算符(先&&后||)>赋值运算符(=)>逗号运算符(,)

7、流程控制分支结构                  回到顶部

7.1 if选择结构

  // 1. if 的语法结构   如果if 否则 else else...
          if (条件表达式1) {
            // 语句1;
        } else if (条件表达式2) {
            // 语句2;
        } else if (条件表达式3) {
            // 语句3;
        } else {
            // 最后的语句;
        }
  // 例子
        if (3 > 5) {
            alert('正确');
        }else if(3=3){
       		alert('还是对的') 
        }else{
        	alert('错误')
        };//还是对的

7.2 switch多分支语句

<script>
        // 1. switch 语句也是多分支语句 也可以实现多选1
        // 2. 语法结构 switch 转换、开关  case 小例子或者选项的意思
        // switch (表达式) {
        //     case value1:
        //         执行语句1;
        //         break;
        //     case value2:
        //         执行语句2;
        //         break;
        //         ...
        //         default:
        //             执行最后的语句;
        // }
        // 3. 执行思路  利用我们的表达式的值 和 case 后面的选项值相匹配 如果匹配上,就执行该case 里面的语句  如果都没有匹配上,那么执行 default里面的语句
        // 4. 代码验证
        switch (8) {
            case 1:
                console.log('这是1');
                break;
            case 2:
                console.log('这是2');
                break;
            case 3:
                console.log('这是3');
                break;
            default:
                console.log('没有匹配结果');
        }	//没有匹配结果
    </script>

7.3 for循环

for (初始化变量; 条件表达式; 操作表达式) {
            //循环体
         }
//--------------------------------------------
 for (var i = 1; i <= 100; i++) {
            console.log('Are you ok?');
        }//输出100句Are you ok?
        //与绝大多数高级语言一样,具体看java笔记(这里不详讲)

7.4 while循环和do while循环

// 1. while 循环语法结构  while 当...的时候
        // while (条件表达式) {
        //     // 循环体
        // 
        // 例子:
        var num = 1;
        while (num <= 100) {
            console.log('你好');
            num++;
        }//输出100次你好
//-------------------------------------------------
  //do while 循环 语法结构
        do {
            // 循环体
        } while (条件表达式)


        //  例子:
        var i = 1;
        do {
            console.log('how are you?');
            i++;
        } while (i <= 100)     

7.5 关键词continue和break
continue 退出本次(当前次的循环) 继续执行剩余次数循环
break 退出整个循环

8、数组                        回到顶部

		// 1.利用new 创建数组
        var arr = new Array(); // 创建了一个空的数组
        // 2.利用数组字面量创建数组 []
        var arr = []; // 创建了一个空的数组
        var arr1 = [1, true];
        console.log(arr1);
        console.log(arr1[1]); // true
        console.log(arr1[2]); // 因为没有这个数组元素 所以输出的结果是 undefined
        // 3.数组长度 数组名.length------>数组元素的个数
        console.log(arr1.length); //2
        // 4.新增数组元素
         arr1.length = 5; // 方式一:把我们数组arr1的长度修改为了 5  
         console.log(arr1[2]); // undefined    里面应该有5个元素(空的为undefined)
         arr1[5] = 666	  // 方式二:新增数组元素 修改索引号 追加数组元素
         				//	扩容成了6个元素了
         //注意点:不要直接给 数组名赋值 否则里面的数组元素都没有了
         arr1 = '啊这';
        console.log(arr1); //啊这

9、函数

函数,就是一个一系列JavaScript语句的集合,这是为了完成某一个会重复使用的特定功能。
可以方便代码重用,方便维护。

9.1 函数的定义

 <script>
        // 函数使用分为两步: 声明函数 和 调用函数
        // 1. 声明函数
         function 函数名() {
             // 函数体
         }
        function hello() {
            console.log('hello!');

        }
        // function 声明函数的关键字 全部小写
  //----------------------------------------------------------
        // 2. 调用函数
        // 函数名();
        hello();
        // 调用函数的时候千万不要忘记加小括号
    </script>

9.2 函数的值传递机制

 我们可以利用函数的参数实现函数重复不同的代码
         function 函数名(形参1,形参2...) { // 在声明函数时,小括号里面是 形参

         }
        // 函数名(实参1,实参2...); // 在函数调用时,小括号里面是 实参
        // 3. 形参和实参的执行过程
        function hello(name) { //
            console.log(name);
        }
        function hello1(a,b){
        	console.log(a+'给'+b+'打招呼');
        }
        hello('何森');//何森
        hello1('何森','张三');//何森在给张三打招呼
        // 4. 注意点
        // (1) 函数的参数可以有,也可以没有个数不限
        // (2) 多个参数之间用逗号隔开
        // (3) 形参可以看做是不用声明的变量

9.3 形参相关问题

   <script>
        // 函数形参实参个数匹配
        function getSum(num1, num2) {
            console.log(num1 + num2);
        }
        // 1. 如果实参的个数和形参的个数一致 则正常输出结果
        getSum(1, 2);//3
        // 2. 如果实参的个数多于形参的个数  只取到形参的个数(以形参数量为准)
        getSum(1, 2, 3);//3
        // 3. 如果实参的个数小于形参的个数  多于的形参定义为undefined  最终的结果就是 NaN
        // 形参可以看做是不用声明的变量  num2 是一个变量但是没有接受值  结果就是undefined 
        getSum(1); // NaN
    </script>

9.4 有返回值的函数

函数的返回值格式
         function 函数名() {
            return 需要返回的结果;
         }
         //调用函数
         函数名();
        // (1) 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名() 通过return 实现的
        // (2) 只要函数遇到return 就把后面的结果 返回给函数的调用者  函数名() = return后面的结果
         // 例子:
        function getResult() {
            return 2333;
        }
        var ABC = getResult(); 
        console.log(ABC); //2333

9.5 有返回值函数的注意点

<script>
        // 函数返回值注意事项
        // 1. return 终止函数
        function getSum(num1, num2) {
            return num1 + num2; // return 后面的代码不会被执行
            alert('改行不执行!');//这一行不会执行,在return后面
        }
        console.log(getSum(1, 2));
        // 2. return 只能返回一个值
        function fn(num1, num2) {
            return num1, num2; // 返回的结果是最后一个值
        }
        console.log(fn(1, 2));

        // 3.  我们求任意两个数的 加减乘除结果
        function getResult(num1, num2) {
            return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
        }
        var re = getResult(1, 2); // 返回的是一个数组
        console.log(re);
        
        // 4. 我们的函数如果有return 则返回的是 return 后面的值,如果函数么有 return 则返回undefined
        function fun1() {
            return 666;
        }
        console.log(fun1()); // 返回 666
        function fun2() {
        }
        console.log(fun2()); // 函数返回的结果是 undefined
    </script>

9.6 arguments的使用(伪数组)
arguments:里面存储了所有传递过来的实参
使用场景:当我们不知道用户要传多少个实参的时候,可以用arguments进行调用

 <script>
        // arguments 的使用  只有函数才有 arguments对象  而且是每个函数都内置好了这个arguments
        function fn() {
            // console.log(arguments);  arguments = [1,2,3]
            // console.log(arguments.length);	//3
            // console.log(arguments[2]);		//3
            // 我们可以按照数组的方式遍历arguments
            for (var i = 0; i < arguments.length; i++) {
                console.log(arguments[i]);
            }
        }
        fn(1, 2, 3);
        fn(1, 2, 3, 4, 5);
        // 伪数组 并不是真正意义上的数组
        // 1. 具有数组的 length 属性
        // 2. 按照索引的方式进行存储的
        // 3. 它没有真正数组的一些方法 pop()  push() 等等
 <script>
//-----------------------------------------------------------------------------
案例一:利用函数(arguments)求任意数的最大值
<script>
        // 利用函数求任意个数的最大值
        function getMax() { // arguments = [1,2,3]
            var max = arguments[0];
            for (var i = 1; i < arguments.length; i++) {
                if (arguments[i] > max) {
                    max = arguments[i];
                }
            }
            return max;
        }
        console.log(getMax(1, 2, 3)); //3
        console.log(getMax(1, 2, 3, 4, 5));//5
        console.log(getMax(11, 2, 34, 444, 5, 100));//444
</script>
//--------------------------------------------------------------------------------
<script>
 案例二:利用函数翻转任意数组 reverse 翻转
        function reverse(arr) {
            var newArr = [];
            for (var i = arr.length - 1; i >= 0; i--) {
                newArr[newArr.length] =
                 arr[i];
            }
            return newArr;
        }
        var arr1 = reverse([1, 3, 4, 6, 9]); 
        console.log(arr1);
        var arr2 = reverse(['red', 'pink', 'blue']);
        console.log(arr2);
</script>
//--------------------------------------------------------------------------------
<script>
	案例3:利用函数冒泡排序 sort 排序
        function sort(arr) {
            for (var i = 0; i < arr.length - 1; i++) {
                for (var j = 0; j < arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {
                        var temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
        var arr1 = sort([1, 4, 2, 9]);
        console.log(arr1);
        var arr2 = sort([11, 7, 22, 999]);
        console.log(arr2);
</script>

9.7 函数的两种声明方式

<script>
        // 函数的2中声明方式
         1. 利用函数关键字自定义函数(命名函数)
        function fn() {
        }
        fn(); //调用函数
        
         2. 函数表达式(匿名函数) 
        // var 变量名 = function() {};
        var fun = function(aru) {
            console.log('我是函数表达式');
            console.log(aru);
        }
        fun('qaqQAQ');
        // (1) fun是变量名 不是函数名  
        // (2) 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 而 函数表达式里面存的是函数
        // (3) 函数表达式也可以进行传递参数
    </script>

10、作用域                       回到顶部

10.1 作用域 : 就是代码名字(变量)在某个范围内起作用和效果
目的:为了提高程序的可靠性,更重要的是减少命名冲突

<script>
        // 1. js的作用域(es6)之前 : 分为 全局作用域 和  局部作用域 
        // 3. 全局作用域: 整个script标签 或者是一个单独的js文件
        var num = 10;
        var num = 30;
        console.log(num);//30

        // 4. 局部作用域(函数作用域) 在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用
        function fn() {
            // 局部作用域
            var num = 20;
            console.log(num);//20
        }
        fn();
</script>
//---------------------------------------------------------------------------
<script>
        // 变量的作用域: 根据作用域的不同我们变量分为全局变量和局部变量
        // 1. 全局变量: 在全局作用域下的变量 在全局下都可以使用
        // 注意 如果在函数内部 没有声明直接赋值的变量也属于全局变量
        var num = 10; // num就是一个全局变量
        console.log(num);

        function fn() {
            console.log(num);

        }
        fn();
        // console.log(aru);

        // 2. 局部变量   在局部作用域下的变量   后者在函数内部的变量就是 局部变量
        // 注意: 函数的形参也可以看做是局部变量
        function fun(aru) {
            var num1 = 10; // num1就是局部变量 只能在函数内部使用
            num2 = 20;
        }
        fun();
        // console.log(num1);
        // console.log(num2);
        // 3. 从执行效率来看全局变量和局部变量
        // (1) 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
</script>

JS现阶段没有块级作用域。若花括号里面定义的变量赋了值则为全局变量,在花括号外面也可以用。

10.2作用域链
作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链 就近原则

 <script>
        // 
        var num = 10;

        function fn() { // 外部函数
            var num = 20;

            function fun() { // 内部函数
                console.log(num);	//20
            		  }
            fun();
        }
        fn();
    </script>

案例:

 <script>
        // 案例1
        function f1() {
            var num = 123;
            function f2() {
                var num = 0;
                console.log(num); // 0
            }
            f2();
        }
        var num = 456;
        f1();
        // 案例2 
        var a = 1;
        function fn1() {
            var a = 2;
            var b = '22';
            fn2();
            function fn2() {
                var a = 3;
                fn3();

                function fn3() {
                    var a = 4;
                    console.log(a); //a的值 4
                    console.log(b); //b的值 '22'
                }
            }
        }
        fn1();	
    </script>

11、JS预解析                      回到顶部

  1. 我们js引擎运行js 分为两步: 预解析 代码执行
    (1). 预解析:js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
    (2). 代码执行 :按照代码书写的顺序从上往下执行
  2. 预解析分为 变量预解析(var变量提升) 和 函数预解析(function函数提升)
    (1) 变量提升:就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
    (2) 函数提升:就是把所有的函数声明提升到当前作用域的最前面 不调用函数
 // 1  
        console.log(num);  //报错,未定义
 // 2
        console.log(num); // undefined   
        var num = 10;
   // 相当于执行了以下代码,先预解析,var变量提升但赋值不提升。
   // var num;
   // console.log(num); // undefined   
   // num = 10;



        // 3  
        fn();
        function fn() {
            console.log(11);
        }
        //fn();  放在上面或下面都可以,会把这个fn()先提升,直接的函数声明


        // 4
        fun(); // 报错 
        var fun = function() {   //匿名函数
                console.log(22);
            }
    // 函数表达式 调用必须写在函数表达式的下面
    // 相当于执行了以下代码
    // var fun;  
    // fun();    赋值的这种函数不可以提升(非直接),这就一定要把函数声明写在函数调用代码的前面
    // fun = function() {
    //         console.log(22);
    //     }

案例:

案例1var num = 10;
         fun();
         function fun() {
           console.log(num);
            var num = 20;
         }
         
  // 等价于:(把函数提到了最前面,变量也先声明)
         function fun() {
            var num;
           console.log(num);
             num = 20;
         }
         num = 10;
         fun();
 -------------------------------------------------------------------------
案例2var num = 10;
         function fn() {
            console.log(num);
            var num = 20;
            console.log(num);
         }
         fn();
  // 相当于以下代码
         var num;
         function fn() {
             var num;
             console.log(num);
             num = 20;
             console.log(num);
         }
           num = 10;
           fn();
           
------------------------------------------------------------------
案例3var a = 18;
        f1();
        function f1() {
           var b = 9;
           console.log(a);
           console.log(b);
           var a = '123';
        }
    // 相当于以下代码
        var a;

        function f1() {
            var b;
            var a;
            b = 9;
            console.log(a);
            console.log(b);
           a = '123';
        }
           a = 18;
           f1();
           
---------------------------------------------------------------------
 案例4f1();
        console.log(c);
        console.log(b);
        console.log(a);

        function f1() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
  // 相当于以下代码
        function f1() {
            var a;
           a = b = c = 9;
            // 相当于 var  a  = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看
            // 集体声明  var a = 9, b = 9, c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        f1();
         console.log(c);
         console.log(b);
         console.log(a);

12、JS对象                      回到顶部

12.1 自定义对象的创建(三种方式)
一、利用对象字面量创建对象

        // var obj = {};  // 创建了一个空的对象 
        var obj = {
                uname: '张三疯',
                age: 18,
                sex: '男',
                sayHi: function() {
                    console.log('hi~');

                }
            }
          // (1) 里面的属性或者方法我们采取键值对的形式  键 属性名 : 值  属性值 
          // (2) 多个属性或者方法中间用逗号隔开的
          // (3) 方法冒号后面跟的是一个匿名函数
1.1 使用对象
          // (1). 调用对象的属性 我们采取 对象名.属性名
        console.log(obj.uname);
        // (2). 调用属性还有一种方法 对象名['属性名']
        console.log(obj['age']);//在这个对象里没出现的属性是undefined
        // (3) 调用对象的方法 sayHi   对象名.方法名()
        obj.sayHi();

二、利用new Object来创建对象

 var obj = new Object(); // 创建了一个空的对象
        obj.uname = '张三疯';   //每一句都是一个单独的句子
        obj.age = 18;
        obj.sex = '男';
        obj.sayHi = function() {
                console.log('c');
            }   
     // (1) 我们是利用 等号 = 赋值的方法 添加对象的属性和方法
     // (2) 每个属性和方法之间用 分号结束(;)
        console.log(obj.uname);		//张三疯
        console.log(obj['sex']);	//男
        obj.sayHi();				//hi~

三、利用构造函数来创建对象
可以减少代码重复,一次可以创建多个对象(利用函数封装到函数中去)

 构造函数的语法格式:
         function 构造函数名() {
             this.属性 =;
             this.方法 = function() {}
         }
 // new 构造函数名();
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);
            }
        }
-----------------------------------------------
例子:
var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
        // console.log(typeof ldh); 返回是一个对象object
        console.log(ldh.name);   //刘德华
        console.log(ldh['sex']); //男
        ldh.sing('冰雨');		 //冰雨
        var zxy = new Star('张学友', 19, '男');
        console.log(zxy.name);	 //张学友
        console.log(zxy.age);	 //19
        zxy.sing('李香兰')		 //李香兰
----------------------------------------------------
注意点:
 		1. 构造函数名字首字母要大写
        2. 我们构造函数不需要return 就可以返回结果
        3. 我们调用构造函数 必须使用 new
        4. 我们只要new Star() 调用函数就创建一个对象 ldh  {}
        5. 我们的属性和方法前面必须添加 this

12.2 构造函数和对象的关系                       回到顶部

1. 构造函数  明星 泛指的某一大类  它类似于 java 语言里面的  (class)
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);

            }
        }
        
2. 对象 特指 是一个具体的事物 刘德华 ==  {name: "刘德华", age: 18, sex: "男", sing: ƒ}
        var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
        console.log(ldh);
        // 3. 我们利用构造函数创建对象的过程我们也称为对象的实例化
-----------------------------------------------------------
<script>
3.  new关键字执行过程
        // 1. new 构造函数可以在内存中创建了一个空的对象 
        // 2. this 就会指向刚才创建的空对象
        // 3. 执行构造函数里面的代码 给这个空对象添加属性和方法
        // 4. 返回这个对象
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);

            }
        }
        var ldh = new Star('刘德华', 18, '男');
    </script>

12.3 函数、方法、对象、变量的区别                   回到顶部

 1.变量和属性的相同点:
他们都是用来存储数据的 。
变量:单独声明并赋值,使用的时候直接写变量名 单独存在
属性:在对象里面的,不需要声明的。使用的时候必须是 对象.属性

  2.函数和方法的相同点:
都是实现某种功能。
函数:单独声明,并且调用的 函数名() 单独存在的
方法:在对象里面,调用的时候 对象.方法()

12.4 遍历对象(for in 循环)
for in 对于无序号的对象属性进行遍历

<script>
        // 遍历对象 
        var obj = {
                name: '刘德华',
                age: 18,
                sex: '男',
                fn: function() {}
            }
            // console.log(obj.name);
            // console.log(obj.age);
            // console.log(obj.sex);
            // for in 遍历我们的对象
             for (变量 in 对象) {
             }
        for (var k in obj) {
            console.log(k); // k为属性名
            console.log(obj[k]); // obj[k] 是 属性值
        }
        // 我们使用 for in 里面的变量 我们喜欢写 k  或者  key
    </script>

12.5 内置对象(直接使用的工具)                    回到顶部
定义:JS里自带的一些对象,这些对象提供了一些常用的或是最基本的而必要的功能
例如:Math、Date、Array、String等

12.5.1 Math函数

 Math数学对象 不是一个构造函数 ,所以我们不需要new 来调用 而是直接使用里面的属性和方法即可
 		1、max方法
        console.log(Math.PI); // 一个属性 圆周率
        console.log(Math.max(1, 99, 3)); // 99
        console.log(Math.max(-1, -10)); // -1
        console.log(Math.max(1, 99, '其他的东西')); // NaN
        console.log(Math.max()); // -Infinity
---------------------------------------------------------------------
		2、abs方法(绝对值方法)
        console.log(Math.abs(1)); // 1
        console.log(Math.abs(-1)); // 1
        console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型
        console.log(Math.abs('abc')); // NaN 
---------------------------------------------------------------------
        3、三个取整方法
        // (1) Math.floor()   地板 向下取整  往最小了取值
        console.log(Math.floor(1.1)); // 1
        console.log(Math.floor(1.9)); // 1
        // (2) Math.ceil()   ceil 天花板 向上取整  往最大了取值
        console.log(Math.ceil(1.1)); // 2
        console.log(Math.ceil(1.9)); // 2
        // (3) Math.round()   四舍五入  其他数字都是四舍五入,但是 .5 特殊 它往大了取  
        console.log(Math.round(1.1)); // 1
        console.log(Math.round(1.5)); // 2
        console.log(Math.round(1.9)); // 2
        console.log(Math.round(-1.1)); // -1
        console.log(Math.round(-1.5)); // 这个结果是 -1
---------------------------------------------------------------------
        4、随机数方法
        random() 返回一个随机的小数  0 <= x < 1
        // 这个方法里面不跟参数
        // 例子: 
        console.log(Math.random());
        // 1. 得到两个数之间的随机整数 并且 包含这2个整数
        // Math.floor(Math.random() * (max - min + 1)) + min;
        function getRandom(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
        console.log(getRandom(1, 10));
        // 2. 随机点名  
        var arr = ['张三', '张三丰', '张三疯子', '李四', '李思思'];

        console.log(arr[getRandom(0, arr.length - 1)]);

12.5.2 Date日期对象(方法)                       回到顶部

1Date() 日期对象  是一个构造函数 必须使用new 来调用创建我们的日期对象
        var arr = new Array(); // 创建一个数组对象
        var obj = new Object(); // 创建了一个对象实例
        // 1. 使用Date  如果没有参数 返回当前系统的当前时间
        var date = new Date();
        console.log(date);
        // 2. 参数常用的写法  数字型  2019, 10, 01  或者是 字符串型 '2019-10-1 8:8:8'
        var date1 = new Date(2019, 10, 1);
        console.log(date1); // 返回的是 11月 不是 10月 
        var date2 = new Date('2019-10-1 8:8:8');
        console.log(date2);
--------------------------------------------------------------------
2、  格式化日期 年月日 (其实就是调用Date对象里的方法)
        var date = new Date();
        console.log(date.getFullYear()); // 返回当前日期的年  2019
        console.log(date.getMonth() + 1); // 月份 返回的月份小1个月   记得月份+1 
        console.log(date.getDate()); // 返回的是 几号
        console.log(date.getDay()); // 3  周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
        //2019年 5月 1日 星期三
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var dates = date.getDate();
        var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
        var day = date.getDay();
        console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
---------------------------------------------------------
3、 格式化日期 时分秒
        var date = new Date();
        console.log(date.getHours()); // 时
        console.log(date.getMinutes()); // 分
        console.log(date.getSeconds()); // 秒
        // 要求封装一个函数返回当前的时分秒 格式 08:08:08
        function getTimer() {
            var time = new Date();
            var h = time.getHours();
            h = h < 10 ? '0' + h : h;  //三元运算符
            var m = time.getMinutes();
            m = m < 10 ? '0' + m : m;
            var s = time.getSeconds();
            s = s < 10 ? '0' + s : s;
            return h + ':' + m + ':' + s;
        }
        console.log(getTimer());
---------------------------------------------------
4获得Date总的毫秒数(时间戳)
  不是当前时间的毫秒数 而是距离197011号过了多少毫秒数
        // 1. 通过 valueOf()  getTime()
        var date = new Date();
        console.log(date.valueOf()); // 就是 我们现在时间 距离1970.1.1 总的毫秒数
        console.log(date.getTime());
        // 2. 简单的写法 (最常用的写法)
        var date1 = +new Date(); // +new Date()  返回的就是总的毫秒数
        console.log(date1);
        // 3. H5 新增的 获得总的毫秒数
        console.log(Date.now());

倒计时效果案例:

<script>
        // 倒计时效果
        // 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
        // 2.用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
        // 3.把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
        // 转换公式如下: 
        //  d = parseInt(总秒数/ 60/60 /24);    //  计算天数
        //  h = parseInt(总秒数/ 60/60 %24)   //   计算小时
        //  m = parseInt(总秒数 /60 %60 );     //   计算分数
        //  s = parseInt(总秒数%60);            //   计算当前秒数
        function countDown(time) {
            var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
            var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
            var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 
            var d = parseInt(times / 60 / 60 / 24); // 天
            d = d < 10 ? '0' + d : d;
            var h = parseInt(times / 60 / 60 % 24); //时
            h = h < 10 ? '0' + h : h;
            var m = parseInt(times / 60 % 60); // 分
            m = m < 10 ? '0' + m : m;
            var s = parseInt(times % 60); // 当前的秒
            s = s < 10 ? '0' + s : s;
            return d + '天' + h + '时' + m + '分' + s + '秒';
        }
        console.log(countDown('2019-5-1 18:00:00'));
        var date = new Date();
        console.log(date);
    </script>

12.5.3 数组对象                             回到顶部

一、创建数组的两种方式
         1. 利用数组字面量
        var arr = [1, 2, 3];
        console.log(arr[0]);

         2. 利用new Array()
        // var arr1 = new Array();  // 创建了一个空的数组
        // var arr1 = new Array(2);  // 这个2 表示 数组的长度为 2  里面有2个空的数组元素 
        var arr1 = new Array(2, 3); // 等价于 [2,3]  这样写表示 里面有2个数组元素 是 2和3
        console.log(arr1);
 -------------------------------------------------------------------------
二、检测是否为数组
         (1) instanceof  运算符 它可以用来检测是否为数组
        var arr = [];
        var obj = {};
        console.log(arr instanceof Array); \\true
        console.log(obj instanceof Array); \\false
         (2) Array.isArray(参数);  H5新增的方法  ie9以上版本支持
        console.log(Array.isArray(arr));   \\true
        console.log(Array.isArray(obj));   \\false
-------------------------------------------------------------------------
三、添加、删除数组元素
     1. push() 在我们数组的末尾 添加一个或者多个数组元素
        var arr = [1, 2, 3];
        console.log(arr.push(4, '呵呵'));//返回的是新数组的长度5
        console.log(arr);//(5)[1, 2, 3, 4, 呵呵]
        // (1) push 可以给数组追加新的元素
        // (2) push() 参数写数组元素即可
        // (3) push完毕之后,返回的结果是 新数组的长度 
        // (4) 原数组也会发生变化
     2. unshift 在我们数组的开头 添加一个或者多个数组元素
        console.log(arr.unshift('red', 'purple')); //返回的是新数组的长度7
        console.log(arr);//[red, purple, 1, 2, 3, 4, 呵呵]
        // (1) unshift是可以给数组前面追加新的元素
        // (2) unshift() 参数直接写 数组元素就可以了
        // (3) unshift完毕之后,返回的结果是 新数组的长度 
        // (4) 原数组也会发生变化

      3. pop() 它可以删除数组的最后一个元素  
        console.log(arr.pop());
        console.log(arr);
        // (1) pop是可以删除数组的最后一个元素 一次只能删除一个元素
        // (2) pop() 没有参数
        // (3) pop完毕之后,返回的结果是 删除的那个元素 
        // (4) 原数组也会发生变化
      4. shift() 它可以删除数组的第一个元素  
        console.log(arr.shift());
        console.log(arr);
        // (1) shift是可以删除数组的第一个元素 记住一次只能删除一个元素
        // (2) shift() 没有参数
        // (3) shift完毕之后,返回的结果是 删除的那个元素 
        // (4) 原数组也会发生变化
--------------------------------------------------------------------------
四、数组排序
 1. 翻转数组 reverse()方法
        var arr = ['pink', 'red', 'blue'];
        arr.reverse();
        console.log(arr);

 2. 数组排序(冒泡排序) sort()方法,写法固定(需记忆,单用sort方法只能排0~9之间的数字排序)
        var arr1 = [13, 4, 77, 1, 7];
        arr1.sort(function(a, b){
            //  return a - b; 升序的顺序排列
            return b - a; // 降序的顺序排列
        });
        console.log(arr1);
-----------------------------------------------------------------------------
五、获取数组元素索引
     1、indexOf(数组元素)  作用就是返回该数组元素的索引号 从前面开始查找
        // 它只返回第一个满足条件的索引号 
        // 它如果在该数组里面找不到元素,则返回的是 -1  
        // var arr = ['red', 'green', 'blue', 'pink', 'blue'];
        var arr = ['red', 'green', 'pink'];
        console.log(arr.indexOf('blue')); //-1
     2、lastIndexOf(数组元素)  作用就是返回该数组元素的索引号 从后面开始查找
        var arr = ['red', 'green', 'blue', 'pink', 'blue'];
        console.log(arr.lastIndexOf('blue')); // 4

案例:数组去重

 数组去重 ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。
        // 1.目标: 把旧数组里面不重复的元素选取出来放到新数组中, 重复的元素只保留一个, 放到新数组中去重。
        // 2.核心算法: 我们遍历旧数组, 然后拿着旧数组元素去查询新数组, 如果该元素在新数组里面没有出现过, 我们就添加, 否则不添加。
        // 3.我们怎么知道该元素没有存在? 利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有改元素
        // 封装一个 去重的函数 unique 独一无二的 
       
        function QC(){
            var newArr = [];
            var arr = ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'];
            for(var i =0;i<arr.length;i++){
                if(newArr.indexOf(arr[i])==-1){
                    newArr.push(arr[i]);
                }
            }
            alert(newArr);
        }

        QC();

数组转化为字符串的方法(两种)

 1. toString() 将我们的数组转换为字符串
        var arr = [1, 2, 3];
        console.log(arr.toString()); // 1,2,3
        
 2. join(分隔符)   //默认分隔符为“,”
        var arr1 = ['green', 'blue', 'pink'];
        console.log(arr1.join()); // green,blue,pink
        console.log(arr1.join('-')); // green-blue-pink
        console.log(arr1.join('&')); // green&blue&pink

12.5.4 字符串对象                            回到顶部
  1、基本包装类型:把简单数据类型 包装成为了 复杂数据类型

        var str = 'andy';
        console.log(str.length);
        // 对象 才有 属性和方法   复杂数据类型才有 属性和方法 
        // (1) 把简单数据类型包装为复杂数据类型 
        var temp = new String('andy'); //加了new 就是复杂数据类型
        // (2) 把临时变量的值 给 str
        str = temp;
        // (3) 销毁这个临时变量
        temp = null;

  2、字符串的不可变性

 // 字符串的不可变性
        var str = 'andy';  //str指向andy
        console.log(str); //andy
        str = 'red'; //开辟新空间red,str指向red这个内存空间
        console.log(str); //red 
        // 因为我们字符串的不可变所以不要大量的拼接字符串
        var str = '';
        for (var i = 1; i <= 1000000000; i++) {
            str += i;
        }
        console.log(str);

 3、一些字符串的方法

	1、字符串对象  根据字符返回位置  str.indexOf('要查找的字符', [起始的位置])
        var str = '改革春风吹满地,春天来了'; //[]这个表示可有可无
        console.log(str.indexOf('春'));
        console.log(str.indexOf('春', 3)); // 从索引号是 3的位置开始往后查找
---------------------------------------------------------------------
    2、根据位置返回字符
     方法一: charAt(index) 根据位置返回字符
        var str = 'andy';
        console.log(str.charAt(3)); //y
        // 遍历所有的字符
        for (var i = 0; i < str.length; i++) {
            console.log(str.charAt(i)); //a   n   d   y
        }
     方法二: charCodeAt(index)  返回相应索引号的字符的ASCII值 
    	   目的: 判断用户按下了那个键 
        console.log(str.charCodeAt(0)); // 97  (a->97)
     方法三: str[index] H5 新增的 
        console.log(str[0]); // a
----------------------------------------------------------------------
	 3、拼接、截取字符串的方法 
	  	1. concat('字符串1','字符串2'....)
       		 var str = 'andy';
        	console.log(str.concat('red')); //andyred

      	2. substr('截取的起始位置', '截取几个字符');
      		  var str1 = '改革春风吹满地';
       		 console.log(str1.substr(2, 2));  //春风
       		 // 第一个2 是索引号的2 从第几个开始  
       		 // 第二个2 是取几个字符     
----------------------------------------------------------------------
	 4、替换字符串和字符串转化为数组
	 	 1. 替换字符 replace('被替换的字符', '替换为的字符')  它只会替换第一个字符
	        var str = 'andyandy';
	        console.log(str.replace('a', 'b'));
	        // 有一个字符串 'abcoefoxyozzopp'  要求把里面所有的 o 替换为 *
	        var str1 = 'abcoefoxyozzopp';
	        while (str1.indexOf('o') !== -1) {
	            str1 = str1.replace('o', '*');
	        }
	        console.log(str1); //abc*ef*xy*zz*pp

         2. 字符转换为数组 split('分隔符')    前面我们学过 join 把数组转换为字符串
	        var str2 = 'red, pink, blue';
	        console.log(str2.split(',')); //,为分隔符
	        var str3 = 'red&pink&blue';
	        console.log(str3.split('&')); //&为分隔符
----------------------------------------------------------------------
 	5、有一个对象 来判断该属性是否存在。对象['属性名']
 		 若存在返回属性值。(注意:0false)
  		 若不存在返回undefined 
        var o = {
            age: 2
        }
        if (o['age']=undefined) {
            console.log('里面有该属性');

        } else {
            console.log('没有该属性');
        }
        

案例:判断一个字符串 ‘abcoefoxyozzopp’ 中出现次数最多的字符,并统计其次数。

        //核心算法:利用 charAt() 遍历这个字符串
        //把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
        //遍历对象,得到最大值和该字符
        var str = 'abcoefoxyozzopp';
        var o = {};
        for (var i = 0; i < str.length; i++) {
            var chars = str.charAt(i); // chars 是 字符串的每一个字符
            if (o[chars]) { // o[chars] 得到的是属性值
                o[chars]++;
            } else {
                o[chars] = 1;
            }
        }
        console.log(o);
        // 2. 遍历对象
        var max = 0;
        var ch = '';
        for (var k in o) {    // k 得到是 属性名
            if (o[k] > max) {    // o[k] 得到的是属性值
                max = o[k];
                ch = k;
            }
        }
        console.log(max);
        console.log('最多的字符是' + ch);

13、简单数据类型和复杂数据类型            回到顶部

 13.1 简单数据类型:基本数据类型、值类型
eg:String、number、boolean、undefined、null

 // 特别的:简单数据类型 null  返回的是一个空的对象  object 
        var timer = null;
        console.log(typeof timer);

 13.2 复杂数据类型:引用数据类型。

13.3存储方式:

  1. 简单数据类型 是存放在栈里面 里面直接开辟一个空间存放的是值
  2. 复杂数据类型 首先在栈里面存放地址 十六进制表示 然后这个地址指向堆里面的数据

六、DOM (一个接口)

1、DOM简介                     回到顶部

文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口

W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。Dom树
1.文档:一个页面就是一个文档,DOM中使用doucument来表示
2.元素:页面中的所有标签都是元素,DOM中使用 element 表示
3.节点:网页中的所有内容都是节点(标签,属性,文本,注释等),DOM中使用node表示
DOM 把以上内容都看做是对象

2、获取元素

2.1 如何获取元素                     回到顶部
  • 根据 ID 获取
  • 根据标签名获取
  • 通过 HTML5 新增的方法获取
  • 特殊元素获取
2.1.1根据 ID获取

document.getElementById(‘元素’);方法,返回元素的对象

		<div id="time">2019-9-9</div>
  1. 因为我们文档页面从上往下加载,所以先得有标签 所以我们script写到标签的下面
         2. get 获得 element 元素 by 通过 驼峰命名法 
         3. 参数 id是大小写敏感的字符串
         4. 返回的是一个元素对象
        var timer = document.getElementById('time');
        console.log(timer); //一整个标签全部返回了
        console.log(typeof timer); //Object
         5. console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
        console.dir(timer);
2.1.2 根据标签名获取

document.getElementsByTagName(‘标签名’);

<ul>
        <li>知否知否,应是等你好久11</li>
        <li>知否知否,应是等你好久22</li>
        <li>知否知否,应是等你好久33</li>
        <li>知否知否,应是等你好久44</li>

</ul>
 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]); //<li>知否知否,应是等你好久11</li>
        //08 2. 依次打印里面的元素对象我们可以采取遍历的方式
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }
         3. 如果页面中只有一个li 返回的还是伪数组的形式 
         4. 如果页面中没有这个元素 返回的是空的伪数组的形式
         5. element.getElementsByTagName('标签名'); 父元素必须是指定的单个元素
        // var ol = document.getElementsByTagName('ol'); // [ol]
        // console.log(ol[0].getElementsByTagName('li'));
        var ol = document.getElementById('ol');
        console.log(ol.getElementsByTagName('li'));
2.1.3 H5新增的方法
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
</div>
<script>
  1、document.getElementsByClassName('类名') 根据类名获得某些元素集合
		var boxs = document.getElementsByClassName('box');
        console.log(boxs);
  2. querySelector 返回指定选择器的第一个元素对象  切记 里面的选择器需要加符号 .box  #nav
        var firstBox = document.querySelector('.box');
        console.log(firstBox);//<div class="box">盒子1</div>
        var nav = document.querySelector('#nav');
        console.log(nav);//<div id="nav"><ul><li>首页</li><li>产品</li></ul>
</div>
        var li = document.querySelector('li'); // <li>首页</li>
        console.log(li);
  3. querySelectorAll()返回指定选择器的所有元素对象集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox); //NodeList(2)0: div.box 1: div.box
        var lis = document.querySelectorAll('li');
        console.log(lis);//NodeList(2)0: li 1: li

</script>
2.1.4 获取特殊标签(body和html标签)

document.body;
document.documentElement;

      // 1.获取body 元素
        var bodyEle = document.body;
        console.log(bodyEle);
        console.dir(bodyEle);
      // 2.获取html 元素
        // var htmlEle = document.html;错误的
        var htmlEle = document.documentElement; 
        console.log(htmlEle);

3、事件                     回到顶部

3.1 事件概述

事件:JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。简述为触发—响应机制。

3.2 事件三要素

1、 事件源(谁)
2、 事件类型 (什么事,如何触发 什么事件,绑定事件)(可不绑定事件)
3、 事件处理程序 (会做什么处理,采取函数赋值形式)
例子:

 <button id="btn"></button>   //事件源
 <script>
 var btn = document.getElementById('btn'); //绑定事件
 btn.onclick = function() {	//事件处理程序
            alert('好帅');
        }
 </script>
3.3 常见的鼠标事件

       直达addEventListener()

鼠标事件触发条件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发

4、操作元素                     回到顶部

JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等。注意以下都是属性

4.1改变元素内容

1、从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去

element.innerText

2、起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行(标准,用的也最多)

element.innerHTML

案例:

    当我们点击了按钮,  div里面的文字会发生变化
        // 1. 获取元素 
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        // 2.注册事件
        btn.onclick = function() {
            // div.innerText = '2019-6-6';
            div.innerHTML = getDate();
        }

        function getDate() {
            var date = new Date();
            // 我们写一个 2019年 5月 1日 星期三
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var dates = date.getDate();
            var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
            var day = date.getDay();
            return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
        }
        // 我们元素可以不用添加事件
        var p = document.querySelector('p');
        p.innerHTML = getDate();
4.2 innerTest和innerHTML的区别
  1. innerText 不识别html标签 非标准 去除空格和换行
  2. innerHTML 识别html标签 W3C标准 保留空格和换行的
<p>
        我是文字
        <span>123</span>
</p>
<script>
        var div = document.querySelector('div'); 
        // div.innerText = '<strong>今天是:</strong> 2019';
        
        div.innerHTML = '<strong>今天是:</strong> 2019';
        // 这两个属性是可读写的  可以获取元素里面的内容
        //输出:今天是: 2019   ('今天是:'加粗了,识别了strong标签)
        var p = document.querySelector('p');
        console.log(p.innerText); //去除空格和换行,输出:我是文字 <span>123</span>
        console.log(p.innerHTML); //保留了空格和换行,标签识别了 输出:我是文字 123(“我是文字”加粗了)
</script>
4.3 修改元素属性

img的属性(图片)

img.src = "xxx";
//表单属性:  
input.value = "xxx";   //默认值
input.type = "xxx";    //类型
input.checked = "xxx"; //是否选中
input.selected = true / false; //是否已被选
input.disabled = true / false; //是否禁用

案例:

<body>
    <button id="ldh">刘德华</button>
    <button id="zxy">张学友</button> <br>
    <img src="images/ldh.jpg" alt="" title="刘德华" style="width:300px">

    <script>
        // 修改元素属性  src
        // 1. 获取元素
        var ldh = document.getElementById('ldh');
        var zxy = document.getElementById('zxy');
        var img = document.querySelector('img');
        // 2. 注册事件  处理程序
        zxy.onclick = function() {
            img.src = 'images/zxy.jpg';
            img.title = '张学友思密达';
        }
        ldh.onclick = function() {
            img.src = 'images/ldh.jpg';
            img.title = '刘德华';
        }
    </script>
</body>
4.4 表单元素的属性操作                    回到顶部

不能用innerHTML和innerText
type、value、checked、selected、disabled这几个元素。可以通过DOM进行修改。
例子:

<body>
    <button>按钮</button>
    <input type="text" value="输入内容">
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var input = document.querySelector('input');
        // 2. 注册事件 处理程序
        btn.onclick = function() {
            // input.innerHTML = '点击了';  这个是 普通盒子 比如 div 标签里面的内容
            // 表单里面的值 文字内容是通过 value 来修改的
            input.value = '被点击了';
            // 如果想要某个表单被禁用 不能再点击 disabled  我们想要这个按钮 button禁用
            // btn.disabled = true;
            this.disabled = true;
            // this 指向的是事件函数的调用者 btn
        }
    </script>
</body>
4.5 改变样式属性            回到顶部

行内样式操作:

element.style

类名样式操作:

element.className

案例1:

 <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
-----------------------------------------
    <body>
    <div></div>
    <script>
        // 1. 获取元素
        var div = document.querySelector('div');
        // 2. 注册事件 处理程序
        div.onclick = function() {
            // div.style里面的属性 采取驼峰命名法 
            this.style.backgroundColor = 'purple';
            div.style.width = '250px'; //div和this的都可以
        }
    </script>
</body>

注意:
1.JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
2.JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
3.如果样式修改较多,可以采取操作类名方式更改元素样式
4.class 因为是个保留字,因此使用className来操作元素类名属性
5.className 会直接更改元素的类名,会覆盖原先的类名

案例2:

<style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        
        .change {
            background-color: purple;
            color: #fff;
            font-size: 25px;
            margin-top: 100px;
        }
    </style>
</head>


<body>
    <div class="first">文本</div>
    <script>
        // 1. 使用 element.style 获得修改元素样式  如果样式比较少 或者 功能简单的情况下使用
        var test = document.querySelector('div');
        test.onclick = function() {
            // this.style.backgroundColor = 'purple';
            // this.style.color = '#fff';
            // this.style.fontSize = '25px';
            // this.style.marginTop = '100px';
            // 让我们当前元素的类名改为了 change

            // 2. 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
            // 3. 如果想要保留原先的类名,我们可以这么做 多类名选择器
            // this.className = 'change';
            this.className = 'first change';
        }
    </script>
</body>

总结:
请添加图片描述

4.6 排他思想                     回到顶部

如果有同一组元素,我们相要某一个元素实现某种样式,需要用到循环的排他思想算法:
1、所有元素全部清除样式(干掉其他人,清除所有元素的某一样式)
2、给当前元素设置样式 (留下我自己,设置自己的样式)
3、注意顺序不能颠倒,首先干掉其他人,再设置自己

<button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        // 1. 获取所有按钮元素
        var btns = document.getElementsByTagName('button');
        // btns得到的是伪数组  里面的每一个元素 btns[i]
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function() {
                // (1) 我们先把所有的按钮背景颜色去掉  干掉所有人
                for (var i = 0; i < btns.length; i++) {
                    btns[i].style.backgroundColor = '';
                }
                重点:这里只能用this,不能用btns[i]。因为外层循环的i只是给每一个按钮绑定事件(声明事件),并不会执行里面的代码。内外层的i在循环完后,都变成了i=5,故不可以。i成了固定值
                // (2) 然后才让当前的元素背景颜色为pink 留下我自己
                this.style.backgroundColor = 'pink';

            }
        }
        //2. 首先先排除其他人,然后才设置自己的样式 这种排除其他人的思想我们成为排他思想
    </script>
4.7 自定义属性

目的:保存并使用数据

4.7.1 获取自定义属性

1、获取内置属性值(元素本身自带的属性)

element.属性;

2、获取自定义的属性(自己可以添加属性,自己添加的就是自定义属性)

element.getAttribute('属性');
4.7.2 设置自定义属性值

1、设置内置属性值

element.属性 = '值';

2、主要设置自定义的属性值

element.setAttribute('属性');
4.7.3 移除属性
element.removeAttribute('属性');

综合:

var div = document.querySelector('div');
        // 1. 获取元素的属性值
        // (1) element.属性
        console.log(div.id);
        //(2) element.getAttribute('属性')  get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));
        // 2. 设置元素属性值
        // (1) element.属性= '值'
        div.id = 'test';
        div.className = 'navs';
        // (2) element.setAttribute('属性', '值');  主要针对于自定义属性
        div.setAttribute('index', 2);
        div.setAttribute('class', 'footer'); // class 特殊  这里面写的就是class 不是className
        // 3 移除属性 removeAttribute(属性)    
        div.removeAttribute('index');
4.8 H5自定义属性                           回到顶部

自定义属性目的:

保存并保存数据,有些数据可以保存到页面中而不用保存到数据库中

注:有些自定义属性很容易引起歧义,不容易判断到底是内置属性还是自定义的,所以H5有了规定

4.8.1 设置H5自定义属性

H5规定自定义属性 data-开头作为属性名并赋值

<div data-index = "1"></>
// 或者使用JavaScript设置
div.setAttribute('data-index',1);
4.8.2 获取H5自定义属性

兼容性获取:

element.getAttribute(‘data-index’)

H5新增的:

element.dataset.index 或element.dataset[‘index’] IE11才开始支持

<body>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
        var div = document.querySelector('div');
        // console.log(div.getTime);
        console.log(div.getAttribute('getTime'));
        div.setAttribute('data-time', 20);
        console.log(div.getAttribute('data-index'));
        console.log(div.getAttribute('data-list-name'));
        // h5新增的获取自定义属性的方法 它只能获取data-开头的
        // dataset 是一个集合里面存放了所有以data开头的自定义属性
        console.log(div.dataset);
        console.log(div.dataset.index);
        console.log(div.dataset['index']);
        // 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
        console.log(div.dataset.listName);
        console.log(div.dataset['listName']);
    </script>
</body>

5、节点                        回到顶部

获取元素通常使用两种方式:

1.利用DOM提供的方法获取元素2.利用节点层级关系获取元素
document.getElementById()利用父子兄节点关系获取元素
document.getElementsByTagName()逻辑性强,但是兼容性较差
document.querySelector 等
逻辑性不强,繁琐

这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单

一般的,节点至少拥有三个基本属性

5.1节点概述

网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。

HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。

基本属性:
一般的,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。

  1. 元素节点:nodeType 为1
  2. 属性节点:nodeType 为2
  3. 文本节点:nodeType 为3(文本节点包括文字、空格、换行等)

节点操作主要操作的是元素节点

5.2 父级节点
node.parentNode
  • parentNode属性可以返回某节点的父结点,注意是最近的一个父结点
  • 如果指定的节点没有父结点则返回null
<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>

    <script>
        // 1. 父节点 parentNode
        var erweima = document.querySelector('.erweima');
        // var box = document.querySelector('.box');
        // 得到的是离元素最近的父级节点(亲爸爸) 如果找不到父节点就返回为 null
        console.log(erweima.parentNode);
    </script>
</body>
5.3 子节点
parentNode.childNodes(标准)
  1. parentNode.childNodes返回包含指定节点的子节点的集合,该集合为即时更新的集合
  2. 返回值包含了所有的子结点,包括元素节点,文本节点等
  3. 如果想获取一种的元素节点,要另处理(一般不用这个)
parentNode.children(非标准) (很重要)
  1. 这是一个只读属性,返回所有的子元素节点
  2. 返回子元素节点,其余节点不返回(重点)

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>

    </ul>
    <ol>
        <li>我是li</li>
        <li>我是li</li>
    </ol>

    <div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>

    <script>
        // DOM 提供的方法(API)获取
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        // 1. 子节点  childNodes 所有的子节点 包含 元素节点 文本节点等等
        console.log(ul.childNodes);
        console.log(ul.childNodes[0].nodeType);
        console.log(ul.childNodes[1].nodeType);
        // 2. children 获取所有的子元素节点 也是我们实际开发常用的
        console.log(ul.children);
    </script>
</body>
5.3.1 第一个子结点                        回到顶部
parentNode.firstChild 或 parentNode.firstElementChild

前面的:(parentNode.firstChild)
1、返回第一个子节点,找不到则返回null
2、包含所有的节点
后面的:(parentNode.firstElementChild)
1、同上
2、有兼容性问题,IE9以上才支持

5.3.2 最后一个子节点
parentNode.lastChild  或 parentNode.lastElementChild

前面的:
1、返回第一个子节点,找不到则返回null
2、同样,也是包含所有的节点
后面的:
1、同上
2、有兼容性问题,IE9以上才支持

5.3.3 实际开发使用

第一个子元素节点:parentNode.chilren[0]
最后一个子元素节点:
(children为伪数组,里面存的是子元素的数量)parentNode.chilren[parentNode.chilren.length - 1]
例子:

<body>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
        <li>我是li5</li>
    </ol>
    <script>
        var ol = document.querySelector('ol');
        // 1. firstChild 第一个子节点 不管是文本节点还是元素节点
        console.log(ol.firstChild);
        console.log(ol.lastChild);
        // 2. firstElementChild 返回第一个子元素节点 ie9以上才支持
        console.log(ol.firstElementChild);
        console.log(ol.lastElementChild);
        // 3. 实际开发的写法  既没有兼容性问题又返回第一个子元素
        console.log(ol.children[0]); //利用伪数组
        console.log(ol.children[ol.children.length - 1]); //最后一个子元素
    </script>
</body>
5.4 兄弟节点

5.4.1下一个兄弟节点

node.nextSibling 或node.nextElementSibling 
  • 返回当前元素的下一个兄弟节点,找不到则返回null
  • 包含所有的节点
  • 后者: 有兼容性问题,只返回兄弟元素节点

5.4.2 上一个兄弟节点

node.previousSibling 或node.previousElementSibling
  • 返回当前元素上一个兄弟元素节点,找不到则返回null
  • 包含所有的节点
  • 后者: 有兼容性问题,只返回兄弟元素节点

列子:

<body>
    <div>我是div</div>
    <span>我是span</span>
    <script>
        var div = document.querySelector('div');
        // 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
        console.log(div.nextSibling);
        console.log(div.previousSibling);
        // 2. nextElementSibling 得到下一个兄弟元素节点
        console.log(div.nextElementSibling);
        console.log(div.previousElementSibling);
    </script>
</body>

解决兼容性问题:自己封装一个兼容性的函数

function getNextElementSibling(element) {
	 var el = element;
	 while (el = el.nextSibling) {
 		if (el.nodeType === 1) {
			 return el;
		 }
	 }
	 return null;
 }
5.5 创建节点                        回到顶部
document.createElement('tagName');
  • 方法创建由 tagName 指定的HTML 元素
  • 因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
5.5.1 添加节点
node.appendChild(child)
  • 该方法将一个节点添加到指定父节点的子节点列表的末尾。类似于 CSS 里面的 after 伪元素。(子节点列表的最后面)
node.insertBefore(child,指定元素)
  • 该方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。(子节点列表的最前面)

创建和添加元素示例:

<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        // 1. 创建节点元素节点
        var li = document.createElement('li');


        // 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素  类似于数组中的push
        var ul = document.querySelector('ul');
        ul.appendChild(li);
        // 3. 添加节点 node.insertBefore(child, 指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
        // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
    </script>
</body>
5.5.2 删除节点
node.removeChild(child)
  • 该方法从 DOM 中删除一个子节点,返回删除的节点
5.5.3 克隆节点                        回到顶部
node.cloneNode()
  1. 返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
  2. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
  3. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点
<body>
    <ul>
        <li>1111</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
        // 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
        var lili = ul.children[0].cloneNode(true);
        ul.appendChild(lili);
    </script>
</body>

在这里插入图片描述
-------在这里插入图片描述

5.5.4 三种动态创建元素的区别
  • doucument.write()
  • element.innerHTML()
  • document.createElement()
    区别:

doucument.write()直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘

element.innerHTML()将内容写入某个 DOM 节点,不会导致页面全部重绘
element.innerHTML()创建多个元素效率更高不要拼接字符串,采取数组形式拼接),结构稍微复杂

document.createElement()创建多个元素效率稍一点点,但是结构更清晰

<script>
        // window.onload = function() {
        //         document.write('<div>123</div>');

        //     }
        // 1. innerHTML 创建元素
        var inner = document.querySelector('.inner');
         for (var i = 0; i <= 100; i++) {
             inner.innerHTML += '<a href="#">百度</a>'
         }     //创建100个a标签,创造多个元素时,效率高



        var arr = [];
        for (var i = 0; i <= 100; i++) {
            arr.push('<a href="#">百度</a>');
        }  //效率不同,效率最高(不拼接字符串)
        inner.innerHTML = arr.join('');
        // 2. document.createElement() 创建元素 //慢些
        var create = document.querySelector('.create');
        for (var i = 0; i <= 100; i++) {
            var a = document.createElement('a');
            create.appendChild(a);
        }
    </script>

总结:
不同浏览器下, innerHTML 效率要比 createElement 高

6、DOM核心            回到顶部

对于DOM操作,我们主要是操作子元素
创建,增,删,改,查,属性操作,时间操作。

6.1创建
  1. document.write
  2. innerHTML
  3. createElement
6.2 增
  • appendChild
  • insertBefore
6.3 删
  • removeChild
6.4 改

主要修改dom的元素属性,dom元素的内容、属性、表单的值等
1、 修改元素属性:src、href、title 等
2、 修改普通元素内容:innerHTML、innerText
3、 修改表单元素:value、type、disabled
4、 修改元素样式:style、className

6.5 查
  • DOM提供的API方法:getElementById、 getElementsByTagName (古老用法,不推荐)
  • H5提供的新方法:querySelector、querySelectorAll (提倡)
  • 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
6.5 属性操作
  • 主要针对于自定义属性
  1. setAttribute:设置dom的属性值
  2. getAttribute:得到dom的属性值
  3. removeAttribute:移除属性

7、事件高级           回到顶部

7.1 注册事件(绑定事件)

给元素添加事件,称为注册事件或者绑定事件
注册事件有两种方式:传统方式和方法监听注册方式

传统注册方式方法监听注册方式
利用 on 开头的事件 onclickw3c 标准推荐方式
<button onclick = “alert(“hi”)”>addEventListener() 它是一个方法
btn.onclick = function() {}IE9 之前的 IE 不支持此方法,可使用 attachEvent() 代替
特点:注册事件的唯一性特点:同一个元素同一个事件可以注册多个监听器
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数按注册顺序依次执行
7.1.1 addEventListener事件监听方式(重点)

eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上。

当该对象触发指定的事件时,就会执行事件处理函数

eventTarget.addEventListener(type,listener[,useCapture])

三个参数:  查看常见的鼠标事件

  • type:事件类型字符串,比如click,mouseover,注意这里不要带on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
<body>
    <button>传统注册事件</button>
    <button>方法监听注册事件</button>
    <button>ie9 attachEvent</button>
    <script>
        var btns = document.querySelectorAll('button');
        // 1. 传统方式注册事件
        btns[0].onclick = function() {
            alert('hi');
        }
        btns[0].onclick = function() {
                alert('hao a u');
            } //只弹出hao a u
            // 2. 事件侦听注册事件 addEventListener 
            // (1) 里面的事件类型是字符串 必定加引号 而且不带on
            // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
        btns[1].addEventListener('click', function() {
            alert(22);
        })
        btns[1].addEventListener('click', function() {
                alert(33); //先弹出22后弹出33
            })
            // 3. attachEvent ie9以前的版本支持
        btns[2].attachEvent('onclick', function() {
            alert(11);
        })
    </script>
</body>
7.1.2 addEvent 事件监听方式(兼容ie8及以前)

eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上

当该对象触发指定的事件时,就会执行事件处理函数

 eventTarget.attachEvent(eventNameWithOn, callback)

两个参数:

  • eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
  • callback: 事件处理函数,当目标触发事件时回调函数被调用
7.1.3 注册事件兼容性解决方案

兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器

 function addEventListener(element, eventName, fn) {
      // 判断当前浏览器是否支持 addEventListener 方法
      if (element.addEventListener) {
        element.addEventListener(eventName, fn);  // 第三个参数 默认是false
      } else if (element.attachEvent) {
        element.attachEvent('on' + eventName, fn);
      } else {
        // 相当于 element.onclick = fn;
        element['on' + eventName] = fn;
 } 


7.2 删除事件(解绑事件)            回到顶部
7.2.1 removeEventListener删除事件方式
eventTarget.removeEventListener(type,listener[,useCapture]);

三个参数:

  • type:事件类型字符串,比如click,mouseover,注意这里不要带on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
7.2.2 detachEvent删除事件方式(兼容)
eventTarget.detachEvent(eventNameWithOn,callback);

两个参数:

  • eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
  • callback:事件处理函数,当目标触发事件时回调函数被调用
  • ie9以前的版本支持
    7.2.3 传统事件删除方式
eventTarget.onclick = null;

示例:

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
                alert(11);
                // 1. 传统方式删除事件
                divs[0].onclick = null;
            }
            // 2. removeEventListener 删除事件
        divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号

        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }
        // 3. detachEvent
        divs[2].attachEvent('onclick', fn1);

        function fn1() {
            alert(33);
            divs[2].detachEvent('onclick', fn1);
        }
    </script>
</body>

7.2.4 删除事件兼容性解决方案

function removeEventListener(element, eventName, fn) {
 // 判断当前浏览器是否支持 removeEventListener 方法
 if (element.removeEventListener) {
 element.removeEventListener(eventName, fn); // 第三个参数 默认是false
 } else if (element.detachEvent) {
 element.detachEvent('on' + eventName, fn);
 } else {
 element['on' + eventName] = null;
 }
7.3 DOM事件流
  1. 事件流描述的是从页面中接收事件的顺序
  2. 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程DOM事件流请添加图片描述
  • 事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
  • 事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
    形象比喻:
    我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
    请添加图片描述
7.3.1 捕获阶段

document -> html -> body -> father -> son
先来看个例子:
两个盒子嵌套,一个父盒子一个子盒子,我们的需求是当点击父盒子时弹出 father ,当点击子盒子时弹出 son
请添加图片描述

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        // dom 事件流 三个阶段
        // 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
        // 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
        // 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段  document -> html -> body -> father -> son
         var son = document.querySelector('.son');
         son.addEventListener('click', function() {
             alert('son');
         }, true);
         var father = document.querySelector('.father');
         father.addEventListener('click', function() {
             alert('father');
         }, true);

捕获阶段:以上代码的结果:点击子元素,先弹出“father”,关掉后,再弹出“son”。(最开始检查document是否监听,一次向下检查,由于DOM流的影响)
请添加图片描述
请添加图片描述
这是因为捕获阶段由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收

  • document -> html -> body -> father -> son
  • 先看 document 的事件,没有;再看 html 的事件,没有;再看 body 的事件,没有;再看 father 的事件,有就先执行;再看 son 的事件,再执行。
7.3.2 冒泡阶段
  • son -> father ->body -> html -> document
    同理:冒泡则是反过来的,先检查son是否有监听器后依次向上检查。

addEventListener 第三个参数是 false 或 省略,则处于冒泡阶段。第三个参数为true则为捕获阶段

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
		// 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段  son -> father ->body -> html -> document
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, false);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>

我们点击子盒子,会依次弹出 son、father、document的提示框。

这是因为冒泡阶段开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点

  • son -> father ->body -> html -> document

总结:

  • JS 代码中只能执行捕获或者冒泡其中的一个阶段
  • onclickattachEvent只能得到冒泡阶段
  • addEventListener(type,listener[,useCapture])
第三个参数阶段
true捕获阶段
false 或 不写冒泡阶段
  • 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
  • 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
7.4 事件对象            回到顶部
eventTarget.onclick = function(event) {} 
 eventTarget.addEventListener('click', function(event) {}// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt 

-.①.-官方解释:
event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。

-.②.-简单理解:
事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象
event,它有很多属性和方法:

  • 谁绑定了这个事件
  • 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
  • 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键

+.③.+这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
+.④.+当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)

<body>
    <div>123</div>
    <script>
        // 事件对象
        var div = document.querySelector('div');
        div.onclick = function(e) {
                // console.log(e);
                // console.log(window.event);
                // e = e || window.event;
                console.log(e);


            }
            // div.addEventListener('click', function(e) {
            //         console.log(e);

        //     })
        // 1. event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
        // 2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
        // 3. 事件对象 是 我们事件的一系列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了那个键
        // 4. 这个事件对象我们可以自己命名 比如 event 、 evt、 e
        // 5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法  e = e || window.event;
    </script>
</body>
7.4.1 兼容性方案

事件对象本身的获取存在兼容问题:

  1. 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
  2. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找
解决兼容性问题的代码:
e = e || window.event;
7.4.2 事件对象的常见属性和方法
事件对象属性方法说明
e.target返回触发事件的对象 标准
e.srcElement返回触发事件的对象 非标准 ie6-8使用
e.type返回事件的类型 比如click mouseover 不带on
e.cancelBubble该属性阻止冒泡,非标准,ie6-8使用
e.returnValue该属性阻止默认行为 非标准,ie6-8使用
e.preventDefault()该方法阻止默认行为 标准 比如不让链接跳转
e.stopPropagation()阻止冒泡 标准

e.target 和 this 的区别:

  • this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
  • e.target 是事件触发的元素。
<body>
    <div>123</div>
    <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
      
        // 1. e.target 返回的是触发事件的对象(元素)  this 返回的是绑定事件的对象(元素)
        // 区别 : e.target 点击了那个元素,就返回那个元素 this 那个元素绑定了这个点击事件,那么就返回谁
        var div = document.querySelector('div');
        div.addEventListener('click', function(e) {
            console.log(e.target); //<div>123</div>
            console.log(this);//<div>123</div>

        })
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
                // 我们给ul 绑定了事件  那么this 就指向ul  
                console.log(this);  //<ul>...</ul>
                console.log(e.currentTarget);//<li>abc</li>

                // e.target 指向我们点击的那个对象 谁触发了这个事件 我们点击的是li e.target 指向的就是li
                console.log(e.target);

            })
</script>
</body>
7.5 事件对象阻止默认行为

利用:

  • e.preventDefault()标准写法
  • returnValue 非标准写法:低版本浏览器 ie678 returnValue 属性

示例:

<body>
    <div>123</div>
    <a href="http://www.baidu.com">百度</a>
    <form action="http://www.baidu.com">
        <input type="submit" value="提交" name="sub">
    </form>
    <script>
        // 常见事件对象的属性和方法
        // 1. 返回事件类型
        var div = document.querySelector('div');
        div.addEventListener('click', fn);
        div.addEventListener('mouseover', fn);
        div.addEventListener('mouseout', fn);

        function fn(e) {
            console.log(e.type);

        }
        // 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom 标准写法
            })
            // 3. 传统的注册方式
        a.onclick = function(e) {
            // 普通浏览器 e.preventDefault();  方法
            // e.preventDefault();
            // 低版本浏览器 ie678  returnValue  属性
            // e.returnValue;
            // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
            return false;
            alert(11);
        }
    </script>
</body>

7.6 阻止事件冒泡
  • 标准写法
e.stopPropagation();
  • 非标准写法: IE6-8 利用对象事件 cancelBubble属性
e.cancelBubble = true;

代码示例:

<body>
    <div class="father">
        <div class="son">son儿子</div>
    </div>
    <script>
        // 常见事件对象的属性和方法
        // 阻止冒泡  dom 推荐的标准 stopPropagation() 
        var son = document.querySelector('.son');
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation(); // stop 停止  Propagation 传播
            e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
        }, false);

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>
7.7 事件委托
  1. 事件委托也称为事件代理,在 jQuery 里面称为事件委派
  2. 目的:提高执行代码效率
  3. 事件委托的原理
  • 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
<body>
    <ul>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
        <li>知否知否,点我应有弹框在手!</li>
    </ul>
    <script>
        // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // alert('知否知否,点我应有弹框在手!');
            // e.target 这个可以得到我们点击的对象
            e.target.style.backgroundColor = 'pink';
            // 点了谁,就让谁的style里面的backgroundColor颜色变为pink
        })
    </script>
</body>

以上案例:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上, ul 有注册事件,就会触发事件监听器。

7.8 常见的鼠标事件            回到顶部
鼠标事件触发条件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发
7.8.1 禁止鼠标右键与鼠标选中
  • contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
  • selectstart 禁止鼠标选中
<body>
    <h1>我是一段不愿意分享的文字</h1>
    <script>
        // 1. contextmenu 我们可以禁用右键菜单
        document.addEventListener('contextmenu', function(e) {
                e.preventDefault(); // 阻止默认行为
            })
            // 2. 禁止选中文字 selectstart
        document.addEventListener('selectstart', function(e) {
            e.preventDefault();

        })
    </script>
</body>

7.8.2 鼠标事件对象
  • event对象代表事件的状态,跟事件相关的一系列信息的集合
  • 现阶段我们主要是用鼠标事件对象 MouseEvent 和键盘事件对象 KeyboardEvent。
鼠标事件对象说明
e.clientX返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX(重点)返回鼠标相对于文档页面的X坐标 IE9+ 支持
e.pageY(重点)返回鼠标相对于文档页面的Y坐标 IE9+ 支持
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的Y坐标

相对于可视窗:
请添加图片描述
相对于文档页面:
请添加图片描述

<body>
    <script>
        // 鼠标事件对象 MouseEvent
        document.addEventListener('click', function(e) {
            // 1. client 鼠标在可视区的x和y坐标
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------------------');

            // 2. page 鼠标在页面文档的x和y坐标,相对于其他,更重要
            console.log(e.pageX);
            console.log(e.pageY);
            console.log('---------------------');

            // 3. screen 鼠标在电脑屏幕的x和y坐标
            console.log(e.screenX);
            console.log(e.screenY);

        })
    </script>
</body>
7.9 常见的键盘事件
键盘事件触发条件
onkeyup某个键盘按键被松开时触发
onkeydown某个键盘按键被按下时触发
onkeypress某个键盘按键被按下时触发,但是它不识别功能键,比如 ctrl shift 箭头等
  • 如果使用addEventListener 不需要加 on
  • onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift 等
  • 三个事件的执行顺序是: keydown –》 keypress —》 keyup
<body>
    <script>
        // 常用的键盘事件
        //1. keyup 按键弹起的时候触发 
        // document.onkeyup = function() {
        //         console.log('我弹起了');

        //     }
        document.addEventListener('keyup', function() {
            console.log('我弹起了');
        })

        //3. keypress 按键按下的时候触发  不能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keypress', function() {
                console.log('我按下了press');
            })
            //2. keydown 按键按下的时候触发  能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keydown', function() {
                console.log('我按下了down');
            })
            // 4. 三个事件的执行顺序  keydown -- keypress -- keyup
    </script>
</body>

键盘对象属性
键盘事件对象 属性说明
keyCode返回该键值的ASCII值
  • onkeydownonkeyup不区分字母大小写,onkeypress区分字母大小写。
  • 在我们实际开发中,我们更多的使用keydown和keyup, 它能识别所有的键(包括功能键)
  • Keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
<body>
    <script>
        // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
        // 1. 我们的keyup 和keydown事件不区分字母大小写  a 和 A 得到的都是65
        // 2. 我们的keypress 事件 区分字母大小写  a  97 和 A 得到的是65
        document.addEventListener('keyup', function(e) {
            console.log('up:' + e.keyCode);
            // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
            if (e.keyCode === 65) {
                alert('您按下的a键');
            } else {
                alert('您没有按下a键')
            }

        })
        document.addEventListener('keypress', function(e) {
            console.log('press:' + e.keyCode);
        })
    </script>
</body>

六、BOM                  回到顶部

1.BOM概述

  • BOM(Browser Object Model)即浏览器对象模型
  • 它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window
  • BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
  • BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。
DOMBOM
文档对象模型浏览器对象模型
DOM 就是把 文档 当作一个对象来看待浏览器当作一个对象来看待
DOM 的顶级对象是 documentBOM 的顶级对象是 window
DOM 主要学习的是操作页面元素BOM 学习的是浏览器窗口交互的一些对象
DOM 是 W3C 标准规范BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
1.1BOM的构成

请添加图片描述

  • window 对象是浏览器的顶级对象,它具有双重角色

1、 它是 JS 访问浏览器窗口的一个接口
2、它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。
在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert
注意:window下的一个特殊属性 window.name

<body>
    <script>
        // window.document.querySelector()
        var num = 10;
        console.log(num); //结果一样。全局变量会变成window对象的属性
        console.log(window.num);//10
----------------------------------------------------------
        function fn() { //全局方法也会变成window对象的方法
            console.log(11);
        }//11
   
        console.dir(window);
        // var name = 10;  name为window下的特殊属性,不能自己命名一个
        console.log(window.name);
    </script>
</body>

2.window 对象的常见事件          回到顶部

2.1 窗口加载事件

window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,CSS文件等),就调用的处理函数。

window.onload = function(){   //传统注册方式一
};
// 或者,使用监听器(用得最多),方式二
window.addEventListener("load",function(){});

一些注意点:

  • 有了window.onload就可以把JS代码写到页面元素的上方
  • window.onload 传统注册事件方式,只能写一次
  • 如果有多个,会以最后一个window.onload为准
  • 如果使用addEventListener(监听器) 则没有限制

方式三:

document.addEventListener('DOMContentLoaded',function(){})

两个参数:

  • DOMCountentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等
  • 使用场景:如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间
  • 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded事件比较合适。
2.1.1两种方法的区别
  • load等页面内容全部加载完毕,包括页面dom元素,图片,flash,css等
  • DOMContentLoaded是DOM加载完毕,不包含图片 flash css 等就可以执行,加载速度比load更快一些
<script>
        // window.onload = function() {
        //     var btn = document.querySelector('button');
        //     btn.addEventListener('click', function() {
        //         alert('点击我');
        //     })
        // }
        // window.onload = function() {
        //     alert(22);
        // }
        window.addEventListener('load', function() {
            var btn = document.querySelector('button');
            btn.addEventListener('click', function() {
                alert('点击我');
            })
        })
        window.addEventListener('load', function() {

            alert(22);
        })
        document.addEventListener('DOMContentLoaded', function() {
                alert(33);
            })
            // load 等页面内容全部加载完毕,包含页面dom元素 图片 flash  css 等等
            // DOMContentLoaded 是DOM 加载完毕,不包含图片 falsh css 等就可以执行 加载速度比 load更快一些
    </script>
<body>

    <button>点击</button>

</body>
2.2调整窗口大小事件

window.onresize 是调整窗口大小加载事件,当触发时就调用的处理函数

window.onresize = function() {}  //传统方式

// 或者 监听器
window.addEventListener('resize',function(){});

  • 只要窗口大小像素发生变化,就会触发这个事件
  • 我们经常利用这个事件完成响应式布局。
  • window.innerWidth当前屏幕的宽度
  • window.innerheight当前屏幕的高度
<body>
    <script> //在body里,即要等页面加载完毕。再执行
        window.addEventListener('load', function() {
            var div = document.querySelector('div');
            window.addEventListener('resize', function() {
                console.log(window.innerWidth);
                console.log('变化了'); //当屏幕像素宽度小于800像素,则该盒子(div)隐藏。
                if (window.innerWidth <= 800) {
                    div.style.display = 'none';
                } else {
                    div.style.display = 'block';
                }  

            })
        })
    </script>
    <div></div>
</body>

3.定时器            回到顶部

window 对象给我们提供了两个定时器

第一种:
setTimeout()
第二种:
setInterval()
3.1 setTimeout()定时器

setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。

window.setTimeout(调用函数,[延迟的毫秒数]);

一些注意点:

  • window可以省略
  • 调用函数:
    - 可以直接写函数
    - 可以写函数名
    - 可以采取字符串 ‘函数名()’ (不推荐)
  • 延迟的毫秒数省略默认是0,如果写,必须是毫秒
  • 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
  • setTimeout()这个调用函数我们也称为回调函数 callback
  • 普通函数是按照代码顺序直接调用,而这个函数,需要等待事件,事件到了才会去调用这个函数,因此称为回调函数。
<body>
    <script>
        // 1. setTimeout 
        // 语法规范:  window.setTimeout(调用函数, 延时时间);
        // 1. 这个window在调用的时候可以省略
        // 2. 这个延时时间单位是毫秒 但是可以省略,如果省略默认的是0
        // 3. 这个调用函数可以直接写函数 还可以写 函数名 还有一个写法 '函数名()'
        // 4. 页面中可能有很多的定时器,我们经常给定时器加标识符 (名字)
        // setTimeout(function() {
        //     console.log('时间到了');

        // }, 2000);
        function callback() {
            console.log('爆炸了');

        }
        var timer1 = setTimeout(callback, 3000);
        var timer2 = setTimeout(callback, 5000);
        // setTimeout('callback()', 3000); // 我们不提倡这个写法
    </script>
</body>
3.2 clearTimeout()停止定时器            回到顶部
  • clearTimeout()方法取消了定时器 ( 先前通过调用setTimeout()建立的定时器)
window.clearTimeout(timeoutID)

注意:

  1. window可以省略
  2. 里面的参数就是定时器的标识符
<body>
    <button>点击停止定时器</button>
    <script>
        var btn = document.querySelector('button');
        var timer = setTimeout(function() {
            console.log('爆炸了');
        }, 5000);
        btn.addEventListener('click', function() {
            clearTimeout(timer);
        })
    </script>
</body>
3.3 setInterval()定时器
  • setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
window.setInterval(回调函数,[间隔的毫秒数]);
  • window可以省略

  • 这个回调函数:

    • 可以直接写函数
    • 或者写函数名
    • 或者采取字符 ‘函数名()’
  • 第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次

<body>
    <script>
        // 1. setInterval 
        // 语法规范:  window.setInterval(调用函数, 延时时间);
        setInterval(function() {
            console.log('继续输出');

        }, 1000);
        // 2. setTimeout  延时时间到了,就去调用这个回调函数,只调用一次 就结束了这个定时器
        // 3. setInterval  每隔这个延时时间,就去调用这个回调函数,会调用很多次,重复调用这个函数
    </script>
</body>
3.4 clearInterval()停止定时器

clearInterval()取消定时器(由setInterval()建立的定时器)
注意:

  • window可以省略
  • 里面的参数就是定时器的标识符
<body>
    <button class="begin">开启定时器</button>
    <button class="stop">停止定时器</button>
    <script>
        var begin = document.querySelector('.begin');
        var stop = document.querySelector('.stop');
        var timer = null; // 全局变量  null是一个空对象
        begin.addEventListener('click', function() {
            timer = setInterval(function() {
                console.log('ni hao ma');

            }, 1000);
        })
        stop.addEventListener('click', function() {
            clearInterval(timer);
        })
    </script>
</body>
3.5 this指向
  • this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁
    现阶段,我们先了解一下几个this指向
    重点
  • 全局作用域或者普通函数this指向全局对象window(注意定时器里面的this指向window)—|---(window.fn window.setTimeout等等,window省略)
  • 方法调用中谁调用this指向谁
  • 构造函数中this指向构造函数实例,对象里的this指向自己
<body>
    <button>点击</button>
    <script>
        // this 指向问题 一般情况下this的最终指向的是那个调用它的对象

        // 1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
        console.log(this);

        function fn() {
            console.log(this);

        }
        window.fn();
        window.setTimeout(function() {
            console.log(this);

        }, 1000);
        // 2. 方法调用中谁调用this指向谁
        var o = {
            sayHi: function() {
                console.log(this); // this指向的是 o 这个对象

            }
        }
        o.sayHi();
        var btn = document.querySelector('button');
        // btn.onclick = function() {
        //     console.log(this); // this指向的是btn这个按钮对象

        // }
        btn.addEventListener('click', function() {
                console.log(this); // this指向的是btn这个按钮对象

            })
            // 3. 构造函数中this指向构造函数的实例
        function Fun() {
            console.log(this); // this 指向的是fun 实例对象

        }
        var fun = new Fun();
    </script>
</body>

4.JS执行机制            回到顶部

4.1 JS是单线程
  • JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
  • 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
4.2 同步和异步
  • 为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程

  • 于是,JS 中出现了同步和异步。

  • 同步:
    - 前一个任务结束后再执行后一个任务

  • 异步:
    - 在做这件事的同时,你还可以同时去处理其他事情

  • 同步任务:
    - 同步任务都在主线程上执行,形成一个 执行栈

  • 异步任务:

  • JS中的异步是通过回调函数实现的

  • 异步任务有以下三种类型
    - 普通事件,如click,resize
    - 资源加载,如load,error
    - 定时器,包括setInterval,setTimeout等(这些定时器为同步任务,定时器里的回调函数是异步任务)

  • 异步任务相关回调函数添加到任务队列中请添加图片描述
    执行顺序:
    1、 执行 执行栈 中的同步任务
    2、异步任务(回调函数)放入任务队列
    3、一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行

请添加图片描述
例子1:

console.log(1);
setTimeout(function() {
    console.log(3);
},1000);
console.log(2); //结果为:1、2、3

例子2:

console.log(1);
setTimeout(function() {
    console.log(3);
},0);
console.log(2); //结果为:1、2、3

例子3:

console.log(1);
document.onclick = function() {   //若未点击,则为1、2、3(3为等3秒后出现)
    console.log('click');
}
console.log(2);						//若点击,且在三秒后点击,结果为1、2、3、click(点一						                       
setTimeout(function() {    			//下一个就有click)
    console.log(3)			
}, 3000)							//若在3秒内点击,结果为1、2、click(可有多个,多点几
									//下)、3、(click)(后面可以继续点击)			 

事件循环:由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)
请添加图片描述

5.location对象            回到顶部

  • window 对象给我们提供了一个 location属性用于获取或者设置窗体的url,并且可以解析url。因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。
5.1 url

统一资源定位符(uniform resouce locator)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

url 的一般语法格式为:

protocol://host[:port]/path/[?query]#fragment

http://www.itcast.cn/index.html?name=andy&age=18#link
组成说明
protocol通信协议 常用的http,ftp,maito等
host主机(域名) www.itheima.com
port端口号,可选
path路径 由零或多个’/'符号隔开的字符串
query参数 以键值对的形式,通过&符号分隔开来
fragment片段 #后面内容 常见于链接 锚点
5.2 location对象属性
location对象属性返回值
location.host返回主机(域名)www.baidu.com
location.href获取或者设置整个URL
location.port返回端口号,如果未写返回空字符串
location.pathname返回路径
location.search返回参数
location.hash返回片段 #后面内容常见于链接 锚点

href 和 search
例子1(5秒后跳转页面):

<body>
    <button>点击</button>
    <div></div>
    <script>
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        var timer = 5;
        setInterval(function() {
            if (timer == 0) {
                location.href = 'http://www.itcast.cn';
            } else {
                div.innerHTML = '您将在' + timer + '秒钟之后跳转到首页';
                timer--;
            }

        }, 1000);
    </script>
</body>

5.3 location对象方法
location对象方法返回值
location.assign()跟href一样,可以跳转页面(也称为重定向页面)
location.replace()替换当前页面,因为不记录历史,所以不能后退页面
location.reload()重新加载页面,相当于刷新按钮或者 f5 ,如果参数为true 强制刷新 ctrl+f5
<body>
    <button>点击</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            // 记录浏览历史,所以可以实现后退功能
            // location.assign('http://www.itcast.cn');
            // 不记录浏览历史,所以不可以实现后退功能
            // location.replace('http://www.itcast.cn');
            location.reload(true);
        })
    </script>
</body>

5.4 获取URL参数

我们写一个网页,有登录框的,点击登录跳转到 index.html

<body>
    <form action="index.html">
        用户名: <input type="text" name="uname">
        <input type="submit" value="登录">
    </form>
</body>

再写index.html

<body>
    <div></div>
    <script>
        console.log(location.search); // ?uname=andy
        // 1.先去掉?  substr('起始的位置',截取几个字符);
        var params = location.search.substr(1); // uname=andy
        console.log(params);
        // 2. 利用=把字符串分割为数组 split('=');
        var arr = params.split('=');
        console.log(arr); // ["uname", "ANDY"]
        var div = document.querySelector('div');
        // 3.把数据写入div中
        div.innerHTML = arr[1] + '欢迎您';
    </script>
</body>
这样就能获得URL参数了

6、navigator对象            回到顶部

  • navigator 对象包含有关浏览器的信息,它有很多属性
  • 我们常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

下面前端代码可以判断用户是用哪个终端打开页面的,如果是用 PC 打开的,我们就跳转到 PC 端的页面,如果是用手机打开的,就跳转到手机端页面

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    window.location.href = "XXXXX.html";     //手机
 } else {
    window.location.href = "xxx/XXXX.html";     //电脑
 }

7、history对象            回到顶部

  • window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互
  • 该对象包含用户(在浏览器窗口中)访问过的 URL。
history对象方法作用
back()可以后退功能
forward()前进功能
go(参数)前进后退功能,参数如果是 1 前进1个页面 如果是 -1 后退1个页面
<body>
    <a href="list.html">点击我去往列表页</a>
    <button>前进</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            // history.forward();
            history.go(1);
        })
    </script>
</body>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值