JavaScript笔记

JavaScript

JavaScript介绍

页面组成

  • HTML:超文本标记语言 结构层
  • css:层叠样式表 样式层;表现层
  • JavaScript:交互脚本 行为层

什么是JavaScript?基于对象和事件驱动的解释性脚本语言

  • 基于对象和事件驱动的解释性脚本语言
  • 基于对象:JavaScript是一种基于对象的语言,这意味着它能运用自己已经创建的对象,因此,许多功能可以来自脚本环境中对象的方法与脚本的互相作用。
  • 事件驱动:JavaScript可以直接对用户或者客户输入作出响应,无须经过web服务器,它对用户的响应,以事件驱动的方式进行。
  • 解释性
    • 编译性:机器语言,计算机无法直接识别,先进行编译,在执行(c,c++)
    • 解释性:直接识别的代码,解释一行执行一行(浏览器可以直接识别js,直接执行
  • 跨平台:JavaScript依赖于浏览器本身,与操作环境无关,只需要能运行支持JavaScript的浏览器的计算机
  • JavaScript的特征:基于对象,事件驱动,解释性,跨平台

JavaScript发展历史

  • 1995 网景(Netscape) 发布了商用浏览器
  • 解决问题:表单提交
  • 要求:新开发一门语言 尽可能跟Java像,比java简单
  • 布兰登.艾奇 10天 LiveScript----->JavaScript
  • 微软:同年 发布IE3.0 搭载一个克隆版的JScript
  • ECMA:欧洲计算机制造商协会
  • ECMAScript1.0 ECMAScript5.1 ECMAScript6.0---- ES6
  • 网景(Netscape) —>火狐

JavaScript组成

  • ECMAScript:指定了语法规则,常用对象
  • DOM:Document Object Model:文档对象模型
  • BOM:Browser Object Model:浏览器对象模型

JavaScript初识

引入方式

行间引入
<!-- 第一种:行间引入
    onclick : 点击事件
    alert('提示信息')
    问题:结构不分离,后期不方便维护
-->
<button onclick="alert('没吃,饿了!!!')">吃饭吗?</button>
内部引入(内嵌)
<!-- 第二种:内部引入 
    js代码写入到script标签中,script标签可以写任意多个可以放在任意位置,代码从上往下执行
    一般放在head或body的末尾,建议放在body的末尾
    问题:结构不分离
-->
<script>
    alert("弹弹弹,弹走鱼尾纹4");
</script>
外部引入(外链)
<!-- 第三种:外链引入.js 
    通过script标签的src属性引入外部js文件
    注意:用于引入外部js文件的script标签,就不要再写其他的js代码,不会执行
-->
<script src='./outer.js'>
    // alert("对,你说的对!!!");
</script>

<script>
    alert("对,你说的对!!!");
</script>

语法规则
  • 每行语句后加;
  • js中严格区分大小写,使用驼峰标识(大驼峰 FontSize ;小驼峰 fontSize)

JavaScript的调试语句

调试:程序在开发过程中检测,检查代码的功能,数据的一种方式

alert()
  • 语法:alert(message)
  • 作用:在页面弹出警告框,提示信息
//1.alert(message):在页面弹出提示框,一次只能弹一个,阻塞型
var a = 10;
var b = 10;
var c = 10 * 10;
alert(a);
alert("马上就可以吃饭了?");
alert("今天不吃饭了",b);
console.log()
  • 语法:console.log(message)
  • 作用:在控制台打印信息,多个输出之间用逗号隔开
//- 语法:console.log(message) 作用:在控制台打印信息,多个输出之间用逗号隔开
console.log(a,b);
console.log("今天星期三");
document.write()
  • 语法:document.write(message) 数值、文字、标签
  • 作用:在页面写入内容
//3.- 语法:document.write(message)-- 数值-- 文字---标签   - 作用:在页面写入内容
document.write("今天周三,上三天课就可以休息");
document.write(a);
document.write("<h1>我们还是要自习</h1>");
断点
打开控制台---->sources -----> 打开html/js文件 ---->点击行号 ---->刷新

数据类型与变量

变量

变量:可以改变的量,用于存储数据的容器

  • 语法:var 变量名 = 值
  • 变量的命名规则
1.变量名只能以数字、字母、下划线、$组成  不能使用数字开头
2.不能使用关键字和保留字
3.见名知意,遵循驼峰标识
4.不要重名,会覆盖
A. Var a = 10;
B. var a%1 = 10;
C. var 0A = 20; 
D. var $a_01 = 200;  对的
//1.声明变量:var 变量名 = 值
var a;
console.log(a);  //undefined:未定义,变量声明了,没有赋值,结果就是undefined

a = 10;  //=赋值运算符  等号右边的值,赋给左边的变量
console.log(a); //10


//2.声明的同时赋值
var b = 3;
console.log(b); //3

//3.同时声明多个变量
var x = 10,y = 2,z=1;
console.log(x,y,z);  //10 2 1

//4.连等
m = n = 1;
console.log(n,m);

//5.特殊的使用  (不建议使用)
s = 10;
console.log(s); //10 不声明直接使用,不加默认是全局变量

console.log(t); //没有声明,没有赋值  报错   t is not defined

JavaScript的数据类型

  • 数据类型:JavaScript根据数据的特征将数据分为不同的类型,每一种数据类型都有自己的功能
  • 数据类型的分类:六大数据类型 number,string,boolean,努力力,undefined,复杂类型(对象类型,引用类型)
  • 五大基本数据
    • number
    • string
    • boolean
    • null
    • undefined
  • 复杂数据类型
  • function
  • array
  • object
typeof
  • 语法:typeof(要检测的数据)/ typeof 要检测的数据
  • 作用:检测数据的数据类型,并返回
//1.typeof(数据) : 返回数据的数据类型
var a = 10;
var t = typeof(a);
console.log(a,t); //10 "number"

//2.第二种用法 typeof 数据
var t1 = typeof a;
console.log(t1);  //"number"

var t2 = typeof 3.14;
console.log(t2); //"number"
number

数值类型,包含小数、整数、十六进制、八进制、NaN、infinity

//1.1 整数,小数,
var n1 = 10;
var n2 = 3.14;
console.log(typeof(n1),typeof n2); //"number"  "number"
  • 进制
//1.2 八进制,以0开头,并且没有超过8的值,表示8进制   0-7 
var n3 = 057;
console.log(typeof n3,n3); //"number"  55(默认输出的是10进制)

//1.3 十六进制 以0x开头,0-9 a-f 
var n4 = 0x22;
console.log(typeof n4,n4); //number  34
  • 特殊
//1.4 精度缺失 不要用小数做判断
console.log(0.1 + 0.2) ; //0.30000000000000004

//1.5 NaN : not a number (掌握)
var n5 = NaN; //自己定义的
var n6 = "哈哈哈"*3; //运算出错的结果
console.log(n6,typeof n6); //NaN  "number"
console.log(NaN == NaN); //false


var n7 = 10/0;
console.log(n7,typeof n7); //Infinity "number"
string

字符串类型 引号引起来的 “” / “”

  • 基本语法
 //字符串类型 引号引起来的  “”  ‘’
var s1 = "web";
var s2 = '0824';
console.log(typeof(s1),typeof s2); //string string
  • 方法
var tel = "23112345678";
//1. 字符串.length : 返回字符串的长度
var l = tel.length;
console.log(l); //1

//2.字符串.charAt(下标):下标从0开始
var s = tel.charAt(0);
console.log(s); //2  下标从0开始 
console.log(tel[0]); //2 tel[下标]  []不兼容ie7
  • 特殊
//3. +号遇到字符串会变成连接符
console.log(10+"10"); //1010   
console.log(10+18+"age"+10+20); //代码做从左往右运算,两两运算  "28age1020"
boolean

布尔值 true,false

  • 作用:作为结果判断
//1.boolean:布尔   true  false
var b1 = true;
var b2 = false;
console.log(typeof b1,b1); //boolean true

//作为判断结果
console.log(10 > 20); //false
if(false){
    alert("今天没有作业");
}
null与undefined
//1.boolean:布尔   true  false
var b1 = true;
var b2 = false;
console.log(typeof b1,b1); //boolean true

//作为判断结果
console.log(10 > 20); //false
if(false){
    alert("今天没有作业");
}
  • null与undefined的区别
    • null空对象,有存储空间没有值,访问一个不存在的对象返回的结果
    • undefined未定义,空变量,没有存储空间,声明变量但是没有赋值的结果

数据类型转换

  • 强制转换:通过方法,将数据必须转换成某种类型,转换不了NaN
  • 隐式转换:运算过程中,数据自动进行的类型转换
数据类型的强制转换-number
  • Number()
    • 可以转换boolean(1、0),null(0),字符串(纯数值字符串、空字符串)
var n1 = 10;
var s1 = "101";
var b1 = true;
var n1 = null;
var u1 = undefined;

//1.  Number(要转换的数据):返回一个新的转换好的数据,原数据不受影响
//字符串转number:纯数字、空字符
var s2 = Number(s1);
console.log(s2, s1); //101 "101"
console.log(Number("a1"));  //NaN  转不了
console.log(Number("1a"));  //NaN  转不了
console.log(Number("")); //0 空字符

//布尔转number:1 0
console.log(Number(b1)); //1   true--1  false---0
console.log(Number(false)); //0   

//null转换number
console.log(Number(n1)); //0

//undefined转number
console.log(Number(u1)); //NaN
  • parseInt()
    • 语法:parseInt(要转换的数据)
    • 作用:从左往右开始转换,遇到不能转换的或者是数据的结尾就结束,一开始不能转换就是NaN,取整,舍小数
  • parseFloat()
    • 语法:parseFloat(要转换的数据)
    • 作用:从左往右开始转换,遇到不能转换的或者是数据的结尾就结束,一开始不能转换就是NaN,保留小数
//2.parseInt(要转换的数据):从左往右开始转换,遇到不能转换的或者是数据的结尾就结束,一开始不能转换就是NaN,取整,舍弃小数
//3.parseFloat(要转换的数据):从左往右开始转换,遇到不能转换的或者是数据的结尾就结束,一开始不能转换就是NaN,保留小数
var price = "51.949元5";
console.log(parseInt(price)); //51
console.log(parseFloat(price));//51.99

console.log(parseInt("$19.9")); //NaN
console.log(parseFloat("$19.9"));//NaN
数据类型的强制转换-string
  • String()
    使用String()函数做强制类型转换时
    对于Number和Boolean实际上就是调用toString()方法
    但是对于null和undefined,就不会调用toString()方法
    它会将null 直接转换为“null”
    将undefined 直接转换为“undefined”
var n1 = 10;
var s1 = "101";
var b1 = true;
var n2 = null;
var u1 = undefined;

//1.String(要转换的数据): 就是在数据的外面加“”
console.log(1,String(n1));  //"10"	
console.log(1,String(s1));  //"101"
console.log(1,String(b1));  //"true"
console.log(1,String(n2));  //"null"
console.log(1,String(u1));  //"undefined"
  • xx.toString
    • null 和 undefined没有toString方法
//2.xx.toString():将xx转换成字符串  的
var nn1 = n1.toString();
console.log(1,nn1); //"10"
console.log(1,s1.toString());
console.log(1,b1.toString());
//console.log(n2.toString()); //报错  Cannot read property 'toString' of null  null上面没有任何东西
console.log(u1.toString()); //Cannot read property 'toString' of undefined
转boolean
  • 语法:Bolean(要转换的数据)
  • 作用:将数据类型转换为boolean
  • 类型:
    • number: 非0为真
    • string: 非空为真
    • null false null—0,0为false
    • undefined false
方法
  • isNaN()
/* 
   isNaN: is not a number : 是不是不是数字  是数字:false   不是数字:true
*/
var b1 = isNaN(10)
console.log(b1); //false
console.log(isNaN("haha")); //true

//isNaN在判断之前,会先使用Number()对数据进行类型转换,判断的时候转换后的
console.log(isNaN(true)); //false   Number(true)==>1   isNaN(1) 
  • toFixed()
//xx.toFixed(num):将xx保留n位小数,四舍五入
var price = 19.449999999999;
var p = price.toFixed(2);
console.log(1,p); //"19.45"

运算符与表达式

运算符和表达式的概念

  • 运算符:连接一个或以上的操作数的中间的符号就叫运算符
  • 表达式:由操作符合运算符组成的式子就叫表达式
  • 运算符分类
    • 运算符分类:算数运算符、赋值运算符、逻辑运算符、比较运算符、三目运算符
    • 表达式分类:算数表达式、赋值表达式、逻辑表达式、比较表达式、三目表达式

算数运算符

  • 类型:+ - * / % ++ –
//算术运算符分类:+ - * /  %(取余,求模) ++ --
console.log(10 + 4);  //14
console.log(10 - 4);  //6
console.log(10 * 4);  //40
console.log(10 / 4);  //2.5   在js中取完整
console.log(10 % 4);  //2
  • 特殊
//1. % 的作用  n的倍数
var n = 9;
console.log(n % 2 == 0); //偶数

//2.精度缺失:运算过程中,小数运算可能会出现偏差 不要用小数做判断
console.log(0.1 + 0.2); //0.30000000000000004
console.log(0.1 * 0.7); //0.06999999999999999
console.log((0.1 * 0.7).toFixed(2)); //0.07
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
//3.隐式转换:在运算过程中,数据自动进行的数据类型转换
//隐式转换的规律:都会转换为number进行运算,+号遇到字符串就会变成连接符
console.log(100 * false);  //0   false--->0
console.log("100" - 10); //90 number    "100"--->  100
console.log(10+null); //10  null --->0
console.log("10" + 10); //"1010"  10 --> "10"

赋值运算符

  • 赋值运算符: = += -= *= /= %=
//赋值运算符:  =   +=  -=  *=  /=  %=
var a = 10 + 10;  //将等号右边的值赋值给左边的变量

//+=
a += 2; //累加  等价于  a = a + 2;
console.log(a); //22

a -= 10;  //a = a - 10
console.log(a); //12

比较运算符

  • 比较运算符: > < <= >= == != ===(全等,恒等) !== ASCII:“0” – 48 , “A”–65 “a”–97
//比较运算符: >   <   <=    >=  ==   !=  \=\==(全等,恒等)  !==
console.log(30 > 20); //true, 比较运算符的结果:true  false

//1.两个字符串比较,一位一位比较,而且比较的是字符编码   "0" -- 48 , "A"--65   "a"--97
console.log("10000" < "2"); //true
console.log("a" > "A"); //97 > 65  true

//2. == ===的区别?(笔试题)
console.log(10 == "10"); //true : 比较运算符再进行运算的时候,也会进行隐式转换,尽量转换为number
console.log(10 === "10"); //false 不会进行隐式转换,必须一模一样才相等

//3. null在判断相等的时候,不会进行隐式转换,null和自己和undefined相等,其他都不相等
console.log(null >= 0); //true
console.log(null <= 0); //true
console.log(null == 0); //false
console.log(null == null); //true
console.log(null == undefined); //true

逻辑运算符

  • 逻辑运算符:&& || !
  • 基础用法
 //逻辑运算符:&&  ||  !
var s = 55;
//代码中运算,是两两运算的,数学中的习惯可能无法得到正确结果
console.log(60 > s > 40); //false
//两个两个写,使用&&  || 进行连接

//1. && 连接两个或两个以上的条件,条件都为真结果才为真
console.log(60 > s && s > 40);  //true


//2. || 连接两个或两个以上的条件,只要有一个条件为真结果就为真
//考试成绩< 10      >100分  打一顿
console.log(s<10 || s>100);   //false


//3. 取反 (结果只会是true,false
console.log(!1); //false
console.log(!null); //true
  • 短路运算
// 与(&&)短路
//&&:两真为真,如果第一个条件为假,		第二个条件不执行
var a1 = 1;
var b1 = 1;
var c1 = --a1 && --b1;	//计算右边的结果,执行到哪,就将那部分的值赋值给前面的变量
console.log(a1,b1,c1);	//0 1 0

//&&:如果第一个条件为真,			再执行第二个条件
var a2 = 10;
var b2 = 2;
var c2 = --a2 && --b2;
console.log(a2,b2,c2);	//9 1 1


// 或(||)短路
//||:一真为真:如果第一个条件为假,		再执行第二个条件
var x1 = 1;
var y1 = 10;
var z1 = --x1 || --y1; 
console.log(x1,y1,z1);	//0 9 9

//||:一真为真:如果第一个条件为真,		第二个条件不执行
var x2 = 10;
var y2 = 10;
var z2 = --x2 || --y2;
console.log(x2,y2,z2);	//9 10 9

三目运算符

  • 作用:用于判断(低配版条件判断)
  • 语法:条件?条件执行的代码(不能加分号,只能写一句语句):条件不成立执行的代码
  • 练习
//输入年份,判断是否闰年  还是 平年
//闰年:能被4整除但是不能被100整除,或者能被400整除的就是闰年
var year = prompt("请输入年份");
(year%4==0 && year%100!=0) || year % 400 == 0 ?alert("是闰年"):alert("不是闰年")

DOM获取标签

  • id获取

    • 语法:document.getElementById(“id名”)

      //1.通过id名获取:document.getElementById("id名");
      var oLi = document.getElementById("login");
      console.log(oLi);
      
      //添加事件:标签.onclick = function(){ 事件发生要执行的代码 }
      oLi.onclick = function () {
          alert("登录成功");
      }
      
  • 标签名获取

    • 语法1:document.getElementsByTagName(“标签名”) 整个文档中对应名字的标签

    • 语法2:父元素.getElementsByTagName(“标签名”) 父元素对应名字的标签

      //2.通过标签名获取
      //2.1 document.getElementsByTagName("标签名") : 在整个文档中获取对应名字的标签
      var oLis = document.getElementsByTagName("li");
      console.log(oLis); //HTMLCollection(5)  元素集合 ,不能整体操作,必须一个一个获取到具体标签再操作
      console.log(oLis.length); //获取长度 5
      console.log(oLis[1]);//通过下标,获取到具体的标签  标签[下标],下标从0开始
      
      oLis.onclick = function () {
          alert("你猜我弹吗?")
      }
      
      //2.2 父元素.getElementsByTagName("标签名") : 在父元素中获取对应名字的标签
      var oUl = document.getElementsByTagName("ul")[1]; //获取父元素
      var uLis = oUl.getElementsByTagName("li");
      console.log(uLis);
      
  • 通过类名获取(IE8不兼容)

    • 语法1:document.getElementsByClassName(“标签名”) 整个文档中对应类名的标签

    • 语法2:父元素.getElementsByClassName(“标签名”) 父元素对应类名的标签

       //3.通过类名获取元素
      var oBoxs = oUl.getElementsByClassName("box");
      console.log(oBoxs);
      

常用鼠标事件

  • 添加事件:标签.事件名=function(){ 事件发生时要执行的代码 }

  • 常用鼠标事件

onclick:点击事件、单击事件
onmouseover:鼠标移入	/onmouseenter 子元素不会触发父元素
onmouseout:鼠标移出		/onmouseleave 子元素不会触发父元素
onmousedown:鼠标按下
onmouseup:鼠标抬起
onmousemove:鼠标移动

操作标签

width height background border
<div id='box' class='box' > 标签内容 </div>

操作标签内容

  • 标签内容:闭合标签和表单元素都有内容

    <div>  <span> 我是一个span </span> </div>  : 开始标签到结束标签中间的都是内容
    <input value='2323'>
    
1) 操作表单元素内容
  • 获取表单元素内容: var 变量 = 表单元素.value

  • 设置表单元素内容:表单元素.value = 值

    //1.获取元素
    var oIn = document.getElementsByTagName("input")[0];
    var oBtns = document.getElementsByTagName("button");
    
    //2.点击获取的按钮
    oBtns[1].onclick = function(){
        var v = oIn.value;
        console.log(v);
    }
    
    //3.点击设置按钮  设置表单元素内容:表单元素.value = 值
    oBtns[0].onclick = function(){
        oIn.value = "123456";
    }
    
2) 操作闭合标签内容
  • 获取闭合标签内容:var 变量 = 标签.innerHTML/innerText

  • 设置闭合标签内容:标签.innerHTML/innerText= 值

  • 特性:

    • 后面会覆盖原有的内容
    • innerHTML能识别标签,innerText不能识别标签
    /*
    获取:var 变量 = 标签.innerHTML/innerText
    设置:标签.innerHTML/innerText = 值
    特性:
    	会覆盖之前的
    	innerHTML:识别标签  innerText:操作文本
     */      
    //1.获取元素
    var oDiv = document.getElementsByTagName("div")[0];
    
    //2.获取闭合标签内容  var 变量 = 标签.innerHTML/innerText
    var html = oDiv.innerHTML;
    console.log(html);  // <p>先帝...</p>  能识别标签
    
    var text = oDiv.innerText;
    console.log(text); //先帝...    操作文本内容
    
    
    
    //3.设置闭合标签内容:标签.innerHTML/innerText = 值  :会覆盖原有的内容
    //3.1 不想覆盖 = 之前的 + 现在的
    //oDiv.innerHTML = oDiv.innerHTML +  '<p>然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。</p>';
    
    
    //3.2 += : 追加,累加,现有的基础上+
    //oDiv.innerHTML+='<p>然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也</p>';
    oDiv.innerText+='<p>然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。</p>';
    

操作标签属性

  • 标签属性

    <div id='box' class="box" title='fd' ></div>
    <img src ='地址'>
    
  • 语法:

    • 获取标签属性:var 变量 = 标签.属性名

    • 设置标签属性:标签.属性名 = 值

    • 特殊:class —> 标签.className

      //1.获取元素
      var oDiv = document.getElementsByTagName("div")[0];
      
      //2.获取属性:var 变量 = 标签.属性名
      var t = oDiv.title;
      console.log(t);
      
      //2.设置属性:标签.属性名 = "属性值"
      oDiv.id = "box";
      
      
      //3.把class名改成active
      oDiv.className = "active";
      

操作标签样式

  • 标签样式

    <style>
    div{
        width: height...
    }
    <style>
    
  • 语法

    • 获取标签样式:var 变量 = 标签.style.属性名(了解)

    • 设置标签样式:标签.style.属性名 = “属性值”

    • 特殊:js中不允许出现-符,需要使用驼峰标识 font-size ----> fontSize

      //2.设置标签样式  : js都是操作的行间样式
      oDiv.style.width = "200px";
      oDiv.style.height = "200px";
      oDiv.style.border = "2px solid red";
      
      //js中不允许出现-符,需要使用驼峰标识 font-size ----> fontSize
      oDiv.style.fontSize = "24px";
      oDiv.style.backgroundColor = "teal";
      
  • cssText

    <div style="background:red">下课,吃饭!!</div>
       
    //cssText:重新行间的style属性
    oDiv.style.cssText = "width:200px;height:200px;";
    执行后:<div style="width:200px;height:200px;">下课,吃饭!!</div>
    
    oDiv.style.width = "200px";
    oDiv.style.height = "200px";
    执行后:<div style="background:red;width:200px;height:200px;">下课,吃饭!!</div>
    
    

流程控制语句

流程控制语句分类

  • 顺序结构(代码从上往下执行)
  • 选择结构(分支语句):if if-else if else-if switch
  • 循环结构:for while do-while for-in

选择结构(分支语句)

单分支if
  • 语法:if(条件){ 条件成立执行的代码 }
//1.如果是10月1,八达岭长城
var date = "101";
if(date == "101"){
    console.log("去八达岭");
}
  • 注意

    • 可以省略if后面的大括号,如果该省略了,if只能控制紧跟在后面的一条语句
    • if()条件并不一定要写判断,只要能判断真假就可以
    //2.可以省略if后面的大括号,如果省略了,if只能控制紧跟在后面的一条语句
    //假设有钱, 辞职环游世界, 造坦克
    var money = 100;
    if(money >= 1000000) 
        console.log("辞职环游世界");
    console.log("造坦克");		//会打印造坦克
    
    
    //3.if()条件并不一定要写判断,只要能判断真假就可以
    if(null){		//null false  不会执行打印
        console.log("条件并不一定要写判断,只要能判断真假就可以");
    }
    
多分支 if-else if/switch
  • if-else if

    • 语法:if(条件){ 条件成立时执行的代码 }else if(条件){ 条件成立时执行的代码 }else if…
    /* 
    3.多分支
       语法:if(条件){条件成立时执行的代码}else if(条件){条件成立时执行的代码}else if.....
       90以上:优秀  80以上:良好  70:还行  60:及格   60以下:继续努力
       遵循规则:从最不容易实现的开始判断
            */
    var c = 87;
    if(c >= 90){
        console.log("优秀");
    }else if(c >= 80){
        console.log("良好");
    }else if(c >= 70){
        console.log("还行");
    }else if(c >= 60){
        console.log("及格");
    }else{
        console.log("继续努力");
    }
    
  • switch

    • 语法:
    switch(匹配){
        case1 : 匹配到值1以后执行的代码;break
        case2 : 匹配到值2以后执行的代码;break
        case3 : 匹配到值3以后执行的代码;break
        default:前面的都没有匹配到执行的代码
    }
    注意:值要求必须是一个具体的不变的值
    ***break防止穿透,如果没有break,匹配到值以后后面的代码就不会再判断,会立刻执行***
    条件是一些简单的固定的符号或数字,会选择使用switch
    

循环结构

for循环
  • for循环

什么时候需要用?:多次重复执行,多次有规律重复执行

for的作用?:可以让特定的代码执行指定次数

  • 语法:
for(表达式1;表达式2;表达式3{  循环体(需要重复执行的代码) }
for(初始化循环变量;循环条件;更新循环变量){ 循环体(需要重复执行的代码)}
forvar i=0;i<10;i+{ 循环体(需要重复执行的代码)}
  • 列子
forvar i=0;i<5;i++{
    console.log(i)}
执行过程:
	1.初始化循环变量  i=0;
	2.判断循环条件  i<5;
    	成立 执行3;不成立循环结束
    3.执行循环体
    4.更新循环变量  i++5.回到步骤2
    注意:一定要有结束条件,否则就会变成死循环
  • 使用场景

    • 循环数组,逻辑
    var arr = ["A","B","C","D"];
    
    console.log(arr[0]);
    console.log(arr[1]);
    console.log(arr[2]);
    console.log(arr[3]);
    
    for(var i = 0;i < arr.length;i++){
        console.log(arr[i]);  //arr[0]  arr[1]
    }
    
    • 循环绑定事件
    10li == >oLis
    
    oLis[0].onclick = function(){}
    oLis[1].onclick = function(){}
    oLis[2].onclick = function(){}
    oLis[3].onclick = function(){}
    oLis[4].onclick = function(){}
    
    for(var i = 0;i<oLis.length;i++){
        oLis[i].onclick = function(){}
    }
    
    • 循环生成标签
    //这种,经常改变内容的标签,在html中就不写,在js中通过获取后台数据动态生成
    var news = ["国庆节不放假","哈尔滨疫情","福建疫情","国庆节高铁不开了","国庆节飞机不飞了"];
    
    var oUl = document.getElementsByTagName("ul")[0];
    
    //根据后台数据生成标签
    for(var i = 0;i<news.length;i++){
        oUl.innerHTML += "<li>hahaha</li>";
    }
    
while与do-while
  • while

    • 语法:

      ​ 初始化循环变量(不是必须)

      ​ while(循环条件){

      ​ 循环体

      ​ 更新循环变量

      ​ }

      //while
      var j=0;
      while(j>1){
          console.log(j);
          j++;
      }
      
  • do-while

    • 语法

      ​ 初始化循环变量(不是必须)

      ​ do{

      ​ 循环体

      ​ 更新循环变量

      ​ }while( 循环条件 )

      //do-while 
      var t=0;
      do{
          console.log(t);
          t++;
      }while(t>1);
      
循环的选择
  • while与do-while的区别

    do-while先执行后判断,至少执行一次
    while:先判断后执行
    
  • for与while的区别

break与continue
  • break:结束循环
  • continue:结束本次循环
//break:结束循环
for(var i = 1;i<=10;i++){
    if(i == 5){
        console.log("碗里有蟑螂");
        break;
    }
    console.log("现在在吃第"+i+"个饺子");
}

//continue:结束本次循环(跳出本次循环)
for(var i = 1;i<=10;i++){
    if(i == 5){
        console.log("掉地上了");
        continue;
    }
    console.log("现在在吃第"+i+"个饺子");
}
双重for循环
  • 循环嵌套
var movie=[
    ["峰暴", "血战虎门", "我和我的父辈", "末日", "灵媒"],
    ["扫黑风暴", "周生如故", "乔家的儿女", "你是我的荣耀", "庆余年", "赘婿2"],
    ["柯南", "一人之下", "海贼王", "海绵宝宝", "蜡笔小新"]
]
//1.获取标签
var oUls = document.getElementsByTagName("ul");
//2.双重for循环
for (var j=0;j<movie.length;j++){
    for (var i=0;i<movie[j].lenght;i++){
        oUls[j].innerHTML+="<li>"+movie[j][i]+"</li>";
    }
}
for-in循环
  • 语法
for(var 变量 in 循环对象){
    循环体
}
  • 案列
var obj = {
    "name":"web",
    "age":18,
    "height":180,
    "sex":"女
     
}
for(var key in obj){	//for会自动将对象的数据从头到尾循环一次,一组一组循环,每次循环都会将key的值存储在前面定义的变量中
    console.log(key);	//name,age,height,sex
    console.log(obj[key]);	//"web",18,180,"女"
}

函数

概念

  • 函数function:函数就是将具有独立功能的代码块,整合到一起并命名,需要的时候调用即可(保存一段代码块,在需要的时候调用)

  • 作用:调高代码复用率

    right.onclick = function(){ 换图片,换文字}   {change}
    left.onclick = function(){ 换图片,换文字}    {change}
    圆点.onclick = function(){ 换图片,换文字}      {change}
    
    
    function change(){
        换图片,换文字
    }
    
  • 使用场景

    • 事件处理函数

      //1.作为事件处理函数
      document.body.onclick=function(){
          console.log("作为事件处理函数")}
      
    • 代码复用 函数封装

      //2.代码复用  函数封装
      /*
      right.onclick = function(){ 换图片,换文字}   {change}
      left.onclick = function(){ 换图片,换文字}    {change}
      圆点.onclick = function(){ 换图片,换文字}      {change}
      
      
      function change(){
          换图片,换文字
      }
      */
      
    • 对象的方法

      //3.作为对象的方法
      var obj ={
          //属性
          "name":"web",
          //方法
          "skill":function(){
              console.log("敲代码,杀猪")}
      }
      

函数的声明及使用

  • 普通声明

    • 语法

      声明:function 函数名(){  代码块  }
      调用:函数名();
      
    • 使用

      //1.声明函数:存储代码块  (没有调用是不会执行的)
      function homework(){
          console.log("现在开始做作业。。。。。");
          console.log("中间自闭一会,奔溃一会,开心一会");
          console.log("作业做完了");
      }
      
      //2.调用(多次重复使用)
      homework();
      homework();
      homework();
      
  • 表达式声明

    • 语法

      声明:var 变量名 = function (){  代码块  }
      调用:变量名;
      
    • 使用

      //3.表达式声明方式
      var eat = function(){
          console.log("吃饭--睡觉");
      }
      eat();
      eat();
      

函数参数

  • 什么时候需要使用函数参数:函数中出现不能确定的值的时候,传递不同参数,实现不同功能

  • 参数

    • 形参(形式参数):function 函数名(a){ a——》var a

    • 实参(实际参数):函数名(10)10——实参 实参会将值赋值给形参

      //声明一个函数,计算6!(阶乘)  6!= 6*5*4*3*2*1
      function jc(n) { //var n  形参
          var s = 1;
          for (var i = 1; i <= n; i++) {
              s *= i;
          }
          console.log(s);
      }
      //调用
      jc(6); //720   n = 6
      jc(7); //5040  n = 7
      
  • 多个参数:多个参数之间用逗号隔开

    //声明一个函数,计算n-m的和  1-100 2=200  3-300
    function sum(n,m){
        var s = 0;
        for(var i = n;i<=m;i++){
            s += i;
        }
        console.log(s);
    }
    sum(1,100); //一一对应赋值  n=1,m=100
    sum(2,10); //一一对应赋值  n=1,m=100
    
  • 参数个数不确定:不写形参,使用arguments(实参集合)

    //声明一个函数,计算所有参数的和
    function add(){
        console.log(arguments); //实参集合
        console.log(arguments.length); //实参集合的个数
        console.log(arguments[0]); //集合是通过下标获取元素
    }
    add(1,2);
    add(1,2,3,4,5);
    add(10,100,1000);
    
  • 参数类型

    所有的js数据类型都能作为函数的参数,null和undefined不会作为参数,没有意义

  • 函数问题(面试题)

    //1.重名会覆盖,后面会覆盖前面的 (函数跟变量重名照样会覆盖)
    function sum(){
        console.log("我是函数1");
    }
    function sum(){
        console.log("我是函数2");
    }
    var sum = 0;  
    console.log(sum);  //0
    // sum();   sum is not a function
    
    
    //2.重名覆盖
    function add(a,b){
        console.log(a+b);
    }
    function add(a,b){
        console.log("a+b="+(a+b));
    }
    //var a=10,b=undefined, 实参比形参少,一一对应,没有被赋值就是undefined
    add(10);  //a+b=NaN
    
    //var a = 10,b = 20   实参比形参多,多了不管
    add(10,20,30); //a+b=30
    
    
    
    //3.arguments是实参集合,形参指其中一个实参,一改全改
    function fun(a){
        a = 100;
        console.log(arguments[0]); //100
    
        arguments[0] = 200;
        console.log(a);  //200
    }
    fun(10,20);
    

函数封装

  • 封装:将具有独立功能的代码块,存储在函数中,需要的时候调用
获取非行间样式
  • 获取行间样式

    • var 变量=标签.style.属性名

       //2.获取元素的宽: 标签.style.样式名 操作的是行间样式,无法获取非行间样式
      var w = oDiv.style.width;
      console.log(w); //100px
      
      • 注意:只能获取行间样式
  • 获取非行间样式

    • 标准浏览器:window.getComputedStyle(标签).属性名 window可以省略 IE8不兼容

    • IE浏览器:标签.currentStyle.属性名 标准浏览器

      //3.1 标准浏览器:window.getComputedStyle(标签).属性名      window可以省
      var w1 = getComputedStyle(oDiv).width;
      console.log(w1); //ie不兼容
      
      //3.2 IE浏览器:标签.currentStyle.属性名
      var w1 = oDiv.currentStyle.width;
      console.log(w1); //标准浏览器不兼容
      
  • 兼容

    • 兼容思路

      • 如果要兼容的是方法(有括号),兼容需要使用判断

      • 判断条件(其中一个,但格式必须是xx.xx)

        //使用标准浏览器的语法作为判断条件
        alert(window.getComputedStyle); //标准--function     ie--undefined
        if(window.getComputedStyle){
            var w1 = getComputedStyle(oDiv).width;
        }else{
            var w1 = oDiv.currentStyle.width;
        }
        console.log(w1);
        
        
        
        //使用ie浏览器的语法作为判断条件
        if(oDiv.currentStyle){ //.后面接变量
            var w2 = oDiv.currentStyle.width;
        }else{
            var w2 = getComputedStyle(oDiv).width;
        }
        console.log(w2);
        

#### 封装函数

  • 封装步骤

    • 先实现功能

    • 声明函数,将代码放入函数中

    • 找函数中可变的值做参数,代入到函数中

    • 调用调试

      function getStyle(elemObj,attr) {//元素:elemObj  attr:属性
          if (elemObj.currentStyle) {
              var w = elemObj.currentStyle[attr];
          } else {
              var w = getComputedStyle(elemObj)[attr];
          }
          return w;
          // return elemObj.currentStyle ? elemObj.currentStyle[attr] : getComputedStyle(elemObj)[attr]
      }
      

代码复用

  • 代码复用:结构一致,功能一样,循环比较麻烦的时候,使用代码复用
  • 操作步骤:
    • 当它只有一组趋势线,元素必须通过父元素获取(各自的父元素)
    • 声明一个函数,将实现功能的所有代码放入到函数中,将父元素作为参数传递
    • 调用

是作用域与预解析

作用域

  • 作用域:变量或函数的有效使用范围

  • 作用域种类:全局作用域、局部作用域

    • 全局作用域

      //1.全局作用域:函数外声明的变量/函数,叫全局变量/函数,可以在页面的任何地方和修改,会一直存储在内存汇总,直到页面关闭
      var a = 10;
      function fun1(){
          console.log(a); //10
          a = 100;
      }
      fun1();
      console.log(a); //100
      
    • 局部作用域

      //2.局部作用域:函数内声明的变量/函数,叫局部变量/函数,只能在函数内部使用,出了函数括号就会被销毁
      function fun2(){
          var c = 10; //局部变量
          console.log(c); //10
      }
      fun2();
      console.log(c); //c is not defined
      
      //3.全局,只有函数内声明的才是局部变量
      if(true){
          var b = "A";
      }
      console.log(b); //"A"
      
  • 作用域链

    js的查找机制,先找自己作用域本身,如果自己作用域没有,依次往复机作用域查找,一直找到全局,仍然找不到报错,is not defined (类比css继承性)

预解析

  • 预解析(变量提升):浏览器在解析js的时候,其中至少有两步

    • 一:预解析(变量提升)
      • 找var,声明这个变量(只是声明,只看等号左边的部分),如果重名,只声明一次
      • 找function,声明整个函数,如果重复会多次声明
    • 二:逐行执行
  • 预解析:找var

    //1.找var,声明这个变量(只是声明,只看等号右边的部分),如果重名,只声明一次
    console.log(a);  //undefined
    var a =10;
    console.log(a);  //10
    
  • 预解析:找function

    //2.找function,声明整个函数,如果重复会多次声明
    console.log(fun1);//ƒ fun1() {//注释2  console.log("函数2");}
    function fun1() {
        //注释1
        console.log("函数1");
    }
    function fun1() {
        //注释2
        console.log("函数2");
    }
    console.log(fun1);
    
  • 预解析:函数内部代码执行也会进行预解析

    //函数内部在执行代码的时候,也会进行预解析
    function fun1(){
        console.log(a); //undefined
        var a = 10;
        console.log(a); //10
    }
    fun1();
    
  • 面试题

    //面试题1:普通函数与表达式函数的区别
    fun2(); //提前调用  预解析  fun2 = function(){console.log("普通函数");}
    function fun2(){
        console.log("普通函数");
    }
    //fun3(); //不能提前调用,预解析  fun3=undefined
    var fun3 = function(){
        console.log("表达式函数");
    }
    
    //面试题2:代码执行后的结果是?
    console.log(c); //函数2
    var c = 10;
    function c(){
        console.log("函数1");
    }
    console.log(c); //10 
    var c = 20;
    function c(){
        console.log("函数2");
    }
    console.log(c); //20
    var c = 30;
    console.log(c); //30
    c(); //is not a function 
    
    //面试题3:预解析+作用域链
    var b = "A";
    function fun2(){
        console.log(b); //undefined
        var b = "AA";
        console.log(b); //"AA"
    }
    fun2();
    
    //面试题4
    var x = 10;
    var y = 10;
    function fun3(){
        console.log(x,y); //undefined  10
        var x = 10;
    }
    fun3();
    
    //面试题5
    var m = 10;
    var n = 10;
    function fun4(){
        console.log(m,n);//undefined 10 
        var m = n = 40; //var m = 10  n = 40
    }
    fun4();
    console.log(n);
    
    //面试题6
    function fun(s){//var s = 100
        console.log(s);  //100
        var s = 10}
    fun(100);
    
    //面试题7
            function test(a, b) {//var a=1; var b;
                console.log(a);     //1
                console.log(b);     //undefined
    
                var b = 234;
                console.log(b);     //234
    
                a = 123;
                console.log(a);     //123
                var a;
                
                b = 234;
                var b = function () { };
                console.log(a);     //123
                console.log(b);     //函数b
            }
            test(1)
    

函数返回值

  • 函数返回值:return

  • 作用:将函数内部的内容输出到函数外部,并且结束函数执行

  • 语法:return 要返回的内容

  • 代码

     function sum(){
         var s = 0; //局部变量,出了函数就会被销毁
         for(var i = 1;i<=100;i++){
             s += i;
         }
         //s = 5050
         return s; //将函数内部的数据返回到函数外部使用
     }
    var su = sum(); //su接受函数调用后返回的结果
    console.log(su); //5050
    
  • 特性

    • 一次只能返回一个值

      function add(a,b){
          var c = a + b;
          var d = a * b;
          // return c,d;  //一次只能返回一个,写多个返回的是最后一个的值
          return {"sum":c,"cheng":d}; //如果要返回多个数据,可以存储在对象中返回
      }
      var a = add(10,20);
      console.log(a); //{sum: 30, cheng: 200}
      
    • 函数只要遇到return,函数就会结束,一般return都会在函数的末尾

      function fun3(){
          var s = 0; //局部变量,出了函数就会被销毁
          for(var i = 1;i<=100;i++){
              s += i;
              return s; //函数中只要遇到return,函数就会结束
          }
      }
      var sss = fun3();
      console.log(sss);
      

this

为什么需要使用this

//2.循环添加点击事件
for(var i = 0;i<oBtns.length;i++){ 
    //循环给标签绑定事件,在给标签绑定事件的时候,事件不会立刻触发执行
    //循环绑定i = 5,条件不成立,循环结束
    oBtns[i].onclick = function(){
        console.log(i); //5  事件触发时打印i,这个i此时是循环结束后的i = 5
        // console.log(oBtns[i]);
    }
}

this概念

  • this:这个

  • 解释this

    概念:一般在函数中使用,在不同的环境的值不一样,取决于当前函数被调用时所处的环境,谁调用的函数,this就指向谁
    1.在普通函数中this————》window
    2.在事件处理函数中this————》触发事件的对象
    3.在对象的方法中this————》当前对象
    
    • 在普通函数中(所有的全局都属于window)

      //所有的全局都属于window
      var a = 10;
      console.log(window.a);  //一般会省略window
      
      //1. 普通函数中的this指window
      function sum() {
          console.log(this); //window
      }
      sum();
      
    • 在事件处理函数中(事件处理函数的this指触发事件的对象(点谁this就是谁))

      //所有的全局都属于window
      var a = 10;
      console.log(window.a);  //一般会省略window
      
      //1. 普通函数中的this指window
      function sum() {
          console.log(this); //window
      }
      sum();
      
    • 在对象的方法中(对象的方法中this指当前对象)

      //3.对象的方法中this---->当前对象
      var obj = {
          "name":"web",
          "skill":function(){
              console.log(this); //obj
          }
      }
      obj.skill();
      

this在循环事件中使用

//1.获取元素
var oBtns = document.getElementsByTagName("button");

//2.循环添加点击事件
for(var i = 0;i<oBtns.length;i++){ 
    oBtns[i].onclick = function(){
        //3.点击打印对应标签的内容
        console.log(this.innerText);
    }
}

自定义属性

开关示例(为什么要使用自定义属性)

单组开关
  • 现象:一个事件里面两种现象,一个标签两种状态

  • 实现步骤

    • 定义一个变量,用于标识当前的状态

    • 通过判断变量的状态,选择执行的操作

    • 当状态发生变化,变量的值需要做对应的改变

      //自己创造一个判断条件
      var tag = true; //true:关   false:开
      
      //2.点击图片
      oImg.onclick = function () {
          //4.判断状态,判断,但是又没有合适的判断条件,就直接创造条件
          console.log(oImg.src); // 获取的是绝对路径,不建议绝对路径做判断条件      file:///E:/txf/%E5%8C%97%E4%BA%AC0824%E7%AC%AC%E4%BA%8C%E9%98%B6%E6%AE%B5/day05_this%E4%B8%8E%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7/code/images/dark.jpg
          
          if (tag == true) {
              //3.切换图片 关---->开
              oImg.src = "./images/bright.jpg";
              tag = false; //状态改变,tag的值需要保持同步
          } else {
              //3.切换图片 开---->关
              oImg.src = "./images/dark.jpg";
              tag = true;//状态改变,tag的值需要保持同步
          }
          //可以使用三目简化
      }
      
多组开关
  • 现象:多组开关

    //1.获取元素
    var oDiv = document.getElementsByTagName("div");
    
    var tag = true; 
    
    //2.循环添加点击事件
    for(var i = 0;i<oDiv.length;i++){
        oDiv[i].onclick = function(){
            if(tag){
                this.style.height = "100px";
                tag = false;
            }else{
                this.style.height = "40px";
                tag = true;
            }
        }
    }
    问题:共用了一个tag,点击的时候,就混乱了
    解决:给每个标签都添加一个属于自己的tag
    

自定义属性

#### 定义属性

  • 属性的分类

    • 固有属性:系统给的 id class title
    • 自定义属性:程序员自己定义的 tag index
  • 添加自定义属性

    • 直接添加标签上(暂时获取不到)

      <div tag = "true"></div>
      //2.自定义属性直接写行间,可以直观看见,暂时无法获取写在行间的自定义属性
      console.log(oDiv.tag); //undefined
      
    • 使用js添加:标签.属性名=属性值

      //3.通过js添加自定义属性,标签上看不见,但是可以直接使用
      oDiv.a = true;
      console.log(oDiv.a); //true
      

#### 自定义属性使用场景

  • 多组开关效果(自定义属性)

    //2.循环添加点击事件 
    for(var i = 0;i<oLis.length;i++){ 
        oLis[i].tag = true; //给所有标签都添加一个属于自己的标记,默认关 
        oLis[i].onclick = function(){ 
            if(this.tag == true){ //如果是true[关] 
                this.style.height = "100px"; //设置为开的状态 
                this.tag = false; //对应的标记需要保持同步 
            }else{
                this.style.height = "40px"; 
                this.tag = true; 
            } 
        }
    }
    
  • 选项卡(自定义索引)

    //1.获取元素 
    var oDivs = document.getElementsByTagName("div"); 
    var oBtns = document.getElementsByTagName("button"); 
    //2.循环添加点击事件 点击对应的按钮,显示对应的模块 
    for(var i = 0;i<oBtns.length;i++){ 
        oBtns[i].index = i; //给每一个标签存储对应的下标 
        oBtns[i].onclick = function(){
            for(var j = 0;j<oDivs.length;j++){ 
                Divs[j].style.display = "none";
            }
            //2.显示对应的div
            oDivs[this.index].style.display = "block";
        }
    }
    

定时器

定时器分类

  • 延时定时器:setTimeout():广告弹窗
  • 间隙定时器:setInterval():轮播图,倒计时,抽奖

setTimeout

  • setTimeout:延时定时器

  • 语法:setTimeout(函数,时间):延迟一定时间执行函数一次(只执行一次) ms

  • 使用场景:广告弹窗

    //1.基础使用
    setTimeout(function(){
        console.log("setTimeout(函数,时间):等待一段时间执行函数一次");
    },2000);
    
    
    //2.可以提前定义好函数,自己将函数名做参数
    var oImg = document.getElementsByTagName("img")[0];
    setTimeout(hide,3000);
    function hide(){
        oImg.style.display = "none";
    }
    

setInterval

  • setInterval:间隙定时器

  • 语法:setInterval(函数,时间):隔一段时间执行一次

  • 使用场景:轮播图,抽奖,倒计时

    //1.基础使用
    setTimeout(function(){
        console.log("setTimeout(函数,时间):等待一段时间执行函数一次");
    },2000);
    
    
    //2.可以提前定义好函数,自己将函数名做参数
    var oImg = document.getElementsByTagName("img")[0];
    setTimeout(hide,3000);
    function hide(){
        oImg.style.display = "none";
    }
    

停止定时器clear

  • 停止定时器clear:定时器只要一开器,就不会主动停止(setInterval)

  • 语法:

    • clearInterval(定时器id)
    • clearTimeout(定时器id)
    • 参数
      • intervald:number值,每一个定时器在调用的时候,会返回一个能唯一标识当前定时器的id
  • 例1:停止的是下一次的执行

    /*定时器停止:定时器只要已开启就不会主动停止
    	      clearInterval(intervalId) : 停止对应的定时器
    定时器id:每一个定时器在调用的时候,会返回一个能唯一标识当前定时器的id
    */  
    var n = 5;
    var timer = setInterval(function(){
        n--;
        if(n <= 0) {
            n = 0;
            //停止定时器  本次还是会执行往,然后结束不会再执行
            clearInterval(timer)
        }
        document.body.innerText = n;
    
    },1000);
    console.log(timer); //1
    
  • 例2:定时器只要停止就没用了,重新开启需要重新填写

    //1.获取元素
    var oImg = document.getElementsByTagName("img")[0];
    var n = 1;
    
    //2.间隔1秒切换图片1次
    var timer = setInterval(changeImg, 1000);
    function changeImg() {  
        n++;
        if (n > 4) { n = 1 }
        oImg.src = "./img/" + n + ".jpg";
    }
    
    //3.鼠标移入图片,停止定时器
    oImg.onmouseover = function () {
        clearInterval(timer);//1
    }
    
    //4.鼠标离开图片,重新开始定时器
    oImg.onmouseout = function () {
        timer = setInterval(changeImg, 1000);
    }
    

同步异步

  • 同步:在做一件事情的时候,如果这件事情没有做完,同步只能等待 alert、for

    //同步:在做一件事情的时候,如果这件事情没有做完,同步只能等待   alert,for
    alert("中午睡觉了吗?");
    console.log("开始");
    for(var i = 0;i<100;i++){
        console.log(i);
    }
    console.log("结束");   //开始  0 1 .... 100 结束
    
  • 异步:在做一件事情的时候,如果这件事情没有做完,但是又需要时间,会执行后面的内容,然后回头处理 定时器、Ajax

    console.log(1);
    setTimeout(function(){
        console.log("异步");
    },1000); //0  就算时间是0,定时器就是异步操作也会等到最后再执行
    console.log(2);  //1  2  一秒后打印 "异步"
    

运动函数封装

1 起飞(从左往右)

  • 实现思路:

    • 点击按钮,改变img的left值

    • left = 当前位置基础 + 10

    • 开启定时器,自动移动位置

      //2.点击button,移动10个像素
      oBtns[0].onclick = function () {
          var timer = setInterval(function () {
              //4.获取元素当前位置
              var cur = parseInt(getStyle(oImg, "left")) + 10;
      
              //3.移动图片的位置 
              oImg.style.left = cur + "px";
          }, 30);
      }
      
  • 问题1:一直飞,飞出边界

    • 解决:限制范围,当运动的1000的位置,停止定时器

      //2.点击button,移动10个像素
      oBtns[0].onclick = function () {
          var timer = setInterval(function () {
              //4.获取元素当前位置
              var cur = parseInt(getStyle(oImg, "left")) + 10;
      
              //5.判断,运动到1000的位置停止
              if(cur >= 1000){
                  cur = 1000;
                  clearInterval(timer);
              }
      
              //3.移动图片的位置 
              oImg.style.left = cur + "px";
          }, 30);
      }
      
  • 问题2:多次点击,速度越点越快

    • 分析原因:定时器会叠加,多次点击会添加多个定时器,叠加执行

    • 解决方案:如果定时器添加在能频繁被触发的地方,在开启定时器之前,将之前的定时器清除掉

      var timer; //timer需要定义成全局变量,因为局部变量每次会重新声明,无法保存值
      
      //2.点击button,图片移动
      oBtns[0].onclick = function () {
          oImg.src = "./img/right.gif";
      
          //6.问题:多次点击,速度越来越快
          //6.原因:定时器会叠加
          //6.解决:如果定时器添加在能频繁被触发的地方,在开启定时器之前,将之前的定时器清除掉
          clearInterval(timer); 
          timer = setInterval(function () {
              //4.获取当前元素的位置   在当前基础上 + 10
              var cur = parseInt(getStyle(oImg, "left")) + 10;
      
              //5.运动到1000的位置停止
              if(cur >= 1000){
                  cur = 1000;
                  clearInterval(timer);
              }
      
              //3.移动图片 
              oImg.style.left = cur + "px";
          }, 30);
      }
      

2 凯旋(往回飞)

  • 在起飞的基础上,(从右到左,-10,条件为<=)

    oBtns[1].onclick = function () {
        oImg.src = "./img/left.gif";
    
        //6.问题:多次点击,速度越来越快
        //6.原因:定时器会叠加
        //6.解决:如果定时器添加在能频繁被触发的地方,在开启定时器之前,将之前的定时器清除掉
        clearInterval(timer); 
        timer = setInterval(function () {
            //4.获取当前元素的位置   在当前基础上 + 10
            var cur = parseInt(getStyle(oImg, "left")) - 10;
    
            //5.运动到1000的位置停止
            if(cur <= 0){
                cur = 0;
                clearInterval(timer);
            }
    
            //3.移动图片 
            oImg.style.left = cur + "px";
        }, 30);
    }
    

3 封装

3.1 基础封装

封装执行过程

  • 实现功能
  • 声明一个函数,将主要代码放入到函数中
  • 找函数中,可变的值做参数,代入到函数中
  • 调用,调试
function move(elemObj,attr,step,target){ //元素:elemObj,属性:attr,步长:step,目标值:target
    clearInterval(timer); 
    timer = setInterval(function () {
        //4.获取当前元素的位置   在当前基础上 + 10
        var cur = parseInt(getStyle(elemObj, attr)) + step;

        //5.运动到1000的位置停止
        if(cur >= target){
            cur = target;
            clearInterval(timer);
        }

        //3.移动图片 
        elemObj.style[attr] = cur + "px";
    }, 30);
}
3.2 条件判断问题
  • 问题:点击起飞可以正常,点击凯旋闪现
  • 原因: 起飞>=目标值 凯旋<=目标值,不能共用一个条件
  • 解决:每一个运动不同的条件
function move(elemObj,attr,step,target){ //元素:elemObj,属性:attr,步长:step,目标值:target
    clearInterval(timer); 
    timer = setInterval(function () {
        //4.获取当前元素的位置   在当前基础上 + 10
        var cur = parseInt(getStyle(elemObj, attr)) + step;

        //5.运动到1000的位置停止
        if(cur >= target && step > 0){ //起飞
            cur = target;
            clearInterval(timer);
        }
        if(cur <= target && step < 0){ //凯旋
            cur = target;
            clearInterval(timer);
        }
        
        
        /*
         if((cur >= target && step > 0) ||(cur <= target && step < 0)) { 
            cur = target;
            clearInterval(timer);
         }
        */

        //3.移动图片 
        elemObj.style[attr] = cur + "px";
    }, 30);
}
3.3 步长问题
  • 问题:傻瓜式操作,+10 -10不让用户考虑

  • 解决

    当前值0 目标值100 +

    当前值100 目标值0 -

    step = 如果 当前值 < 目标值 ? + : -

function move(elemObj,attr,step,target){ //元素:elemObj,属性:attr,步长:step,目标值:target
    step = parseInt(getStyle(elemObj, attr)) < target ? step : -step
    clearInterval(timer); 
    timer = setInterval(function () {
        //4.获取当前元素的位置   在当前基础上 + 10
        var cur = parseInt(getStyle(elemObj, attr)) + step;

        //5.运动到1000的位置停止
        if(cur >= target && step > 0){ //起飞
            cur = target;
            clearInterval(timer);
        }
        if(cur <= target && step < 0){ //凯旋
            cur = target;
            clearInterval(timer);
        }
        
        
        /*
         if((cur >= target && step > 0) ||(cur <= target && step < 0)) { 
            cur = target;
            clearInterval(timer);
         }
        */

        //3.移动图片 
        elemObj.style[attr] = cur + "px";
    }, 30);
}

轮播图

1 轮播图布局

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wc9khY8l-1635473056997)(C:\Users\ibm\AppData\Roaming\Typora\typora-user-images\1629107394896.png)]

2 轮播图自动切换
//2.自动切换图片   每隔2秒切换图片
setInterval(auto,2000);
function auto(){
    n++;   //n 0 0    n=1  -600   n=2  -1200   n=3  -1800
    if(n > 4){
        n = 1;
    }
    move(oUl,"left",40,-600*n);  //600 1200 1800
}
  • 问题:从最后一张到第一张是从后往前扯过去的,想实现的功能,图片永远从挨着的右边切换

  • 解决:在最后添加一张图片1,给用户错觉

    //2.自动切换图片   每隔2秒切换图片
    setInterval(auto,2000);
    function auto(){
        n++;   //n 0 0    n=1  -600   n=2  -1200   n=3  -1800
        if(n > 4){
            n = 1;
            oUl.style.left = 0; //在切换图片2之前,将ul的位置切换到0,
        }
        move(oUl,"left",40,-600*n);  //600 1200 1800
    }
    
轮播图…

对象

对象介绍

  • 对象:在js中万物皆对象,可以将对象分为“内部对象”、“宿主对象”、和“自定义对象”三种。
    • 本地对象[内部对象]:js中的内部对象包括Array、Boolean、Date、Function、Global(全局)、Math、Object、RegExp(正则)、string、Error对象,其中Global和Math对象又被称为”内置对象“,这两个对象在脚本初始化时被创建,不必实例化这两个对象。
    • 宿主对象:宿主对象就是执行js脚本的环境提供的对象,就是浏览器提供的对象,如window和document
    • 自定义对象
  • API
    • API,全称Application Programming Interface,即应用程序编程接口。说白了就是函数,但是这些函数都是封装好的,固定功能的,可以直接调用实现功能的。好比遥控器,不同的按键不同的功能,都是提前定义好的

Math对象

  • 取整方法【掌握】

    • Math.floor():向下取整,有小数就舍弃

    • Math.ceil():向上取整,有小数就进位

    • Math.round():四舍五入

      //4. 公式:min-max : 公式:Math.random()*(max-min+1)+min
      //0-10
      for (var i = 0; i < 10; i++) {
          var num = Math.floor(Math.random() * (10 - 0 + 1) + 0) // ===>11
          //0*11 == >0
          //1*11 ==>11 -->10
          console.log(num);
      }
      
      var arr = ["谢谢惠顾", "五百万", "再抽一次", "豪华轮船", "别墅", "轮播图"];
      console.log(arr[Math.floor(Math.random()*arr.length)]); //0-arr.length-1
      
  • 随机数【掌握】

    • Math.random():生成0-1之间的随机数,范围——[0-1)

    • 公式:生成最大值到最小值之间的随机数 Math.random()*(max-min+1)+min

      //公式:Math.random()*(max-min+1)+min
      //0-10
      for(vari=0;i<10;i++){
          var num=Math.floor(Math.random()*(10-0+1)+0)//--->11
          //0*11--->0
          //1*11--->11,不到11的数,因为random为[0-1)
          console.log(num);
      }
      
      var arr = ["谢谢惠顾", "五百万", "再抽一次", "豪华轮船", "别墅", "轮播图"];
      console.log(arr[Math.floor(Math.random()*arr.length)]); //0-arr.length-1
      
    • 封装一个函数,获取min-max随机数

      //封装一个函数,获取min-max的随机数
      function getRandom(){
          return Math.floor(Math.random()*(max-min)+min);
      }
      
  • 数学公式

    • Math.max (数值1,数值2,数值3…):找序列中的最大值

    • Math.min(数值1,数值2,数值3…):找序列中的最小值

    • Math.abs():取绝对值

    • MAth.sqrt():开根号

    • Math.pow():计算次防数

      //2.数学公式
      console.log(Math.max(1, 9, 4, 7, 2, 8)); //9 找一串参数序列中最大的值
      console.log(Math.min(1, 9, 4, 7, 2, 8)); //1 找一串参数序列中最小的值
      console.log(Math.pow(2, 10)); //1024   Math.pow(基数,次方数) 次方数
      console.log(Math.sqrt(81)); //9   开根号
      console.log(Math.abs(-10)); // 10  取绝对值
      

DAte对象

创建时间对象

  • 创建时间对象

    //1.创建时间对象--当前时间
    var oDate = new Date();
    console.log(oDAte;)//计算机当前这一秒的时间 Wed Sep 29 2021 11:18:13 GMT+0800 (中国标准时间)
    
    setInterval(function(){
    	console.log(oDate);//当时间创建的一瞬间,时间就固定了,后期再使用,一直是一样的
    },1000)
    
  • 创建特定时间

    //1.创建时间对象--任意时间
    //1.1 给多个参数,年,月(月份从0开始),日,时,分,秒    默认0
    var nDate1 = new Date(2021,10-1,1,12,12,12);
    console.log(nDate1);
    
    //1.2 给一个参数  "年,月,日,时:分:秒"
    var nDate2 = new Date("2021,10,1,12:12:12");
    var nDate2 = new Date("2021/10/1,12:12:12");
    var nDate2 = new Date("2021-10-1,12:12:12");
    var nDate2 = new Date("2021 10 1,12:12:12");
    console.log(nDate2);
    
    //1.3 给英文  "月 日 年  时:分:秒"
    var nDate3 = new Date("Oct 1 2021,12:12:12");
    console.log(nDate3);
    

获取时间

  • 获取特定格式时间

    //获取特定格式的时间(年月日)
    console.log(oDate.toDateString());//Wed Sep 29 2021
    console.log(oDate.toLocaleDateString());//2021/9/29
    
    //获取特定格式时间(时分秒)
    console.log(oDate.toTimeString());//13:36:59  GMt+0800 (中国标准时间)
    console.log(oDate.toLocaleTimeString());//下午1:37:10
    
  • 获取单个时间

    //获取单个时间
    var y = oDate.getFullYear();
    console.log(y); //年份 2021
    
    var m = oDate.getMonth()+1;
    console.log(m); //月份   月份从0开始
    
    var d = oDate.getDate(); //日期
    
    var w = oDate.getDay(); //星期
    var week = ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"];
    console.log(week[w]); 
    
    var h = oDate.getHours();
    console.log(h); //13 小时
    
    var mi = oDate.getMinutes();
    console.log(mi); //分钟
    
    var s =  oDate.getSeconds();
    console.log(s); //秒
    
    var t = oDate.getTime();  //获取时间戳 //1970年1月1 --- 现在时间毫秒数
    

倒计时

  • 实现原理

    • 创建一个未来时间

    • 创建一个现在时间

    • 计算两个时间的时间差=未来时间-现在时间

    • 时间换算

      fucntion auto(){
          var futureDate = new Date("2021,10,1");
          var currentDAte = new Date();
          var time = Math.floor((futureDate-currentDate)/1000);//时间戳是毫秒
          
          var t = Math.floor(time/ 86400);
          var h = Math.floor(time % 86400 / 3600);
      	var m = Math.floor(time % 3600 / 60);
          var s = time % 60;
          
          document.body.innerHTML = "现在距离十一放假还剩:" + fullZero(t) + "天 " + fullZero(h) + "小时" + fullZero(m) + "分钟" +fullZero(s) + "秒";
      }
      

moment.js

  • moment.js:JavaScript的日期处理类库

    <script src="./moment.js"></script> 
    <script> 
        //1.日期格式化 console.log(moment().format("YYYY")); //年 
        console.log(moment().format("MM")); //M:月份,MM:一位情况下会补0
    	console.log(moment().format("DD")); //日期 
        console.log(moment().format("HH")); //小时 
        console.log(moment().format("mm")); //分钟 
        console.log(moment().format("ss")); //秒 
        console.log(moment().format("YYYY年 MM月 DD日 HH:mm:ss")); 			    
        console.log(moment().format("YYYY/MM/DD HH:mm:ss")); //2021/04/26 15:42:40 
        setInterval(function(){ 
            document.body.innerHTML = moment().format("YYYY/MM/DD HH:mm:ss")
        },1000);
    </script>
    

String对象

创建字符串

//1.字面量创建 ==string类型==(包装类对象,在使用对象方法的时候,会暂时将自己包装成对象)
var str1 = "web0824";
console.log(str1);
console.log(str1.length); //7  获取字符串长度
console.log(str1.charAt(3)); //"0"  通过下标获取对应的字符
console.log(typeof str1); //"string"

//2.new 关键字创建  ==object类型==
var str2 = new String("web0824");
console.log(str2);
console.log(typeof str2); //"object"

字符串对象方法

字符串属性
  • length:获取字符串长度
字符串方法
1).charAt()
  • 语法:strObj.charAt(下标)

  • 作用:获取对应下标位置的字符

    //str.charAt(下标):获取下标对应的字符
    var s = str.charAt(2);
    
2).charCodeAt()
  • 语法:strObj.charCodeAt(下标)

  • 作用:获取对应下标字符的编码

    //3.str.charCodeAt(下标):获取下标对应字符的编码 “0”--48  “A"-65  "a"--97
    console.log(str.charCodeAt(2)); //98
    
    //声明一个函数,判断值是不是纯数字字符串,使用charCodeAt()实现
    function isNumber(str){
        for(var i = 0;i<str.length;i++){
            //1.如果不是数字(字符串编码 <48  >57)  return false
            if(str.charCodeAt(i) < 48 || str.charCodeAt(i)>57){
                return false; //中间但凡有一个不是数字,return 
            }
        }
        return true; //代码能执行到这一行,if都没有成立
    }
    
3).inexOf()
  • 语法:str.Obj.indeOf(search.value,index)

  • 作用:查询一个字符串在另一个字符中首次出现的位置,出现返回对应的下标,没有返回-1

  • 参数:

    • search.value:必须的,需要查询的字符串

    • index:可选,开始查找的位置,默认是下标0

       var str = "webuiwebuiweb";
      var s = "ui";
      var index = str.indexOf(s);
      console.log(index); //3  应的下标
      
      var index = str.indexOf("java");
      console.log(index); //-1 :  找不到返回-1
      
      var index = str.indexOf("ui", 4); //在str中查找是否有ui,从下标为4的位置开始
      console.log(index); //8
      
      
4).lastIndexOf()
  • 语法:strObj.lastindexOf(search.value,index)
  • 作用:查询一个字符串在另一个字符串中最后一次出现的位置,出现返回对应的下标,没有返回-1
  • 参数:
    • searchValue:必须的,需要查询的字符串
    • index:可选,开始查找的位置,默认是str.length 从后往前找
5)substring
  • 语法:str.substring(start,end)

  • 作用:截取下标在start和end之间的字符串,包括开始start不包括结end

  • 参数:

    • start:必须,表示从下标为start的位置开始截

    • end:可选,默认是最后str.length

       var id = "431102199912121213";
      var s = id.substring(3);  //从下标为3的位置开始,截取到末尾
      console.log(s);//102200012121213
      
      var date = id.substring(6,10); //从下标为6的位置开始,截取到下标10
      console.log(2021 - date); //22
      
      
6).slice
  • 语法:str.slice(start,end)

  • 作用:截取下标在start和end之间的字符串,包括开始start 不包括结束end

  • 参数:

    • start:必选,表示从下标为start的位置开始截

    • end:可选,默认是最后str.length

      var id = "431102199912121213";
      var s = id.slice(3);  //从下标为3的位置开始,截取到末尾
      console.log(s);//102200012121213
      
      var date = id.slice(6,10); //从下标为6的位置开始,截取到下标10
      console.log(2021 - date); //22
      
  • substring和slice的区别

    //区别
    var str = "web0824";
    console.log(str.substring(3,0)); //web  自动调整位置 0,3  
    console.log(str.slice(3,0)); //""  不自动调整位置3,0
    
    console.log(str.substring(2,-1)); //we 负数默认为0   2,0 --- > 0,2
    console.log(str.slice(2,-1)); //b082 负数表示截取到倒数第几个`
    
7). substr()
  • 语法:str.substr(start,length)

  • 作用:截取某个长度的字符

  • 参数

    • start : 必需,表示从下标为start的位置开始截

    • length:截取几个

8).大小写转换
  • 语法:str.toUpperCase() str.toLowCase();

  • 作用:转换大小写

    var str1 = "R5tX";
    var str2 = "r5tx";
    console.log(str1 == str2); //false
    
    
    //1.大小写转换:toUpperCase():转大写   toLowerCase():转小写
    var s1 = str1.toLowerCase(); 
    console.log(s1);  //r5tx   
    
    var s2 = str1.toUpperCase();
    console.log(s2); //R5TX  
    
    
    //2.进行不区分大小写的验证
    console.log(str1.toUpperCase() == str2.toUpperCase());
    
9).replace():替换字符串,一次只能换一个
  • 语法:str.replace(searchValue,replaceValue)

  • 作用:替换字符串

  • 参数:

    • searchValue:将要被替换的内容

    • replaceValue:替换的内容

      var str = "webuiwebui";
      var s3 = str.replace("ui", "java"); //将ui替换成java  
      console.log(s3); //webjavaweb    一次只能换一个
      
      var s4 = s3.replace("ui", "java");
      console.log(s4);  //webjavawebjava
      
10).split()
  • 语法:str.split(“分割标志”[,length]) length可选

  • 作用:将字符串按特定标识分隔成数组

    var str = "2021/09/30";
    var arr = str.split("/");
    console.log(arr); // ["2021", "09", "30"]
    
    var str = "web";
    var arr = str.split("");
    console.log(arr); //["w", "e", "b"]
    
11).trim()
  • 语法:str.trim()
  • 作用:
  • 字符串首尾空格
12). 字符串转json
  • 有这样一个url:http://item.taobo.com/item.html?a=1&b=2&c=&d=xxx&e,
    请写一段js程序提取url中各个get参数(参数名和参数个数不确定),将其key-value形式返回到一个json结构中,
    如{a:1,b:2”,c:“”,d:“xxx”,e:undefined}
    
  • 实现思路

    • 获取get参数 : ?后面的一块
    • 将一串get参数分成一组一组的
    • 循环写入到json对象中
  • 实现代码

    //http://item.taobo.com/item.html?a=1&b=2&c=&d=xxx&e,
    var urlStr = "http://item.taobo.com/item.html?a=1&b=2&c=&d=xxx&e";
    var json = {};
    
    //1.获取get参数(?号后面)
    urlStr = urlStr.split("?")[1]; //["http://item.taobo.com/item.html","a=1&b=2&c=&d=xxx&e"]
    
    //2.将连续的字符串分成一组一组的
    var urlArr = urlStr.split("&"); //["a=1","b=2","c=","d=xxx","e"]
    
    //3.将一组一组数据写入到json里面
    for (var i = 0; i < urlArr.length; i++) {
        var arr = urlArr[i].split("="); //"a=1" ==== >  ["a","1"]
        json[arr[0]] = arr[1];
    }
    console.log(json); //{a:“1”,b:“2”,c:“”,d:“xxx”,e:undefined}
    

数组对象

  • 概念:数组是存储数据的容器,可以任意多个,可以存储任意数据类型

创建数组对象

  • 字面量创建(与字符串对象字面量创建不同,数组字面量和关键字创建并无不同)

    var arr = [1,2,3,4];
    
  • new 关键字创建

    //2.new关键字创建
    var arr2 = new Array(1,2,3,4);
    
    //3.参数只有一个并且是number,表示创建长度为n的空数组
    var arr3 = new Array(4);
    console.log(arr3); //[empty × 4]
    
  • 获取和存储

    //4.获取数组元素
    console.log(arr2[2]); //3
    
    //5.添加数组元素
    arr2[4] = 5;
    console.log(arr2);
    
    //通过键值对存储(了解)  通过键值对存储,不计入长度,不能通过下标获取,不参与遍历
    arr2.key = "value";
    console.log(arr2); //[1, 2, 3, 4, 5, key: "value"]
    console.log(arr2.key); //"value"
    

数据类型的分类依据

  • 数据类型分类:number,string,boolean,null,undefined,复杂数据类型(object,array,function)

    • 基本数据类型:存储结构单一,存储在内存的栈区(值是直接存储在变量上)

    • 复杂数据类型:存储结构复杂多样的数据,存储在内存中的堆(变量中存储的是内存地址——内存地址也存在栈区

                       typeof
      number          "number"       12
      string          "string"       "12"
      boolean         "boolean"      true
      undefined       "undefined"    
      null            "object"       ""
      
      object          "object"     {"name":"Web","age":18,"is":true,"eat":function(){ }}
      array           "object"     [1,true,null,"d",[],{}]
      function        "function"   function(){f}
      
    • 内存分布

      ​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xA2KS9Rx-1635473056999)(C:\Users\20199\Desktop\笔记\第二阶段\img\QQ截图20211002152437.png)]

  • 验证内存分布

    var a = 10;
    var b = a;
    a = 20;
    console.log(a,b); //20,10
    
    var arr1 = [1,2,3];
    var arr2 = arr1;	//将arr1的内存地址赋给了arr2,他们共用一块地址
    arr1[3] = 4;	//一改都改
    console.log(arr1,arr2);		//[1,2,3,4]  [1,2,3,4]
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oPbXsr89-1635473057001)(C:\Users\20199\Desktop\笔记\第二阶段\img\QQ截图20211002152924.png)]

数组的方法(sort方法在数组排序中)

1)push()与pop()
  • 作用:在数组的末尾添加或删除元素(数组栈方法)

    //1.push,pop:在数组的末尾添加或删除元素(数组栈方法)
    //1.1 arr.push(items) : 在数组的末尾添加一个或多个元素,返回当前数组的长度
    var len = arr1.push(4);
    console.log(arr1, len); //[1, 2, 3,4],4
    
    arr1.push("A", "B");
    console.log(arr1); //[1, 2, 3, 4, "A", "B"]
    
    //1.2 arr.pop():在数组的末尾删除一个元素,返回被删除的元素
    var del = arr1.pop();
    console.log(arr1, del); // [1, 2, 3, 4, "A"] ,"B"
    
2)unshift()与shift()
  • 作用:在数组的头部添加或删除元素

    //2.unshift,shift:在数组的头部添加或删除元素  [1, 2, 3, 4, "A"] 
    //2.1  arr.unshift(items) : 在数组的头部添加一个多个元素,返回当前元素的长度
    arr1.unshift("放假");
    console.log(arr1); // ["放假", 1, 2, 3, 4, "A"]
    
    //2.2 arr.shift():在数组的头部删除一个元素,返回被删除的元素
    arr1.shift();
    console.log(arr1); //[1, 2, 3, 4, "A"] 
    
.splice()
  • 语法:splice(strat[,deleteCount,items])

  • 作用:删除一串连续的元素,使用items替换,返回被删除元素组成的数组

  • 参数

    • start:必须,开始删除的下标位置

    • deleteCount:可选,删的的个数

    • items:可选,替换的内容

      var arr = [1, 2, 3, 4, 5, 6, 7, 8];
      var delArr = arr.splice(3); //从下标为3的位置开始,删除到末尾
      console.log(arr, delArr);//[1,2,3]  ,[4, 5, 6, 7, 8]
      
      
      var arr = [1, 2, 3, 4, 5, 6, 7, 8];
      arr.splice(3,2);//从下标为3的位置开始,删除2个
      console.log(arr);  //[1, 2, 3, 6, 7, 8]
      
      
      var arr = [1, 2, 3, 4, 5, 6, 7, 8];
      arr.splice(3,2,"A","B","C");//从下标为3的位置开始,删除2个,替换
      console.log(arr); //[1, 2, 3, "A", "B", "C", 6, 7, 8]
      
      var arr = [1,2,3,5,6];
      arr.splice(3,0,4);
      console.log(arr); // [1, 2, 3, 4, 5, 6]
      
数组去重
  • 比较删除

    • 原理:

      • 拿第一个和后面所有的进行比较,如果重复,删除后面的

      • 拿第二个和后面所有的进行比较,如果重复,删除后面的

      • for(var i=0;i<arr.length;i++){
            for(var j=i+1;j<arr.length;j++){
                if(arr[i]==arr[j]){
                    //如果相等,删除后面的数组元素
                    arr.splice(j,1);
                    j--;//删除元素,后面的数组元素就会往前移动,对应的下标也需要改变
                }
            }
        }
        

数组小方法

  • arr.indexOf(searchValue):检索元素在数组中首次出现的位置,返回对应的下标,不出现返回-1

     //1.arr.indexOf(searchValue) : 检索元素在数组中首次出现的位置,返回对应的下标,不出现返回-1
    var index = arr.indexOf(5);
    console.log(index);  //4
    
  • arr.slice(srart,end):截取从start开始到end结束连续的数组元素,组成一个新的数组返回

    //2.arr.slice(start,end):截取从start开始到end结束连续的数组元素,组成一个新的数组返回
    var sArr = arr.slice(2,4);
    console.log(sArr); //[3, 4]
    
  • arr.join(标识):将数组按特定的标识组合成字符串

    //3.arr.join(标识) : 将数组按特定的标识组合成字符串 
    var arr = ["w","e","b"];
    var s1 = arr.join("-");
    console.log(s1); //w-e-b
    
    var s2 = arr.join("");
    console.log(s2);  //web
    
    console.log(arr.join()); //w,e,b
    
    var date = "2021/09/30";   //---->2021-09-30
    var s2 = date.split("/").join("-");   //split string方法,将字符串按照标识分隔成数组["2021","09","30"]  join 数组方法,将数组按照标识组合成字符串
    console.log(s2); //2021-09-30
    
  • arr.reverse():倒叙

    //4.arr.reverse():倒序
    var arr = [1,2,3,4];
    arr.reverse();
    console.log(arr); //[4, 3, 2, 1]
    
  • arr.concat(arr1,arr2):将多个数组或元素组合成一个数组返回

    //arr.concat(arr1,arr2,...):将多个数组或元素组合成一个数组返回
    var arr1 = [1,2,3,4];
    var arr2 = ["a","b"];
    var arr3 = arr1.concat(arr2,"ha","d");
    console.log(arr3);  //[1,2,3,4,"a","b","ha","d"]
    

方法是否改变原数组

#### 改变原数组

pop():   删除 arrayObject 的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不 改变数组,并返回 undefined 值。arrayObject.pop() 

push():push() 方法可把它的参数顺序添加到 /arrayObject 的尾部。它直接修改 arrayObject,而不是创建一个新的数组,arrayObject.push(newelement1,newelement2,.,newelementX) 

reverse():该方法会改变原来的数组----将原来的数组倒序,而不会创建新的数组。arrayObject.reverse() 

shift():   删除数组的第一个元素,并返回第一个元素的值,如果数组是空的,那么 shift() 方法将不进行任何操作. 

unshift():  unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。arrayObject.unshift(newelement1,newelement2,.,newelementX)返回arrayObject 的新长度

sort():   对数组的引用。请注意,数组在原数组上进行排序,不生成副本。arrayObject.sort(sortby) (如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。 
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下: 
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。 
若 a 等于 b,则返回 0。 
若 a 大于 b,则返回一个大于 0 的值。) 

splice():  splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。 如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组 arrayObject.splice(index,howmany,item1,..,itemX) 
不改变原数组
concat():用于连接两个或多个数组,仅会返回被连接数组的一个副本,arrayObject.concat(arrayX,arrayX,……,arrayX) 

join():返回一个字符串。该字符串是通过把 arrayObject 的每个元素转换为字符串,然后把这些字符串连接起来,arrayObject.join(separator) 

slice():arrayObject.slice(start,end)返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

数组排序

数组排序算法
  • 选择排序

    • 思路

      • 拿第一个和后面所有的进行比较,如果后面比第一个值更小,交互位置

      • 拿第二个和后面所有的进行比较,如果后面比第二个值更小,交互位置

      • var arr = [3,9,5,6,1,7,8,4,2];
        for(var i = 0;i<arr.length;i++){
            for(var j = i+1;j<arr.length;j++){
                if(arr[i] > arr[j]){  //如果后面比第一个值更小,交互位置
                    var temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        
  • 冒泡排序

    • 思路:相邻的两个进行比较,两两比较

      for (var i=0;i<arr.length;i++){//外层循环不参与比较,内循环两两比较
          for(var j=0;j<arr.length-1-i;j++){
              if(arr[j]>arr[j+1]){
                  var temp = arr[j];
                  var arr[j] = arr[j+1];
                  arr[j+1] = arr[j];
              }
          }
      }
      
数组排序方法.sort()
  • 数组排序

    //2.默认以字符串的比较方式排序
    arr.sort();
    console.log(arr); //[11, 2, 3, 4, 5, 6, 7, 8, 9]
    
    
    //3.以number的形式进行比较
    arr.sort(function(a,b){ //两个相邻的数组元素
        // return a - b ;//从小到大排序    返回值大于0交换位置
        return b - a ;//从大到小排序
    
    })
    console.log(arr); //[2, 3, 4, 5, 6, 7, 8, 9,11]
    
  • 对象排序

    //4. 按年龄排序(从小到大)
    var students = [
        {"name":"张果","age":18,"date":"2003-10-1"},
        {"name":"杨婷","age":16,"date":"2005-6-1"},
        {"name":"李云龙","age":20,"date":"2001-7-1"},
        {"name":"吕辉","age":24,"date":"1997-8-1"},
        {"name":"杨胜昭","age":24,"date":"1997-9-11"}
    ]
    
    students.sort(function(a,b){ 
        //a = {"name":"张果","age":18,"date":"2003-10-1"}
        //b = {"name":"杨婷","age":16,"date":"2005-6-1"}
        return a.age - b.age;
    });
    console.log(students);
    
  • 日期排序

    //5.出生日期降序排序(从大到小)
    students.sort(function(a,b){
        return new Date(b.date) - new Date(a.date);  
    });
    console.log(new Date("2003-10-1"));  //创建成时间对象
    console.log(Date.parse("2003-10-1")); //将字符串格式的时间转换为时间戳
    console.log(students);
    
  • 中文排序

    //6.按中文排序
    students.sort(function(a,b){
        //按本地计算机语言排序   
        return a.name.localeCompare(b.name);
    });
    
  • 随机排序

     //7.随机排序
    var arr = [1,2,3,4,5,6];
    arr.sort(function(){
        return 0.5 - Math.random();  //0.5  [0-1]
    })
    console.log(arr);
    

数组迭代方法(IE8+)

  • 循环、遍历、迭代

  • every

    • 语法:arr.every(function(数组元素,下标,当前循环的数组){ })

    • 作用:对数组元素进行判断,所有的判断都为true,结果才为true

      var arr = [89,56,98,83,44,78];
      //需求:是否都及格
      var isJ = arr.every(function(value){//value:数组元素  89 56 83  index:下标 0 1 2  array:当前循环的数组
          return value > 60;
      });
      console.log(isJ);//false
      
  • some

    • 语法:arr.some(function(数组元素,下标,当前循环的数组){ })

    • 作用:对数组元素进行判断,只要有一个为真结果就为真

      //2.arr.some(function(value,index,array){}) : 对数组元素进行判断,如果结果只要有一个为真,结果就为真
      var arr = [89,56,98,83,44,78];
      //是否有90以上的
      var is9 = arr.some(function(value){
          return value > 90;
      });
      console.log(is9); //true
      
  • filter

    • 语法:arr.filter(function(数组元素,下标,当前循环的数组){ })

    • 作用:对数组元素进行判断,满足条件的组成一个新的数组返回

       //3.arr.filter(function(value,index,array){}) : 对数组元素进行判断,返回满足条件的元素组成一个新的数组返回
      var students = [
          {"name":"苗苗1",c:50},
          {"name":"苗苗2",c:100},
          {"name":"苗苗3",c:59},
          {"name":"苗苗4",c:69},
          {"name":"苗苗5",c:39},
      ]
      //挑选不及格的
      var s = students.filter(function(value){ //value = {"name":"苗苗1",c:50}
          return value.c < 60;
      });
      console.log(s);
      
  • map

    • 语法:arr.map(function(数组元素,下标,当前循环的数组){ })

    • 作用:遍历数组,有返回值,返回值会组成一个新的数组返回

      //4.arr.map(function(value,index,array){}):遍历数组,返回值会组成一个新的数组
      var arr = [67,87,56,12,34];
      //每个都加5分
      var newArr = arr.map(function(value){
          return value + 5;
      });
      console.log(newArr);  //[72, 92, 61, 17, 39]
      
  • forEach

    • 语法:arr.forEach(function(数组元素,下标,当前循环的数组){ })

    • 作用:遍历数组,没有返回值

      //5.arr.forEach(function(value,index,array)):遍历数组,没有返回值
      arr.forEach(function(value,index){
          console.log(index,value);
      })
      

正则对象

  • 正则对象:RegExp
  • 概念:提前定义的,用于检测字符串的逻辑公式(正则表达式)/^1[3-9]\d{9}$/
  • 作用:验证字符串是否满足条件

创建正则对象

  • 字面量创建

    var reg = /检索公式/gi
    
  • 关键字new创建

    var reg = new RegExp(检索公式,修饰符)
    var reg1 = new RegExp("[0-9]","gi");
    console.log(reg1);  ///[0-9]/gi
    
  • 区别

    //3.区别
    var w = "web";
    var reg3 = /w/;  //字面量创建,没有变量的概念
    console.log(reg3); // /w/
    
    var reg4 = new RegExp(w);
    console.log(reg4); //  /web/
    

修饰符

  • g:global执行一个全局的匹配

    //1.g : global 执行一个全局的匹配
    var str = "web7web4webu7";
    var reg1 = /\d/;
    console.log(str.replace(reg1,"*"));  //web*web4webu7
    var reg2 = /\d/g;
    console.log(str.replace(reg2,"*"));  //web*web*webu*
    
  • i:ignore case 执行一个不区分大小写的匹配

    //2.i : ignore case :执行一个不区分大小写的匹配
    var str = "he is girl,He is girl";
    var reg3 = /he/g;
    console.log(str.replace(reg3,"she"));  //she is girl,He is girl
    
    var reg4 = /he/gi;
    console.log(str.replace(reg4,"she")); //she is girl,she is girl
    

检索方法

字符串方法直接使用正则
  • replace

    //1.replace
    var str = "he is girl,He is girl";
    console.log(str.replace(/he/gi,"she")); //she is girl,she is girl
    
  • split

    //2.split()
    var str = "q1w2e3r4t5y6r";
    var arr = str.split(/\d/);
    console.log(arr); // ["q", "w", "e", "r", "t", "y", "r"]
    
  • match (挑选)

    //3.match(正则):挑满足条件的组成一个新的数组返回
    var str = "q1w2e3r4t5y6r";
    var arr = str.match(/\d/g);
    console.log(arr); //["1", "2", "3", "4", "5", "6"]
    
  • search 和indexOf一样,不过search可以使用正则

    //4.search(正则) 和indexOf一样
    var str = "q1w2e3r4t5y6r";
    var index = str.search(/\d/);
    console.log(index); //1
    
正则检索方法
  • test

    //reg.test(str):检索字符串是否通过检索,通过返回true,没有返回false
    var str = "13112345678";
    var reg = /^1\d{10}$/;
    if(reg.test(str)){
        console.log("是正确的电话号码");
    }else{
        console.log("不是正确的电话号码"); //false
    }
    
  • exec

    //reg.exec(str):检索字符串,检索通过返回数组,检索不通过返回null
    var str = "ere3trt6w4";
    var reg = /\d/;
    console.log( reg.exec(str)); //["3", index: 3, input: "ere3trt6w4", groups: undefined]
    
    
    //正则是惰性检测,从左往右开始检测,检测到一个以后就停止
    //默认每次都从下标0开始检测,加上g,从上一次查找到的位置往后开始查找
    var str = "ere3trt6w4";
    var reg = /\d/g;
    console.log(reg.exec(str)); //["3", index: 3, input: "ere3trt6w4", groups: undefined]
    console.log(reg.exec(str)); //["6", index: 7, input: "ere3trt6w4", groups: undefined]
    console.log(reg.exec(str)); //["4", index: 9, input: "ere3trt6w4", groups: undefined]
    console.log(reg.exec(str)); //null
    console.log(reg.exec(str)); //["3", index: 3, input: "ere3trt6w4", groups: undefined]
    

正则的元字符(锚字符)

元字符—单个字符
  • .

    .:匹配除换行符意外的任意字符

    //1)  . : 匹配除换行符以外的任意字符
    var str = "\nab\ncde";
    var reg = /./
    console.log(reg.exec(str)); //["a", index: 1]
    
    //web____ujiuye
    var str = "web0322ujiuye";
    var reg = /web....ujiuye/;
    console.log(reg.exec(str)); //"web0322ujiuye"
    console.log(reg.exec("web03221ujiuye")); //null
    
  • []

    []:匹配字符集中的任意一位字符 [a-z]:匹配小写字母 [a-zA-Z]:匹配字母 [0-9]:匹配数字

    [^]:匹配除字符集中的任意一位字符

    //2). [] : 匹配字符集中的任意一位字符  [a-z]:匹配小写字母  [a-zA-Z]:匹配字母 [0-9]:匹配数字
    var reg = /[@#$%^&*]/;
    var str = "str#fd@!";
    console.log(reg.exec(str)); //["#", index: 3]
    
    // [^]: 匹配除字符集中的任意一位字符
    var reg = /[^0-9A-Z]/;  //匹配除数字和大写字母外的任意字符
    var str = "45243SASA#fdsfs";
    console.log(reg.exec(str)); //["#", index: 9]
    
  • \d:匹配数字 \D:匹配非数字

    //\d:匹配数字 \D:匹配非数字
    var str = "q1w2";
    var reg1 = /\d/;
    var reg2 = /\D/;
    console.log(reg1.exec(str)); //"1"
    console.log(reg2.exec(str)); //"q"
    
  • \w:匹配数字、字母、下划线 \W:匹配非数字、字母、下划线

    //\w:匹配数字字母下划线  \W:匹配非数字字母下划线 
    var str = "w2";
    var reg1 = /\w/;
    var reg2 = /\W/;
    console.log(reg1.exec(str)); //"w"
    console.log(reg2.exec(str)); //null
    
  • \s:匹配空格 \S:匹配非空格

    //\s:匹配空格  \S:匹配非空格
    var str = "          hello world               ";
    console.log(str.replace(/\s/g,"")); //helloworld
    
  • a 以a开头 : a :a a 以a结尾

    //6.  ^ : ^a 以a开头    $ : a$  以a结尾
    var str = "12345642432rwrewrw";
    var reg = /^\d\d\d\d\d\d$/;
    console.log(reg.exec(str)); //null
    
元字符(量词)
  • ?:字符? 匹配前面的字符0次或1次

    // ? : 字符? 匹配前面的字符0次或1次
    var str = "https://www.jd.com"; 
    var reg = /^https?:\/\/www\.jd\.com$/;  //\转义,让符合只是一个字符,失去本身的意义
    console.log(reg.exec(str)); //"["http://www.jd.com""
    
  • *:字符* 匹配前面的字符0次或多次(连续的)

    //2) * : 字符*  匹配前面的字符0次或多次(连续的)
    var str = "aasaaaaa3";
    var reg = /a*/;
    console.log(reg.exec(str)); //"aa"
    
  • +:字符+ 匹配前面的符号至少1次

    //3) + : 字符+ 匹配前面的符号至少1次
    var str = "https://www.taobao.com";  //匹配网址   163.com
    var reg = /^https?:\/\/www\.\w+\.com$/;
    console.log(reg.exec(str));
    
  • {n,m}:a{n,m} 匹配前面的符号最少n次,最多m次

    //4) {n,m} : a{n,m} 匹配前面符号最少n次,最m次
    //验证QQ
    var reg = /^[1-9]\d{4,10}$/;   //手机号
    console.log(reg.exec("0123435435435353"));
    
    //{n} : 匹配n次
    //验证银行卡密码
    var reg = /^\d{6}$/;
    
    //{n,} : 匹配最少n次,最多无限
    var str = "aaa1321321";
    var reg = /a{5,}/;
    console.log(reg.exec(str)); //null
    
    //注意:量词之间不能同时使用   {} + ? *
    console.log(/.?{1,2}/); //报错
    
分组与|
  • |

    // | 或
    var str = "http://www.suibian.cn";
    var reg = /^https?:\/\/www\.\w{2,}\.(com|net|cn|org|cc|edu)$/i;
    console.log(reg.exec(str));  //"http://www.suibian.cn"
    
  • () 分组

    //() 分组
    var str = "hello world";
    var reg = /(hello) (world)/;
    console.log(reg.exec(str));  //["hello world", "hello", "world"]
    console.log(RegExp.$1);  //获取第一个分组的内容
    console.log(RegExp.$2);  //获取第二个分组的内容
    console.log(str.replace(reg,"$2 $1")); //world hello
    
前瞻后顾
  • (?😃:非获取匹配

    var str = "http://www.suibian.cn";
    var reg = /^https?:\/\/www\.\w{2,}\.(com|net|cn|org|cc|edu)$/i;
    console.log(reg.exec(str));  //["http://www.suibian.cn", "cn"] 会获取到括号(分组)中的内容
    
    var str = "http://www.suibian.cn";
    var reg = /^https?:\/\/www\.\w{2,}\.(?:com|net|cn|org|cc|edu)$/i;
    console.log(reg.exec(str));  //["http://www.suibian.cn"] 不会获取到括号(分组)中的内容
    
  • (?=):前瞻 正向肯定预查 后面必须是什么

    //1.(?=) : 前瞻,a(?=匹配条件) : a后面必须是什么
    var str = "w2de";
    var reg = /[a-z](?=[a-z])/;
    console.log(reg.exec(str));  //["d", index: 2]
    
    //需求:验证用户名,必须是数字和字母组成  {5-10}
    //(?=):必须    (?=.*\d.*):必须有数字    (?=.*[a-zA-Z].*)
    //.*  匹配除换行以外的任意0,多次    \d
    var reg = /(?=.*\d.*)(?=.*[a-zA-Z].*)^[0-9a-zA-Z]{5,10}$/;
    var str = "fd32fs";
    console.log(reg.exec(str));
    
  • (?!):负前瞻 正向否定预查 后面不能是什么

    //2.(?!) : 负前瞻  a(?!匹配条件) : a后面不能是什么
    var str = "w2de";
    var reg = /[a-z](?!\d)/;
    console.log(reg.exec(str));  //["d", index: 2]
    
    //需求:验证用户名,必须是数字和字母组成  {5-10}
    // /^[a-zA-Z]+$/ :纯字母
    var reg = /(?!^[a-zA-Z]+$)(?!^\d+$)^[0-9a-zA-Z]{5,10}$/;
    var str = "eq1321321";
    console.log(reg.exec(str));
    
    
  • (?<=):后顾(?<=匹配条件)a: a的前面必须是什么

    var str = "w2de34";
    var reg = /(?<=\d)[a-z]/
    console.log(reg.exec(str));
    
  • (?<!):负后顾(?<!匹配条件)a: a的前面不能是什么

    var str = "w2de34";
    var reg = /(?<![a-z])\d/;
    console.log(reg.exec(str)); //["4", index: 5]
    

DOM

DOM概念

  • JavaScript组成

    • ECMAscript:核心语法标准,常用对象
    • DOM:Document Object Model 文档对象模型
    • BOM:Browesr Object Model 浏览器对象模型
  • 浏览器渲染

    • DOM树:浏览器在解析HTML文档的时候,将文档解析成树形结构(DOM树),由节点组成

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b4y5bj6K-1635473057002)(C:\Users\20199\Desktop\笔记\第二阶段\img\DOM树.png)]

    • CSS树

查找DOM节点

DOM获取节点
  • 通过id获取元素

    • document.getElementById(”id名“);
  • 通过标签名获取元素

    • document.getElementsByTagName(“标签名”):获取整个文档中对应标签名的标签
    • 父元素.getElementsByTagName(“标签名”):获取父元素中对应标签名的标签
  • 通过类名获取元素

    • document.getElementsByClassName(“类名”):获取整个文档中对应类名的标签
    • 父元素.getElementsByClassName(“类名”):获取父元素中对应类名的标签
  • 通过选择器获取元素(兼容IE8+)

    • document.querySelector(“选择器”) : 获取选择器选中标签的第一个元素

    • document.querySelectorAll(“选择器”):获取选择器选中的所有元素

      /*4.选择器获取: ie8以下不兼容 
        document.querySelector("选择器") : 获取选择器的标签中第一个元素,返回节点列表,     
        document.querySelectorAll("选择器"):获取选择器选中的所有元素,返回节点列表, 
        和集合一样的使用方式 
      */
      //document.querySelector("选择器") : 获取选择器的标签中第一个元素 
      var oLis1 = document.querySelectorAll(".list li"); 
      console.log(oLis1); //<li>梅菜扣肉</li> 
      
      //document.querySelectorAll("选择器"):获取选择器选中的所有元素 
      var oLis2 = document.querySelectorAll(".list li"); 
      console.log(oLis2); //NodeList(6) [li, li, li, li.yang, li, li]
      
  • 获取方式区别

    //2.区别: get是动态获取,query是静态获取,获取的时候有就是有,没有就是没有
    var oDiv = document.querySelector("div");
    var getP = document.getElementsByTagName("p");
    var queryP = document.querySelectorAll("p");
    console.log(getP,queryP); //[] []
    
    //往div中添加p标签
    oDiv.innerHTML = "<p></p><p></p><p></p>";
    console.log(getP,queryP); //HTMLCollection(3) [p, p, p]   []
    
DOM获取子节点
  • 语法:

    • 父节点.children : 非标准属性(没有兼容问题,就用这个)
    • 父节点.childNodes : 标准属性
  • //2.父节点.children   非标准属性(没有兼容问题,就用这个)
    var childs = oUl.children;
    console.log(childs); //HTMLCollection(6)
    
    
    //3.父节点.childNodes 标准属性
    var childs2 = oUl.childNodes;
    console.log(childs2); //NodeList(13)  [text,li,text,li]
    
  • 节点分类

    标签节点,文本节点(文字,空格,回车),属性节点,注释节点......
    
  • 节点基本属性

    • 语法:

      • 节点.nodeType : 返回节点类型
      • 节点.nodeName : 返回节点名称
      • 节点.nodeValue : 操作文本节点的内容
    • //4.节点属性
      //4.1 节点.nodeType : 返回节点类型 
      console.log(childs1[0].nodeType); //3 -- 文本节点 
      console.log(childs1[1].nodeType); //1 -- 标签节点 2 -- 属性节点 
      console.log(childs1[6].nodeType); //8 -- 注释节点 
      
      //4.2 节点.nodeName : 返回节点名称 
      console.log(childs1[0].nodeName); //#text 
      console.log(childs1[1].nodeName); //"LI" 
      
      //4.3 节点.nodeValue : 操作文本节点的内容 
      childs1[0].nodeValue = "fdfd";
      
获取父节点
  • 语法:

    • 子节点.parentNode:获取直接父节点
    • 子节点.offerParent:获取定位父元素
  • //1.获取直接父节点   子节点.parentNode
    console.log(oSpan.parentNode);  //p
    console.log(oSpan.parentNode.parentNode);  //div
    
    
    //2.获取定位父元素   子节点.offsetParent
    console.log(oSpan.offsetParent);
    
获取兄弟节点
  • 首节点

    • 父节点.firstElementChild||父节点.firstChild

    • 方法兼容 if 判断,属性兼容||短路运算

      //2.1 父节点.firstChild  在标准浏览器中会获取到文本节点
      var first = oUl.firstChild;
      first.style.background = "red";
      
      //2.2 父节点.firstElementChild    ie8-不兼容
      var first = oUl.firstElementChild;
      first.style.background = "red";
      
      /* 2.3 兼容
         方法的兼容: xx.xx()  判断(拿其中任意一个方法作为判断条件,必须写成xx.xx)
         属性的兼容: xx.xx    ||(标准 || ie)
      */
      
      var first = oUl.firstElementChild || oUl.firstChild;
      first.style.background = "red"; 
      
  • 尾结点

    • 父节点.lastElementChild||父节点.lastChild
  • 上一个兄弟节点

    • 参考节点.previousElementSibling||参考节点.previousSibling
  • 下一个兄弟节点

    • 参考节点.nextElementSibling||参考节点.nextSibling

创建节点

  • 创建标签节点

    • 标签节点:document.createElement(“标签名”)

      //1.创建标签节点  document.createElement("标签名")
      var oDiv = document.creatElement("div");
      
      //3.添加内容
      oDiv.innerHTMl = "明天吃什么?";
      
  • 创建文本节点

    • 文本节点:document.createTExtNode(“文本内容”)

      //1.创建标签节点  document.createElement("标签名")
      var oDiv = document.createElement("div");
      
      //2.创建文本节点: document.createTextNode("文本内容");
      var txt = document.createTextNode("他还是个孩子");
      //添加到标签中
      oDiv.appendChild(txt);
      

添加节点

innerHTML追加节点
  • 之前使用+=进行追加,后面的标签会将之前的覆盖,之前添加的事件都没有了,DOM添加不会出现这种问题

    for(var i = 0;i<oLi.length;i++){
        oLi[i].onclick = function(){
            alert("我是个小可爱");
        }
    }
    
    //之前添加的问题:之前使用+=进行追加,后面的标签会将之前的覆盖,之前添加的事件都没有了
    oUl.innerHTML += "<li>小龙女</li>";
    
DOM添加节点
  • 追加:在父节点末尾追加

    • 父节点.appendChild(子节点)

      //2.1 追加:父节点.appendChild(子节点)   在父元素的末尾添加    
      var cLi = document.createElement("li");
      cLi.innerHTML = "小龙女";
      oUl.appendChild(cLi);
      oUl.appendChild(oLi[0]); //如果添加的是一个已经存在的标签,发生物理位移
      
  • 在某个元素之前插入

    • 父节点.insertBefore(newChild,refChild)

      //2.2 在某个元素之前插入: 父节点.insertBefore(newChild,refChild)
      var xLi = document.createElement("li");
      xLi.innerHTML = "项羽";
      oUl.insertBefore(xLi,oLi[1])
      

删除节点

  • 语法:

    • 删除元素本身:节点.remove() ----》ie8-不兼容

    • 删除子节点:父节点.removeChlid(子节点)

      //1.删除元素本身:节点.remove();   ie8不兼容
      oLis[3].remove();
      
      
      //2.删除子节点: 父节点.removeChild(子节点)
      oUl.removeChild(oLis[3]);
      

替换和复制

替换
  • 语法

    • 父节点.replaceChild(newChild,refChild)

      //1.替换 父节点.replaceChild(newChild,refChild)
      var cLi = document.createElement("li");
      cLi.innerHTML = "html";
      oUl.replaceChild(cLi,oLis[2]);
      
复制
  • 语法

    • 被复制的节点.cloneNode(boolean)

      //2.复制  被复制的节点.cloneNode(boolean)
      //默认是false:只复制标签不复制内容     true:复制标签和内容
      var cloneLi = oLis[0].cloneNode(true);
      oUl.appendChild(cloneLi);
      

DOM操作属性节点

  • 之前操作属性

    • 获取:var 变量 = 标签.属性名
    • 设置:标签.属性名 = 属性值
    • 特殊:标签.className = 属性值
  • DOM操作节点属性

    • 设置:节点.setAttribute(属性名,属性值)

    • 获取:节点.getAttribute(属性名)

    • 删除:节点.removeAttribute(属性名)

      //1.设置:节点.setAttribute(属性名,属性值)
      oDiv.setAttribute("id","active");
      
      //2.获取:节点.getAttribute(属性名)
      var c = oDiv.getAttribute("class");
      console.log(c); //active
      
      //3.删除:节点.removeAttribute(属性名)
      oDiv.removeAttribute("class");
      
      //4.区别
      console.log(oDiv.index);  //undefined  无法获取写在行间的自定义属性,只能获取在js里设置的自定义属性
      console.log(oDiv.getAttribute("index"));  //0  可以获取写在行间的自定义属性
      

快速获取表格元素

console.log(oTab.tHead); //thead 
console.log(oTab.tFoot); //tfoot 
console.log(oTab.tBodies[0]); //HTMLCollection [tbody] 
console.log(oTab.rows); //获取表格的行 HTMLCollection(4) [tr, tr, tr, tr] 
console.log(oTab.tBodies[0].rows); //tbody中行 HTMLCollection(3) [tr, tr, tr] 
console.log(oTab.rows[1].cells); //单元格必须通过行获取 HTMLCollection(4) [td, td, td, td]

BOM

BOM概念

  • BOM:Browser Object Model 浏览器对象模型

  • window和document的关系

    • window:js中最顶层的一个对象,窗口
    • document:文档(html)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYK5RV9K-1635473057003)(C:\Users\20199\Desktop\笔记\第二阶段\img\微信截图_20211011221204.png)]

window提供的方法

系统对话框
  • alert(message) : 警告框

  • confirm(“message”): 带确认的对话框

  • prompt(message,default) : 带输入的对话框

    //1.   alert(message) : 警告框
    alert("今天周一!!!");
    
    //2. confirm("message"): 带确认的对话框  确定---true  取消---false
    var s = confirm("明天听写吗?");
    console.log(s);
    
    //3. prompt(message,default) : 带输入的对话框   确定--输入的内容  取消--null 
    var text = prompt("请输入今天的作业个数",0);  
    console.log(text);
    
open与close
  • open()打开一个新窗口

    /*open写在行间,需要添加window
    open(url,target[_self,_blank],特殊字符串,是否取代当前窗口在浏览记录中的位置)
    返回新窗口的window*/
    <button onclick = "window.open('http://www.taobao.com')">taobao</button>
    <button onclick='fun()'>京东</button>
    <script>
        function fun(){
        var newWindow = open("http://www.jd.com","_blank","width:500px;height:500px");
        newWindow.alert("0824到处一游");
    }
    </script>
    
  • close()关闭当前窗口

    <button onclick="window.close()">关闭当前窗口</button>
    
loaction
  • location.href : 获取或设置当前窗口显示的url地址

  • location.search:获取url中搜索内容

    //1.location.href : 获取或设置当前窗口显示的url地址
    console.log(location.href);
    setTimeout(function(){
        //location.href = "http://www.baidu.com";
        // location.reload(); //重构 刷新
    },2000);
    
    
    //2.如何快速获取url中搜索内容
    console.log(location.search);
    
    //3.协议
    console.log(location.protocol);     
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BkcaO8L7-1635473057004)(C:\Users\20199\Desktop\笔记\第二阶段\img\微信截图_20211011221228.png)]

history

1—》2----》3

当前处于2的页面,history.forward():前进 就会去到 3

当前处于2的页面,history.back() : 后退 就会去到 1

history.go() : 跳转 ,正数,前进n级,负数,后退n级

  • history.forward():前进
  • history.back() : 后退
  • history.go() : 跳转

BOM事件

  • window.onload :

    // 加载事件:等文档和资源都加载完成后调用,保证代码执行的时候,标签加载完成
    window.onload = function () {
        //1.获取元素
        var oBtn = document.getElementsByTagName("button")[0];
        console.log(oBtn);
    
        //2.添加点击事件 
        oBtn.onclick = function () {
            alert("被点击了");
        }
    }
    
  • window.onresize

    //2.window.onresize : 窗口可视区大小发生变化时触发
    window.onresize = function(){
        console.log(document.documentElement.clientWidth);
    } 
    
  • window.onscroll

    //3.window.onscroll : 滚动条滚动事件
    window.onscroll = function(){
        console.log("滚");
    }
    
  • document.write()与innerHTML的区别

     <p>沉迷学习</p>
    <script>
    /* document.write():在页面输入流中写入数据,能识别标签,如果页面加载完成后写入数据会覆盖前面的内容,操作body内容
       document.innerHTML:能识别标签,会覆盖原有的内容,操作闭合标签内容
    */
    window.onload = function () {
         document.write("<p>日渐消瘦</p>");
     }
    </script>
    

BOM三大系列

获取元素在页面中的大小,位置信息,不设置

client系列
  • 获取元素的可视宽高

    • 元素.clientWidth :获取元素的可视宽,包括content+padding
    • 元素.clientHeight:获取元素的可视高,包括content+padding
  • 获取元素的边框

    • 元素.clientTop/Left : 获取元素的边框
  • 获取窗口的可视宽高

    • document.documentElement.clientWidth/Height
      • ​ 屏幕分辨率的高: window.screen.height
        ​ 屏幕分辨率的宽: window.screen.width
        ​ 屏幕可用工作区高度: window.screen.availHeight
        ​ 屏幕可用工作区宽度: window.screen.availWidth
    /*client:可视
        *获取元素的可视宽高:
    		元素.clientWidth : 获取元素的可视宽    content + padding
    		元素.clientHeight : 获取元素的可视高    content + padding
        *获取窗口的可视宽高:
    		document.documentElement.clientWidth / clientHeight
    	元素.clientTop:获取元素的上边框
    	元素.clientLeft:获取元素的左边框
    */
    //1.获取元素
    var oDiv = document.querySelector("div");
    
    //2.元素.clientWidth : 获取元素的可视宽
    var w = oDiv.clientWidth;
    console.log(w);  //120  content + padding
    
    //3元素.clientTop:获取元素的上边框
    console.log(oDiv.clientTop); //10
    
    //4.document.documentElement.clientWidth / clientHeight
    window.onresize = function(){
        console.log(document.documentElement.clientWidth);
    }
    
offset系列
  • 获取元素的占位宽高

    • 元素.offsetWidth:获取元素的占位宽,包括content+padding+border
    • 元素.offsetHeight:获取元素的占位高,包括content+padding+border
  • 获取元素的位置

    • 元素.offsetTop:获取当前元素的顶部到定位父元素的距离,如果没有定位父元素获取到body的距离
    • 元素.offsetLeft:获取当前元素的左边到定位父元素的距离,如果没有定位父元素获取到body的距离
    /*offset:
    	获取元素的占位宽高:
    		元素.offsetWidth:获取元素的占位宽   content+padding+border
    		元素.offsetHeight:获取元素的占位高   content+padding+border
    	获取元素的位置:(获取元素在页面中的位置)
    		元素.offsetTop:获取元素顶部到定位父元素的距离,如果没有定位父元素获取到body的距离
    		元素.offsetLeft:获取元素左边到定位父元素的距离,如果没有定位父元素获取到body的距离
    */
    //1.获取元素
    var oDiv = document.querySelector("div");
    var oP = document.querySelector("p");
    
    //2.元素.offsetWidth:获取元素的占位宽 content+padding+border
    console.log(oDiv.offsetWidth);  //140
    
    //3.元素.offsetTop:获取元素顶部到定位父元素的距离,如果没有定位父元素获取到body的距离
    console.log(oP.offsetTop); //120
    
scroll系列
  • 获取元素的实际内容宽高

    • 元素.scrollWidth/Height : 获取元素的实际内容宽高
  • 获取元素的滚动距离

    • 元素.scrollTop/Left:元素被卷去的宽高
  • 获取页面的滚动距离

    • document.documentElement.scrollTop||document.body.scrollTop
    //4. 获取页面的滚动距离:
    window.onscroll = function(){
        console.log(document.documentElement.scrollTop || document.body.scrollTop);
    }
    //可以设置滚动距离
    document.documentElement.scrollTop = 0;
    

懒加载

  • 懒加载原理

    • 先显示第一屏

      //1.显示第一屏
      //如果图片位置在  屏幕的可视区范围内就可以显示
      var cH = document.documentElement.clientHeight;
      for (var i = 0; i < oImgs.length; i++) {
          if (oImgs[i].offsetTop < cH) {
              oImgs[i].src = oImgs[i].getAttribute("_src");
          } else {
              break; //减少循环的次数  //i = 9;
          }
      }
      
    • 滚动到那显示到那

      //2.滚动到那,显示到那
      window.onscroll = function () {
          如果图片位置在  屏幕的可视区+被卷去高  范围内就可以显示
          var cH = document.documentElement.clientHeight;
          var sH = document.documentElement.scrollTop || document.body.scrollTop;
          for (var i = 0; i < oImgs.length; i++) {
              if (oImgs[i].offsetTop < cH + sH) {
                  oImgs[i].src = oImgs[i].getAttribute("_src");
              } else {
                  break; //减少循环的次数
              }
          }
      }
      

表单事件

快速获取表单元素

  • 快速获取表单元素 form.标签name属性

    //1.获取元素
    var oForm = document.getElementsByTagName("form")[0];
    
    //2.快速获取表单元素  form.标签name属性
    console.log(oForm.user);
    console.log(oForm.password);
    console.log(oForm.sex); //RadioNodeList(2) [input, input, value: "on"]
    console.log(oForm.sex.value);
    console.log(oForm.hobby);
    

表单事件

表单域事件
  • oForm.onsubmit : 提交表单的时候触发

    ​ return true : 默认 允许提交

    ​ return false:阻止提交

    //2.  oForm.onsubmit : 提交表单的时候触发
    oForm.onsubmit = function(){
        if(oForm.user.value == ""){
            alert("请输入内容");
            //阻止提交
            return false;
        }
    }
    
  • oForm.onreset : 重置表单的时候触发

    ​ return true : 默认 允许重置

    ​ return false:阻止重置

    //3.oForm.onreset : 重置表单的时候触发
    oForm.onreset = function(){
        //带确认的对话框,确定--true   取消---false
        var s = confirm("是否需要重置");
        if(s == true){
            return true;
        }else{
            return false;
        }
    }
    
表单元素事件
  • input.onblur : 失去焦点时触发

  • input.onfocus : 获取焦点时触发

    //4.input.onfocus : 获取焦点时触发
    oForm.user.onfocus = function(){
        this.style.background = "green";
    }
    //5.input.onblur : 失去焦点时触发
    oForm.user.onblur = function(){
        this.style.background = "red";
    }
    
  • input.oninput : 内容发生变化时触发 / ie: input.onpropertychange

    //6. input.oninput : 内容发生变化时触发
    /*oForm.user.oninput = function(){ //标准
        console.log(this.value);
    }
    oForm.user.onpropertychange = function(){ //ie
        console.log(this.value); 
    }*/
    oForm.user.oninput = change;
    oForm.user.onpropertychange = change; 
    function change(){
        console.log(this.value);
    }
    
  • input.onchange : 失去焦点时内容和上一次相比发生变化时触发

    //7.input.onchange : 失去焦点时内容发生变化时触发
    oForm.user.onchange = function(){
        console.log(this.value);
    }
    
  • input.focus:自动获取焦点

事件高级

事件对象

事件对象evenet
  • 名词解析

    • 事件处理函数:事件发生时调用的函数 document.onclick = function(){ 事件处理函数 }
    • 事件对象event:事件处理函数中,一个特殊的对象,事件发生的时候会将所有和时间相关的信息存储在事件对象中
  • 事件对象

    • 标准浏览器(ie无兼容):window.event,可以省略window

    • 火狐浏览器:作为事件处理函数的第一个参数传入

      document.onclick = function(eve){  //火狐浏览:事件发生的时候,事件对象通过事件处理函数的第一个参数传入
          //事件对象window.event,window可以省略
          console.log(event);
      
          //低版本火狐浏览,不能省略window,必须写成window.event,不报错,但是结果undefined
          console.log(window.event);
      
          //火狐浏览:事件发生的时候,事件对象通过事件处理函数的第一个参数传入
          console.log(eve);
      
          //兼容
          var ev = window.event || eve;
          console.log(ev);
      }
      
  • 事件对象属性

    • type:事件类型

    • clientX,clientY:鼠标位置,相对于屏幕可视区

    • target||srcElement:事件目标

    • ctrKey,altKey,shiftKey:事件发生的时候有没有按住这个键,按了true,没按false

      document.onclick = function(eve){
          //1.获取事件对象
          var ev = window.event || eve; 
      
          //2.事件对象的属性
          console.log(ev.type); //事件类型 click
          console.log(ev.clientX +"------" + ev.clientY);  //鼠标位置  相对于屏幕
          console.log(ev.target); //事件目标
          console.log(ev.ctrlKey,ev.shiftKey,ev.altKey); //事件发生的时候有没有按住这个键,按了true,没按false
      }
      

事件的绑定与取消

事件绑定
之前添加事件
  • 语法:标签.事件名 = function(){}

  • 问题:给同一个标签添加相同事件,会覆盖

    //1.获取元素
    var oDiv = document.querySelector("div");
    
    //2.之前添加事件 :  标签.事件名 = function(){}
    //问题:如果给同一个标签添加相同的事件,后面的会覆盖前面
    oDiv.onclick = function(){
        oDiv.style.width = "100px";
    }
    oDiv.onclick = function(){ //只有这个有效
        oDiv.style.background = "pink";
    }
    
事件绑定添加
  • 语法

    标准浏览器:标签.addEventListener(事件类型[不加on],事件处理函数,是否捕获)
    IE了浏览器:标签.attachEvent(事件类型[加on],事件处理函数)
    区别:
    	标准:
        	事件类型不加on
            有捕获
            this指触发事件的对象
            相同事件正序触发
        IE:
        	事件类型加on
            没有捕获
            this指window
            相同事件逆序触发
    
  • 例:

    //3.1 标准浏览器:标签.addEventListener(事件类型[不加on],事件处理函数,是否捕获)
    oDiv.addEventListener("click", fun1);
    oDiv.addEventListener("click", fun2);
    
    
    //3.2 IE浏览器:标签.attachEvent(事件类型[加on],事件处理函数)
    oDiv.attachEvent("onclick", fun1);
    oDiv.attachEvent("onclick", fun2);
    
    
    //3.3 兼容
    if (oDiv.addEventListener) {
        oDiv.addEventListener("click", fun1);
    } else {
        oDiv.attachEvent("onclick", fun1);
    }
    
  • 好处:给一个标签加多个相同事件会叠加执行,不会覆盖

事件取消
  • 不同的添加方式,需要不同的取消方式

    事件绑定方式事件取消方式
    标签.事件标签.事件 = null
    标签.addEventListener(事件类型,事件处理函数)标签.removeEventListener(事件类型,事件处理函数)
    标+签.attachEvent(事件类型(加on),事件处理函数)标签.detachEvent(事件类型(加on),事件处理函数)
  • 例:

    • 普通取消

      //1.普通添加事件的取消
      oBtn.onclick = function () {
          console.log(arr[Math.floor(Math.random() * arr.length)]);
          //取消事件
          oBtn.onclick = null;
      }
      
    • 绑定取消

      function fun() {
          console.log(arr[Math.floor(Math.random() * arr.length)]);
          //取消绑定事件
          //oBtn.removeEventListener("click",fun);    标准浏览器
          // oBtn.detachEvent("onclick",fun);        IE浏览器
          if (oBtn.removeEventListener) {
              oBtn.removeEventListener("click", fun);
          } else {
              oBtn.detachEvent("onclick", fun);
          }
      }
      
      //绑定事件
      if (oBtn.addEventListener) {
          oBtn.addEventListener("click", fun);
      } else {
          oBtn.attachEvent("onclick", fun);
      }
      
DOM事件流
DOM事件流
  • DOM事件流:事件发生时的执行过程

    • 事件捕获机制:事件发生的时候,从window开始捕获事件,依次往子元素捕获,直到找到事件目标为止

    • 事件冒泡机制:事件目标处理事件,将事件依次传递给父元素,如果父元素有对应事件,也会触发,一直传递到window

    • 默认是事件冒泡

       //1.获取元素
      var oDiv = document.getElementsByTagName("div");
      
      //2.添加点击事件
      function fun(){
          alert(this.id);
      }
      // oDiv[0].onclick = fun;  默认是冒泡,点击div2,会触发div2 div1 div0的事件
      // oDiv[1].onclick = fun;
      // oDiv[2].onclick = fun;
      
      
      //3.标签.addEventListener("事件类型",事件处理函数,是否捕获)
      //默认是false:冒泡    true:捕获  
      oDiv[0].addEventListener("click",fun,true);
      oDiv[1].addEventListener("click",fun,true);
      oDiv[2].addEventListener("click",fun,true);
      
阻止事件冒泡
  • even.stopPropagation?even.stopPropagation():even.cancelBubble = true;

  • 事件冒泡有时候会影响到代码的正常功能,可以阻止

  • 语法

    标准浏览器:even.stopPropagation();
    ID浏览器:even.cancelBubble = true;
    
  •  oDiv[2].onclick = function(eve){
         var ev = window.event || eve;
         // ev.stopPropagation();  标准浏览器
         // ev.cancelBubble = true;  IE浏览器
         ev.stopPropagation ? ev.stopPropagation():ev.cancelBubble = true;
         alert("我是最小的");
     }
    
阻止默认行为
  • 默认行为

    • 默认行为:浏览器赋予某个标签,某个操作的默认功能

    • 例如:a的跳转,form中button默认提交,右击显示菜单,拖拽图片保存,双击默认选中文字

      <a href="http://www.baidu.com">百度</a>
      <form action="">
          <input type="text" name="user">
          <button>按钮</button>
      </form>
      <p>fdsfdsf</p>
      
  • 阻止默认行为(可以直接使用||兼容)

    添加事件的方式阻止默认行为的方式
    标签.事件return false
    标签.addEventListener()event.preventDefault()
    标签.attachEvent()event.returnValue = false
    • 标签.事件 阻止默认行为

      var oA = document.getElementsByTagName("a")[0];
      //1.普通事件阻止
      oA.onclick = function(){
          return false;
      }
      
    • 事件绑定阻止默认行为

      //2.绑定事件阻止
      bind(oA,"click",function(eve){
          var ev = window.event || eve;
          //阻止默认行为:
          ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;            
      })
      

事件代理(事件委托)

  • 事件代理:把事件添加给父元素(通过事件冒泡,子元素触发事件也能触发父元素),找到具体发生事件子元素,由子元素去处理事件

  • 优点:提高性能,事件可以发生在未来

    var oUl = document.getElementsByTagName("ul")[0];
    
    //1.将事件添加给父元素(事件冒泡)
    oUl.onclick = function (eve) {
        var ev = window.event || eve;
        //2.事件发生的时候,找到具体的子元素
        var target = ev.target || ev.scrElement;
        //确定是代理
        if (target.nodeName == "LI") {
            //3.子元素处理事件
            target.style.background = "teal";
        }
    }
    
    //事件可以发生在未来
    oUl.innerHTML += "<li>7777</li>";
    

键盘事件

  • onkeydown:按键按下 不区分大小写,获取到的大写编码

  • onkeyup:按键抬起

  • onkeypress:按键按下,区分大小写

    document.onkeydown = function (eve) {
        var ev = window.event || ev;
        console.log(ev.key); //IE获取不到值
        console.log(ev.keyCode);//不区分大小写,获取到的大写编码   "0" -- 48  "A"--65  "a"--97    
        console.log(ev.shiftKey, ev.ctrlKey, ev.altKey); //是否按住了这个键,按了true  
    
        //按ctrl+c打印复制
        if (ev.ctrlKey ==  true && ev.keyCode == 67) { 
            console.log("复制");
        }
    }
    
  • 获取按键编码:ev.keyCode ie不支持ev.key,所以使用ev.keyCode

滚轮事件

  • 语法

    标准、IE:onmousewheel
    	获取滚动方向  event.wheelDelta  120:上   -120:下
    火狐:必须是用事件绑定   标签.addEventListener("DOMMouseScroll")
    	获取滚动方法 event.detail     -3:3:下
    
  • 添加

     var oDiv = document.querySelector("div");
    
    //1.标准、IE: onmousewheel
    oDiv.onmousewheel = scroll;
    
    //2. ff:必须是用事件绑定   标签.addEventListener("DOMMouseScroll")
    if (oDiv.addEventListener) {
        oDiv.addEventListener("DOMMouseScroll",scroll);
    }
    
    
    //3.滚动函数
    function scroll(ev){
        var ev = window.event || ev;
    
        //4.获取滚动方向
        // console.log(ev.wheelDelta);  //标准、IE   120:上   -120:下
        // console.log(ev.detail); //ff   -3:上   3:下
    
        var tag = true; //true---上  false:下
        if(ev.wheelDelta){
            tag = ev.wheelDelta > 0 ? true : false;
        }else{
            tag = ev.detail > 0 ? false : true;
        }
    
        if(tag == true){
            console.log("上");
        }else{
            console.log("下");
        }
    
    }
    
  • 封装

    function wheel(elemObj, unFun, downFun) {
        //1.添加滚轮事件  标准浏览器、IE:onmousewheel
        elemObj.onmousewheel = scroll;
    
        //1.添加滚轮事件 火狐浏览器:必须使用事件绑定添加,事件名称-->DOMMouseScroll
        if (elemObj.addEventListener) {
            elemObj.addEventListener("DOMMouseScroll", scroll);
        }
    
        //2.事件处理函数
        function scroll(eve) {
            var ev = window.event || eve;
    
            //4.判断方向
            var tag = true; //true---上    false---下
            if (ev.wheelDelta) { //如果是标准浏览器
                tag = ev.wheelDelta > 0 ? true : false;
            } else { //ff  undefined
                tag = ev.detail < 0 ? true : false;
            }
    
            //5.确定方向
            if (tag) {
                unFun();
            } else {
                downFun();
            }
        }
    
    }
    

## IE全局捕获和释放

全局捕获:setCapture

  • 语法:
    • 标签.setCapture&&setCapture() &&短路运算,判断setCapture为真后执行方法

释放:releaseCapture

  • 语法:
    • 标签.releaseCapture&&releaseCapture() &&短路运算,判断releaseCapture为真后执行方法

函数高级

1.函数分类

  • 函数:function

  • 普通函数

    普通函数:
    function 函数名(){  函数体 }
    
    表达式函数
    var 变量 = function (){ 表达式函数 }
    
    
    事件处理函数
    document.onclick = function(){  事件处理函数  }
    

2.回调函数 callback

  • 概念:将函数作为参数传递给其他函数调用,这就叫回调函数

  • 回调函数调用:等某个动作或某个行为完成后调用

    //1.回调函数
    setTimeout(function(){
        console.log("回调函数");
    },1000);
    
    
    //2.回调函数
    function getData(showData){
    
        console.log("开始请求数据");
        for(var i = 0;i<10;i++){
            console.log("...");
        }
        console.log("数据请求成功");
    
        //显示数据 回调
        showData();
    }
    
    function getShowData(){
        console.log("显示数据");
    }
    getData(getShowData);
    

3.匿名函数-立即执行函数(IIFE)

  • 匿名函数:没有名字的函数

  • 表示方式

    //1.匿名函数--没有名字的函数
    function (){
        console.log("匿名函数");
    }
    
  • 匿名函数自执行-立即执行函数(IIFE)

    //2.匿名函数自执行(立即执行函数 IIFE)   
    //语法 :(函数声明)(函数调用)
    (function(){
        console.log("匿名函数自执行");
    })();
    
    //3.使用立即执行函数
    var s = (function(a,b){ //形参
        console.log(a+b);
        return a*b;
    })(10,20); //实参
    
    console.log(s); //200
    
  • 好处和使用场景

    好处:避免全局污染(声明了大量的全局变量,可以随意修改),节约内存
    	完美嵌入代码
    使用场景:外部封装的js文件中
    	    在已有的项目文件中快速添加功能
    		闭包
    
  • 注意:一般会在匿名函数前面加一个分号

    ;()()
    

4.闭包函数(Closure)

  • 概念:能够访问其他函数内部变量的函数 (函数套函数,内部函数可以访问外部函数变量)
  • 特性:延伸变量的使用范围,闭包中使用的变量会一直存储在内存中,类似全局变量,避免全局污染
  • 缺点:大量使用闭包,可以造成内存泄漏,闭包不用的时候释放内存
4.1 基础闭包
  • 普通函数

    //1.普通函数
    function fun(){
        var c = 10;
        console.log(c++);
    }
    // console.log(c);  is not defined  局部变量出了函数括号就会被销毁
    fun(); // 10
    fun(); // 10
    
  • 普通闭包

    //2.闭包:函数套函数  内部函数访问外部函数变量
    function outer1(){
        var a = 10;
        function inner1(){
            console.log(a++); //作用域链,依次往父级作用域查找
        }
        inner1();
    }
    outer1();
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2qDGFGIl-1635473057004)(C:\Users\20199\Desktop\笔记\第二阶段\img\闭包.png)]

  • 经典闭包

    //3.经典的闭包:内部函数访问外部函数变量,返回内部函数
    function outer2(){
        var a = 10;
        return function (){
            console.log(a++);
        }
    }
    var inner2 = outer2(); //inner2 = function (){  console.log(a++);}
    inner2(); //10
    inner2(); //11 闭包中使用的变量会一直存储在内存中,类似全局变量
    
    
    //多次闭包之间,没有关联
    var inner3 = outer2(); 
    inner3(); //10
    inner3 = null; //释放掉闭包
    
4.2 闭包的使用场景
4.2.1 访问其他函数内部的变量(避免全局污染)
  • 访问其他函数内部变量的时候

    //1.访问其他函数内部变量的时候
    function outer2() {
        var a = 10;
        return function () {
            console.log(a++);
        }
    }
    var inner2 = outer2();
    
4.2.2 解决全局作用域问题
  • 代码执行后的结果是?

    //代码执行后的结果是?怎么修改?
    var arr = [];
    for (var i = 0; i < 10; i++) {
        arr.push(function () {
            console.log(i);
        })
    }
    //[fun,fun,fun,fun,fun,fun,fun,fun,fun,fun];
    //                 arr[5] = function(){ console.log(i)}
    //                 arr[5]()  调用函数
    arr[5](); //10
    
  • 怎么修改

    • 问题:为什么是10

    • 原因:循环添加到数组时,函数不会调用,等循环结束后调用函数,打印i,这个时候全局变量i已经结束循环,所以结果为10

    • 解决:让i变成局部变量,每个函数使用自己的变量i

      var arr = [];
      for(var i=0 ;i<10 ;i++){
          (function(i){  //var i;局部变量i,闭包中i会一直存储在内存中
              arr.push(function(){
                  console.log(i)
              })
          })(i);
      }
      
      arr[5]; //10
      
4.2.3 模拟私有属性
  • 私有属性:外界不可见,但是可以通过方法访问和修改

  • 闭包模拟私有属性

    //1.私有属性,外界不可见,可以获取,可以设置
    function student(){
        var name="苗苗";
        
        return {
            "setName":function(n){
                //设置name
                name = n;
             },
            "getName":function(){
                    //获取name
                    return name;
            }
        }
    }
    
    var s = new student();
    console.log(s);
    
    //获取name
    console.log(s,getName());  //苗苗
    
    //设置name
    s.setName("芳芳");
    console.log(s.getName());  //芳芳
    
4.2.4 防抖和节流
闭包面试题
//1.代码执行后结果
for(var i = 0;i<5;i++){
    setTimeout(function(){
        console.log(new Date(),i);
    },1000);
}
console.log(new Date(),i);


//2.使用闭包模拟私有属性
 function Student(){
     var name = "苗苗";

     return {
         "setName":function(n){
             //设置name
             name = n;
         },
         "getName":function(){
             //获取name
             return name;
         }
     }
 }


//3.代码执行后的结果是?
function fun(n, o) { 
    console.log(o);
    return {
        "fun": function (m) {
            return fun(m, n);
        }
    }
}
var a = fun(0)
a.fun(1);
a.fun(2);
a.fun(3);


//4.代码执行后的结果是?怎么修改?
var arr = [];
for (var i = 0; i < 10; i++) {
    arr.push(function () {
        console.log(i);
    })
}
arr[5]();  //10

//修改
for (var i = 0; i < 10; i++) {
    (function (i) { //var i;
        arr1.push(function () {
            console.log(i);
        })
    })(i);
}

5 递归函数

  • 递归函数:函数内部调用函数本身
  • 和循环的区别:循环无线执行会变成死循环,卡死,递归有最大堆栈调用次数,超过会报错
5.1 阶乘递归
  • 递归的实现过程

    • 找规律

    • 递:函数内部调用函数本身

    • 归:在函数的开头,结束递归的执行

      //1.先找规律
      //6! 阶乘  6*5*4*3*2*1
      //6!  6 * 5!
      //5!  5 * 4!
      //4!  4 * 3!
      //n! = n * (n-1)
      
      
      //2.递://超出最大调用堆栈大小
      // function jc(n) {  
      //     return n * jc(n-1);
      // }
      // jc(6);
      
      
      //3.归(一定要结束)
      function jc(n){
          //归:一定是函数的开头
          if(n == 1) return 1
          //递
          return n * jc(n-1);
          //     return n * jc(n-1);
          //            // 6 * jc(5)  6*5*4*3*2*1
          //                   //5 * jc(4)  5*4*3*2*1
          //                         //4 * jc(3)  4*3*2*1
          //                               //3 * jc(2) 3*2*1
          //                                     //2 * jc(1)  1
          //                                            //1
      }
      console.log(jc(10));
      
5.2 斐波那契数列
  • 数列特点:1,1,2,3,5,8,13,21,34 。。。

  • 数列规律:f(n) = f(n-1) + f(n-2)

    //1.找规律  1 1 2 3 5 8 13 21 34
    //f(6) = f(5) + f(4)
    //f(5) = f(4) + f(3)
    
    //2.递
    // function rabbit(n){
    //     return rabbit(n-1) + rabbit(n-2);
    // }
    // console.log(rabbit(6)); //8
    
    
    //3.归
    function rabbit(n){
        if(n == 1 || n == 2) return 1;
        return rabbit(n-1) + rabbit(n-2);
    }
    console.log(rabbit(6)); //8
    console.log(rabbit(9)); //34
    
5.3 快速排序
  • 实现思路

    arr.length <=1   return arr;
       var arr = [2,7,1,5,4,6,8]
    1.获取数组中间的元素 (从数组中将中间元素删除)
      var middle = arr.aplice(arr.length/2,1)[0];
    2.创建两个空数组,left,right
    3.循环数组和中间值进行比较,比中间值小的放left,比中间值大的放后面
      middle = 5  left = [2,1,4]   right = [7,6,8]
    4.组合
      return quick(left).concat(middle,quick(right))
    
  • 代码实现

    function quick(arr){
        //5.结束递归的条件
        if(arr.length<=1){return arr;}
        //1.找中间值(删除中间值,并接收)
        var middle = arr.splice(Math.floor(arr.length / 2),1)[0];
        
        //2.创建两个空数组
        var left=[];
        var right=[];
        
        //3.循环数组和中间值进行比较,比中间值小的放前面,大的放后面
        for(var i=0;i<arr.length;i++){
            arr[i] < middle ? left.push(arr[i]) : right.push(arr[i]);
        }
        
        //4.组合
        return quick(left).concat(middle,quick(right));
    }
    
    console.log(quick(arr));
    

6 防抖节流函数

  • 用于代码优化
6.1 事件频率
  • 有些事情,一触发就会触发非常多次,可能会影响性能

    //1.滚动事件
    window.onscroll = function(){
        console.log("滚动");
    }
    
    //2.移动事件
    document.onmousemove = function(){
        console.log("移动");
    }
    
    var oIn = document.querySelector("input");
    //3.实时输入
    oIn.oninput = function(){
        console.log(this.value);
    }
    
6.2 防抖(debounce)
  • 防抖:如果在一定时间范围内,多次触发时间,只处理一次

  • 目的:控制触发频率

  • 原理:开启一个定时器,延迟某个时间执行,如果在这个时间内,再次触发时间,重新计数

  • 基础实现

     //2.鼠标移动,内容++
    oDiv.onmousemove = fun;  //事件发生,不立刻处理事件,而是去开启一个定时器
    
    function show(){
        oDiv.innerHTML ++;
    }
    
    //事件发生的时候,开启定时器等待,如果在等待过程中,又有对应事件的发生,重新计数
    var timer;
    function fun(){
        //第一次没有值undefined ,第二次触发timer有值,说明之前已经有事件触发了,现在是等待事件
        if(timer){
            clearInterval(timer);
        }
        timer = setTimeout(show,100);
    }
    
    
  • 封装

    //封装防抖函数
    function debounce(fun,wait){
        var timer;  //会一直存储,不会被随意修改
        return function(){
            if(timer){  //如果有值,说明之前已经触发了时间,并且正在等待
                setTimeout(timer);  //清除当前定时器,重新计数
            }
            timer = setTimeout(fun,wait);  //开启定时器等待
        }
    }
    
  • 节流

    function throttle(fun, wait) {
        var timer;  //开   timer=undefined
        return function () {
            if (!timer) { //判断timer是否有值(当前是否已经开启了定时器) ,
                timer = setTimeout(function () { //关
                    fun();
                    timer = undefined; //开
                }, wait)
            }
        }     
    }
    

面向对象

1 概念

  • 编程思维:

    • 面向过程:注重的是实现过程(怎么做,蛋炒饭:准备材料,起锅烧油,下鸡蛋,翻炒,下米饭,翻炒,放配料,出锅装盘) c,c++
    • 面向对象:注重的是结果(由谁做,蛋炒饭,点外卖,找妈妈,找对象) java
  • 对象三大基本特征

    • 封装
    • 继承
    • 多态
  • 对象的组成

    • 属性:静态的名词性的 ----- var
    • 方法:动态的,行为 ------ function
  • 类(对象):大的类型,抽象的类型

  • 实例对象:具体的实际的 (人–张三)

2 面向对象的创建

2.1 字面量创建
  • 创建方式

    //1.字面量创建
    var obj1 = {
        //属性
        "sex":"女",
        age:18, //引号可以省略
        "height":165,
        "weight":"110kg",
    
        //方法
        "skill":function(){
            console.log("敲代码");
        },
        "eat":function(){
            console.log("一顿吃三个小孩");
        }
    }
    //获取属性
    console.log(obj1.height);
    //调用方法
    obj1.eat();
    
  • 问题:代码冗余,比较直观,适合创建单个对象

2.2 实例创建(单例创建)
  • 创建方式

    //2.实例创建(单例创建)
    var obj1 = new Object();
    
    //添加属性
    obj1.height = "2m";
    obj1.weight = "90kg";
    obj1.city = "北京";
    obj1.job = "CEO";
    
    //添加方法
    obj1.skill = function () {
        console.log("会玩智能手机");
    }
    console.log(obj1);
    
  • 问题:代码冗余

2.3 工厂模式创建
  • 创建方式

     //3.工厂模式创建(封装)
    function createObj(name,age,sex){
        //1.声明对象
        var obj = new Object();
    
        //2.添加属性
        obj.name = name;
        obj.age = age;
        obj.sex = sex;
    
        //3.添加方法
        obj.skill = function(){
            console.log("有车有房有存款");
        }
    
        //4.返回创建好的对象
        return obj;
    }
    var obj1 = createObj("西施",800,"男");
    var obj2 = createObj("貂蝉",18,"女");
    console.log(obj1,typeof obj1); //{name: "西施", age: 800, sex: "男", skill: ƒ} "object"
    
  • 问题:解决代码冗余

     var obj1 = createObj("西施",800,"男");
    var obj2 = createObj("貂蝉",18,"女");
    console.log(obj1,typeof obj1); //{name: "西施", age: 800, sex: "男", skill: ƒ} "object"
    console.log(obj2,typeof obj2);
    
    
    //问题:解决代码冗余的问题,类型识别不明
    var obj3 = createObj("旺财",2,"女");
    console.log(obj3,typeof obj3); //{name: "旺财", age: 2, sex: "女", skill: ƒ} "object"
    console.log(obj3 instanceof Object); //true 实例是否由后面的对象创建
    
    
2.4 构造函数创建
  • 构造函数:还是函数,用于构造对象

  • 特点

     1.构造函数名首字母大写 (为了区分普通函数)
     2.不需要创建空对象,不需要返回对象,直接在this上添加属性和方法
     3.构造函数调用前面必须加new,不加new就跟普通函数一样
    
  • 创建方式

     //1.声明构造函数
    function Student(name,age,sex){
        //添加属性
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.class = "0824";
    
        //添加方法
        this.study = function(){
            console.log("good good study,day day up!!!");
        }
    }
    
    //2.实例化对象
    var s1 = new Student("邱明雨",18,"女");  
    console.log(s1);  //Student {name: "邱明雨", age: 18, sex: "女", study: ƒ}
    console.log(s1 instanceof Student); //true;
    
  • new 操作符的作用

    • 隐式的创建了一个空对象,让this指向这个空对象

    • 执行构造函数中的代码

    • 让实例对象的__proto__指向构造函数的prototype

    • 隐式的返回创建好的对象

       //1.声明构造函数
      function Person(name,age){
          //a.隐式的创建了一个空对象,让this指向这个空对象  this =  new Object
          //b.执行构造函数中的代码
          //添加属性
          this.name = name;
          this.age = age;
      
          //添加方法
          this.play = function(){
              console.log("吃、喝、玩、乐");
          }
      
          //c.隐式的返回创建好的对象  return this
      }
      
      //2.实例化对象  new
      var p1 = new Person("武则天",800);
      console.log(p1);
      
      var p2 = Person("武则天",800);
      console.log(p2); //undefined
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MxJXUS7-1635473057005)(./img/new操作符.png)]

  • 问题:解决代码冗余,识别的问题,浪费内存

     //2.实例化对象
    var s1 = new Student("邱明雨",18,"女");  
    console.log(s1);  //Student {name: "邱明雨", age: 18, sex: "女", class: "0824,study: ƒ}
    console.log(s1 instanceof Student); //true;
    
    var s2 = new Student("玉兔精",1999,"女");
    console.log(s2); //Student {name: "玉兔精", age: 1999, sex: "女", class: "0824", study: ƒ}
    
    //问题:解决代码冗余,解决识别的问题,浪费内存   方法一样,每次创建都会每个对象都会存储一份
    console.log(s1.study == s2.study); //false
    
2.5 原型创建
1).原型对象与原型属性
  • 原型对象:prototype,函数声明时自动创建的一个共享区域,用于存储公共的共享属性和方法

  • 原型属性:_proto_,实例化对象时自动添加的属性,指向构造的prototype

    //1.原型:prototype,函数声明时自动创建的一个共享区域,用于存储公共的共享属性和方法
    function sum() { }
    console.dir(sum);
    console.dir(Array);
    
    
    
    //2.原型属性:__proto__,实例化对象时自动添加的属性,指向构造的prototype
    var arr = new Array("1","2","3","4");
    console.log(arr);
    
    console.log(Array.prototype);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, …]
    console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ,…]
    console.log(arr.__proto__ === Array.prototype); //true
    console.log(arr.__proto__ === Array.prototype); //true
    
2).原型创建
  • 创建方式

    //1.声明构造函数
    function Student(){};
    
    //2.在原型上添加属性和方法
    Student.prototype.name = "吴亦凡";
    Student.prototype.class = "0824";
    Student.prototype.study = function(){
        console.log("好好改造,重新做人");
    }
    
    
    //3.实例化对象
    var s1 = new Student();
    console.log(s1);
    //原型链:查找方式,先找实例本身,没有找__proto__(prototype)
    console.log(s1.name); //吴亦凡  
    
    var s2 = new Student();
    console.log(s2);
    console.log(s1.study == s2.study); //true
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q1Hx9go3-1635473057006)(./img/原型.png)]

  • 问题:不能传参,创建的都是同一个对象

    var s1 = new Student();
    //原型链:查找方式,先找实例本身,没有找__proto__(prototype)
    console.log(s1.name); //吴亦凡  
    
    var s2 = new Student();
    console.log(s2.name); //吴亦凡
    console.log(s1.study == s2.study); //true
    
2.6 混合创建
  • 构造函数 + 原型

    //1.声明构造函数(可变的属性和方法)
    function Student(name,age,sex,ski){
        //添加属性
        this.name = name;
        this.age = age;
        this.sex = sex;
        //添加方法
        this.skill = function(){
            console.log(ski);
        }
    }
    
    //2.原型(共享不变属性和方法)
    Student.prototype.class = "0824";
    Student.prototype.study = function(){
        console.log("敲代码,拿高薪");
    }
    	
    
    //3.实例化对象
    var s1 = new Student("苗苗",18,"女","一秒30行");
    console.log(s1);
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWYM32FY-1635473057006)(./img/混合创建.png)]

  • 问题:破坏了封装性

2.7 动态混合创建
  • 创建方式

     //1.声明构造函数(可变的属性和方法)
    function Student(name, age, sex, ski) {
        //添加属性
        this.name = name;
        this.age = age;
        this.sex = sex;
        //添加方法
        this.skill = function () {
            console.log(ski);
        }
    
        //动态混合
        if (typeof this.study != "function") {
            //2.原型(共享不变属性和方法)
            Student.prototype.class = "0824";
            Student.prototype.study = function () {
                console.log("敲代码,拿高薪");
            }
        }
    }
    

3 面向对象实例

  • 面向对象实例

    • 声明构造函数

    • 添加属性 – 变量(全局,函数中变量还会在其他地方使用)

    • 添加方法-- 行为

       function TabSwitch(id) {
           // this =  new TabSwitch();
           //1.添加属性 -- 变量(全局,函数中变量还会在其他地方使用)
           this.oDiv = document.getElementById(id);
           this.menuBtn = this.oDiv.getElementsByTagName("button");
           this.itemDiv = this.oDiv.getElementsByTagName("div");
           this.index = 0;
           var that = this; //存储一份正确的this执行
      
           //2.添加方法
           //入口方法
           this.init = function () {
               for (var i = 0; i < this.menuBtn.length; i++) {
                   this.menuBtn[i].index = i;
                   this.menuBtn[i].onclick = function () {
                       //this ---button  事件处理函数中指触发事件的对象
                       //点击改变下标
                       that.index = this.index;
                       //调用切换模块的方法
                       that.changeItem();
                   }
               }
           }
      
           //入口方法自己调用
           this.init();
      
           //3.切换模块方法
           // this.changeItem = function () {
           //     for (var j = 0; j < this.itemDiv.length; j++) {
           //         this.itemDiv[j].style.display = "none";
           //     }
           //     this.itemDiv[this.index].style.display = "block";
           // }
       }
      TabSwitch.prototype.changeItem = function () {
          for (var j = 0; j < this.itemDiv.length; j++) {
              this.itemDiv[j].style.display = "none";
          }
          this.itemDiv[this.index].style.display = "block";
      }
      

4.call与apply

4.1 作用及语法
  • 作用:改变this指向

    普通函数this ----> window
    事件处理函数中this ----> 事件触发的对象
    对象方法中this ----> 当前对象
    构造函数中this ----> 实例对象
    
  • 语法

    • 函数名.call(thisArg,参数1,参数2…)

      //1.call: sum.call(thisArg,参数1,参数2,参数3...);
      function sum(a,b){
          console.log(this,a+b);
      }
      sum(10,20);
      //使用
      sum.call(document.body,100,200);//<body></body>  300
      sum.call(1,10,20); //Number {1} 30
      
    • 函数名.apply(thisArg,[参数1,参数2…])

      //1.call: sum.call(thisArg,[参数1,参数2....]);
      function sum(a,b){
          console.log(this,a+b);
      }
      sum(10,20);
      //使用
      //2.apply:sum.apply(thisArg,[参数1,参数2....]);
      sum.apply(document,[30,40]); //#document,70
      
      
  • call与apply的作用及区别?

    • 都是用于改变this的指向
    • apply参数需要放在数组中进行传递
4.2 练习及使用
  • 练习

    //3.练习
    var name = "小花";
    var obj1 = {
        "name":"小红",
        "toString":function(){
            console.log("我的名字是:"+this.name);
        }
    }
    var obj2 = {
        "name":"小明"
    }
    obj1.toString.call(obj2); //小明
    var to = obj1.toString;
    to(); //小花
    
  • 使用

    //4.使用技巧
    var arr = [5,8,2,9,4,7,6];
    console.log(Math.max.apply(1,arr)); //9
    console.log(Math.min.apply(1,arr)); //2
    
    //5.toString()
    var arr = [1,2];
    console.log(arr.toString()); //将数组转换为字符串,去掉外面的【】加引号
    
    //对象的toString方法,用于获取数据的具体的数据类型
    var obj = {"name":"web"};
    console.log(1,obj.toString()); // "[object Object]"
    console.log(obj.toString.call(arr).slice(8,-1)); //[object Array]
    console.log(obj.toString.call(1).slice(8,-1)); //[object Number]
    console.log(Object.prototype.toString.call(function(){})); //[object Function]
    

5.继承

  • 子类继承父类的属性和方法,子类可以添加属于自己的属性和方法
5.1 原型链继承
  • 继承方式:子类的原型 = 父类的实例

    //1.父类型(基本)
    function Student(classN,name,age,sk){
        this.classN = classN;
        this.name = name;
        this.age = age;
        this.course = ["语文","数学","英语"];
    
        this.skill = function(){
            console.log("我有"+sk+"能力");
        }
    }
    Student.prototype.study = function(){
        console.log("好好学习,天天向上");
    }
    
    
    //2.子类型(派生类)
    function SmallStudent(){
        this.findMaMa = function(){
            console.log("找妈妈");
        }
    }
    
    //3.继承的行为:原型链继承 子类的原型对象 = 父类的实例对象
    SmallStudent.prototype = new Student("007","小红",7,"打王者");
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6sIVARAK-1635473057007)(./img/原型链继承.png)]

  • 问题:不能传参,一改全改

    var ss1 = new SmallStudent();
    console.log(ss1);
    //原型链:查找机制,先实例本身,没有找实例__proto__(prototype),父类实例,父类实例的__proto__(父类的prototype).. Object
    console.log(ss1.name); //小红
    ss1.course.push("政治");
    console.log(ss1.course); //["语文", "数学", "英语", "政治"]
    ss1.study();
    
    
    //问题1:子类不能传参
    var ss2 = new SmallStudent();
    console.log(ss2.name); //小红
    //问题2:如果继承到引用数据类型,会一改全改
    console.log(ss2.course); //["语文", "数学", "英语", "政治"]
    
5.2 对象冒充继承
  • 继承方式:调用父类构造函数,改变this指向为子类this

    //2.子类型(派生类)
    function SmallStudent(classN,name,age,sk){
        //3.对象冒充继承
        Student.call(this,classN,name,age,sk);
        this.findMaMa = function(){
            console.log("找妈妈");
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fuE2YMnT-1635473057007)(./img/对象冒充继承.png)]

  • 问题:不能继承父类原型中的方法和属性

    var ss1 = new SmallStudent("0824","小红",6,"敲代码");
    console.log(ss1);
    console.log(ss1.name); //小红  解决传参的问题
    ss1.course.push("少儿编程");
    console.log(ss1.course); //["语文", "数学", "英语", "少儿编程"]
    
    
    var ss2 = new SmallStudent("0824","小明",6,"敲代码");
    console.log(ss2);
    console.log(ss2.name); //小明
    console.log(ss2.course); //["语文", "数学", "英语"]  解决一改全改的问题
    
    
    ss2.study();//报错,不能继承父类原型中的方法和属性
    
5.3 混合继承
  • 继承方式:原型链继承 + 对象冒充继承

    //1.父类型(基本)
    function Student(classN,name,age,sk){
        this.classN = classN;
        this.name = name;
        this.age = age;
        this.course = ["语文","数学","英语"];
    
        this.skill = function(){
            console.log("我有"+sk+"能力");
        }
    }
    Student.prototype.study = function(){
        console.log("好好学习,天天向上");
    }
    //2.子类型(派生类)
    function SmallStudent(classN,name,age,sk){
        //3.对象冒充继承
        Student.call(this,classN,name,age,sk);
        this.findMaMa = function(){
            console.log("找妈妈");
        }
    }
    //4.继承的行为:原型链继承 子类的原型对象 = 父类的实例对象
    SmallStudent.prototype = new Student("007","小红",7,"打王者");
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5NClH2Eq-1635473057008)(./img/混合继承.png)]

  • 问题:创建了一个多余的父类实例

    //4.继承的行为:原型链继承 子类的原型对象 = 父类的实例对象
    SmallStudent.prototype = new Student("007","小红",7,"打王者");
    
5.4 寄生式组合继承
  • 继承方式:对象冒充+原型

    //2.子类型(派生类)
    function SmallStudent(classN,name,age,sk){
        //3.对象冒充继承
        Student.call(this,classN,name,age,sk);
        this.findMaMa = function(){
            console.log("找妈妈");
        }
    }
    //4.继承的行为:原型链继承 子类的原型对象 = 父类空实例对象
    //Object.create(Student.prototype); 以原型为基础创建对象
    SmallStudent.prototype = Object.create(Student.prototype);
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PhkWFf9f-1635473057008)(./img/寄生式组合继承.png)]

LESS

  • LESS概念:css预处理语言(样式)LESS/SASS,融入编程思想,浏览器不能直接识别less文件,

  • 插件:Easy LESS(将less文件,同步编程成css文件)

  • 注释

    /* 多行注释:编译成css时会保留注释 */
    //单行注释:编译成css时不会保留注释
    
  • 引入

    行间
    内部:style标签中
    外链:link href
    /*2.引入  */
    @import "./reset.css";   /*引入css文件,记得加后缀  */
    @import "./reset"; /*将文件内容复制一份,less后缀可以省略 */
    
  • 嵌套

    /* 3.嵌套
       层次嵌套: 父{  父类的样式  子类{}}
       引用嵌套: &:代替父类
    */
    .box{
        width: 100%;
        height: 300px;
        background: teal;
        &:hover{
            background: pink;
        }
        /* 子类样式 */
        p{
            color: #fff;
            font-size: 30px;
            span{
                color: red;
            }
        }
    }
    
  • 变量

    /* 4.变量: @变量名:值 */
    @mainColor:#80C4AE;
    body{
        background: @mainColor;
    }
    
    
  • 混入

    • 基本混入

      //定义
      .radius{
          width: 200px;
          height: 200px;
          background: teal;
          border-radius: 50%;
      }
      //使用
      h1{
         .radius ;
      }
      //编译:
      h1{
         width: 200px;
          height: 200px;
          background: teal;
          border-radius: 50%;
      }
      
    • 带参数混入

      //定义
      .radius(@w,@h,@ra,@bg){
          width: @w;
          height: @h;
          background: @bg;
          border-radius:@ra;
      }
      //使用
      h1{
          .radius(100px,100px,10px,red); /* 复制了一份 */
      }
      //编译
      h1{
          width: 100px;
          height: 100px;
          background: 10px
          border-radius:red
      }
      
      
    • 参数带默认值,传参就使用传参的值,没有传参就是默认值

      //定义
      .radius(@ra:50%){
          border-radius:@ra;
      }
      //使用
      h1{
          .radius;
      }
      h2{
          .radius(10px)
      }
      //编译
      h1{
          border-radius:50%;
      }
      h2{
          border-radius:10px;
      }
      
    • @arguments

      .shadow(@x,@y,@m,@f,@s){
          box-shadow: @arguments;
      }
      h3{
          .radius(200px,200px,10px,red);
          .shadow(2px,2px,2px,2px,#000);
      }
      
  • 继承

    //定义
    .public{
        width: 200px;
        height: 200px;
        background: gold;
    }
    .active{
        &:extend(.public);
    }
    //编译
    .public,.active{
        width: 200px;
        height: 200px;
        background: gold;
    }
    

jQuery初识

1.jQuery起步

1.1 jQuery的基础知识
  • jQuery优秀的JavaScript库(jquery.js)。这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。

  • 下载:

    • 官网:https://jquery.com/

    • 中文官网:https://www.jquery123.com/

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4b5i5NZt-1635473057009)(C:\Users\ibm\AppData\Roaming\Typora\typora-user-images\1634864518770.png)]

  • 版本

    • 最新版:3.6.0
    • 开发版本: 2.0以下版本 2.0以上版本不兼容IE
1.2 jQuery引入
  • 引入本地jQuery文件(下载)

    <!-- 1.引入本地的jQuery文件 -->
    <script src="./js/jquery-3.6.0.js"></script>
    
  • 引入网上CDN的

    <!-- 2.引入网上的   CDN:内容分发网 -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    
1.3 jQuery的特点
  • 兼容性好

  • 强大的选择器功能 : $(“选择器”)

  • 语法简洁:$(“选择器”).方法();

  • 隐式迭代:自动循环

  • 链式操作

    //1.强大的选择器的功能:$("选择器")
    $(".box").css({"width":200,"height":200,"background":"teal"});
    
    //2.语法简洁:$("选择器").方法();
    //3.隐式迭代:自动循环
    $(".box").click(function(){
        console.log("haha");
    });
    
    //4.链式操作
    $(".box").css({"width":200,"height":200,"background":"teal"}).click(function(){alert("点击了")});
    
1.4 $的作用
  • $就是jQuery别名

    //window.jQuery = window.$ = jQuery;  别名
    window.$("#box").css("width",200);
    $("#box").css("height",200);
    jQuery("#box").css("background","red");
    
1.5 jQuery的加载方法
  • jQuery加载方法 $(选择器).ready(function(){}); : 等文档加载完成后调用

    //1.jQuery加载方法  $(选择器).ready(function(){}); : 等文档加载完成后调用
    $(document).ready(function(){
        $("#box").css("width",200);
    });
    
    $().ready(function(){
        $("#box").css("height",200);
    });
    
    $(function(){
        $("#box").css("background","teal");
    });
    
  • window.onload和$.ready的区别是?

    window.onload:
    	等文档和资源都加载完成后调用
        添加多次后面的会覆盖前面
    $.ready:
    	等文档加载完成就调用
        添加多次事件不会覆盖前面的会叠加执行
    
1.6 jQuery对象与DOM对象之间的关系
  • jQuery对象与DOM对象

    //1.DOM对象 : document.  
    var oDiv = document.getElementsByTagName("div")[0];
    console.log(oDiv); //<div></div>
    
    //2.jQuery对象
    var $div = $("div"); 
    console.log($div); //jQuery.fn.init
    
  • 可以共存,

    //2.jQuery对象
    var $div = $("div"); 
    console.log($div); //jQuery.fn.init
    
    //3.DOM对象和jQuery对象关系:可以共存,但是不能混用
    oDiv.style.height = "200px"; //DOM对象,原生js
    $div.css("background","teal"); //jQ对象,jQuery
    
    
  • 不能混用

    oDiv.css("width",200);
    $div.style.width = "200px";
    
    会报错
    
  • 可以相互转换

    • jQuery对象转DOM对象,加下标

    • DOM对象转jQuery对象 $(DOM对象)

      //4.可以共存,但是不能混用,可以相互转换
      //jQuery对象----->DOM对象   $()[下标]
      console.log($("div")[0]);
      
      
      //DOM对象 ----- >  jQuery对象
      console.log($(oDiv)); //jQuery.fn.init [div#box]
      

2.选择器

2.1 基本选择器
$(function(){
    //id:  $("#id")  获取到对应id名的标签
    $("#middle").css({"background":"pink"});

    //class : $(".class名")  获取到对应class名的标签
    $(".box").css({"background":"teal"});

    //元素  jQuery中选择器没有优先级,只有先后顺序
    $("li").css({"background":"orange"});

    //分组  元素,元素
    $("p,span").css({"color":"green"});


    //添加事件
    $("li").click(function(){
        console.log(this); //<li></li>  DOM元素     $(this)--转jQuery
        $(this).css({"background":"teal"});
        //$().index("selector") : 給当前元素的父元素的所有子元素添加下标
        console.log($(this).index());;
        console.log($(this).index("li"));;
    });
});
2.2 层次选择器
//后代选择器 
$("div span").css({"color":"red"});

//子代选择器
$("div>span").css({"color":"teal"});

//+:相邻兄弟选择器
$("p+span").css({"color":"orange"});
//~: 后面所有的
$("p~span").css({"color":"orange"});
2.3 基本过滤选择器
//:位置
$("li:first").css("background","red");
$("li:last").css("background","red");
$("li:nth-child(2n)").css("background","red");
$("li:nth-child(2n+1)").css("background","pink");
$("li:odd").css("background","red");  //奇数
$("li:even").css("background","pink"); //偶数

//:eq(下标) : 从0开始
$("li:eq(2)").css("background","red");
var index = 3;
$("li").eq(index).css("background","pink");

//not(选择器)  : 除了
$("li:not(.box)").css("background","pink");
$("li").not(".box").css("background","pink");


//gt():获取下标大于n   lt():获取下标小于n
$("li:lt(3)").css("background","red");
$("li:gt(2)").css("background","#ccc");
2.4 属性过滤选择器
//E[attr]:匹配有attr属性的E标签
$("div[class]").css("background", "pink");

//E[attr=value]:匹配有attr属性并且值位value的E标签
$("div[class=box2]").css("background", "red");

//E[attr!=value]:匹配有attr属性并且值不为value的E标签
$("div[class!=box2]").css("background", "teal");

//E[attr^=value]:匹配有attr属性并且值以value开头的E标签
$("div[class^=b]").css("background", "teal");

//E[attr$=value]:匹配有attr属性并且值以value结尾的E标签
$("div[class$=4]").css("background", "orange");

//E[attr*=value]:匹配有attr属性并且值包含value的E标签
$("div[class*=s]").css("background", "deeppink");
2.5 表单选择器
//表单选择器
console.log( $(":input")); //获取的是所有的表单元素   (input button textarea select)

// :input的type类型,获取到具体类型的input
console.log($(":text")); //文档框
console.log($(":radio")); //单选框

//:checked : 获取选择框被选中的标签
console.log( $(":checkbox:checked"));
console.log( $(":checkbox:checked").length);

注意常用选择器:id,元素,class,分组,后代,子代,eq必须要掌握

3.操作标签

3.1 jQuery操作标签内容
  • 原生js

    • 表单元素:标签.value

    • 闭合标签:标签.innerHTML/innerText

      操作闭合标签内容,覆盖原有内容,innerHTML识别标签,innerText不识别标签

  • jQuery

    • 表单元素: $().val();
    • 闭合元素: $().html()/text();
    //1.操作表单元素: $().val()
    var value = $("input").val();
    console.log(value);
    $("input").val("我是后期定义的");
    
    
    //2.操作闭合标签
    console.log($("div").html()); //<p>的看风景的大幅度</p>
    console.log($("div").text()); //的看风景的大幅度
     
    $("div").html("<p>发副科级阿凡达</p>"); //解析标签
    $("div").text("<p>发副科级阿凡达</p>"); //标签直接以文本的样式显示
    
    //追加
    $("div").html($("div").html() + "<p>发副科级阿凡达</p>");
    
3.3 操作标签样式
  • 原生js操作标签样式(用于设置)

    • 标签.style.属性名 = 属性名
  • jQuery操作标签样式(用于设置)

    • 单个操作样式:$().css(属性名,属性值);
    • 批量操作样式:$().css({“属性名”:“属性值”})
    //1.操作标签样式  (要么写数字,要么写字符带单位)
    $("div").css("width",200);
    $("div").css("height","200");
    $("div").css("margin","100px");  //值不对,不报错
    $("div").css("background","teal");
    
    
    //2.批量操作样式:$().css({"属性名":"属性值"})
    $("div").css({ 
        "width": 200, 
        "height": 200,
        background:"teal",
        // "font-size":"30px"
        fontSize:"30px"
    })
    
3.3 操作标签属性
3.3.1 普通属性的操作
  • 原生JS操作标签属性

    • 设置:标签.属性名 = 属性值
    • 获取:标签.属性名
    • 特殊:class — > 标签.className
  • DOM操作标签属性

    • 设置:标签.setAttribute(“属性名”,“属性值”)
    • 获取:标签.getAttribute(“属性名”)
    • 删除:标签.removetAttribute(“属性名”)
  • jQuery操作标签属性

    • attr() :操作自定义属性
      • 设置:$().attr(“属性名”,“属性值”)
      • 获取:$().attr(“属性名”)
      • 删除:$().removeAttr(“属性名”)
    • prop():固有属性
      • 设置:$().prop(“属性名”,“属性值”)
      • 获取:$().prop(“属性名”)
      • 删除:$().removeProp(“属性名”)
    • 注意:其他的属性操作都使用attr,如果操作的input的checked属性使用prop
3.3.2 操作class属性
//1.$().addClass("类名") : 追加class
$(this).addClass("active");

//2.$().removeClass("类名"):删除对应的class
$(this).removeClass("active");

//3.$().hasClass("类名")  : 判断当前元素是否存在某个类名,有返回true,不存在返回false
if($(this).hasClass("active")){ //有
    $(this).removeClass("active");
}else{ //没有
    $(this).addClass("active");
}

//4. $().toggleClass("类名") : 开关,如果当前有这个class就删除,没有就添加
$(this).toggleClass("active");
3.5 关系选择
  • 获取子代元素 $().children(selector)
  • 获取后代元素 $().find(selector)
  • 获取父元素 $().parent(selector)
  • 兄弟
    • 上一个 $("").prev(selector) prevAll
    • 下一个 $("").next(selector) nextAll
    • 所有兄弟:$("").siblings(selector)
//1.获取子代元素   $().children(selector): 
console.log($("div").children("span")); //<span>我是个外人</span>

//获取后代元素  $().find(selector)
console.log($("div").find("span")); // [span, span]


//2.获取父元素  $().parent(selector)
console.log($(".haha").parent());  //直接父元素
console.log($(".haha").parents("ul")); //所有的父辈元素


//3.兄弟
//上一个  $("").prev(selector)
$(".xi").prev().css("background","teal");  //上一个兄弟
$(".xi").prevAll().css("background","teal"); //上面所有兄弟

//下一个  $("").next(selector)
$(".xi").next().css("background","teal");  //下一个兄弟
$(".xi").nextAll().css("background","teal"); //下面所有兄弟

//所有兄弟:$("").siblings(selector)  
$(".xi").siblings().css("background","yellowgreen");

jQuery进阶

1.jQuery的循环操作

1.1 原生js循环
  • for:明确的起始,循环次数和结束,循环添加事件,循环生成标签,循环数组
  • while:没有明确的循环次数,但是有明确的结束条件
  • do-while:先执行后判断
  • for-in:循环对象
1.2 jQuery循环
1.2.1 each()
  • $.each():没有返回值

  • 语法:

    • $.each(循环对象,function(index,value){}); 数组、对象

    • $(循环对象).each(function(index,value{})); 标签,数组

      //1.循环数组
      var arr = ["a", "b", "c", "d"];
      $.each(arr, function (index, value) {
          console.log(index + "---------" + value); //0---------a
      });
      
      //2.循环对象
      var obj = {
          "name": "苗苗",
          "age": 18,
          "height": 160,
          "sex": "女"
      }
      $.each(obj, function (key, value) {
          console.log(key + "------" + value); //name------苗苗
      })
      
      //3.循环标签
      $.each($("li"), function (index, elem) {
          console.log(elem); //<li>1</li>  DOM
      });
      $("li").each(function (index, elem) {
          console.log(elem); //<li>1</li>  DOM
      });
      
      //累加
      var sum = 0;
      $("li").each(function (index, elem) {
          sum += $(elem).text() * 1
      })
      
      
1.2.2 map()
  • $.map():有返回值

  • 语法:

    • $.map(循环对象,function(value,index){}); 数组、对象

    • $(循环对象).map(function(index,value{})); 标签,数组

      //循环数组
      var a = $.map(arr,function(value,index){
          console.log(index+"------"+value);
          return index;
      });
      //有返回值
      console.log(a); //[0, 1, 2, 3]
      
      //循环对象
      $("li").map(function(index,elem){
          console.log(elem);
      }
      

2.jQuery的BOM操作

2.1 原生js的BOM操作
  • location
    • href:获取/设置当前窗口的url地址
    • search:获取url中搜索内容
  • client系列:可视区域
    • 获取元素的可视宽高:元素.clientWidth /Height content+padding
    • 获取屏幕的可视宽高:document.documentElement.clientWidth/Height
  • offset系列:占位宽高
    • 获取元素的占位宽高:元素.offsetWidth/Height content+padding+border
    • 获取元素在页面的位置:元素.offsetTop/Left
  • scroll系列:滚动
    • onscroll:滚动条滚动的时候触发
    • 页面滚动距离:document.documentElement.scrollTop || document.body.scrollTop
2.2 jQuery的BOM操作
2.2.1 获取元素的宽高
  • 获取内容宽高
    • $().width()/height()
  • 获取可视宽高
    • $().innerWidth()/innerHeight()
  • 获取占位宽高
    • $().outerWidth(boolean)/outerHeight(boolean)
    • 默认是false:不包含margin true:包含margin
2.2. 获取元素的位置
  • 当前元素到body的距离
    • $().offset()
  • 定位的距离
    • $().position()
  • 滚动的距离
    • $(window).scollTop()

3.jQueryDOM的操作

3.1 原生js的DOM操作
  • 获取
    • 获取DOM元素
      • document.getElementById()
      • document.getElementsByClassName()
      • document.getElementsByTagName()
      • document.querySelector():获取选择器选中元素第一个
      • document.querySelectorAll():获取选择器选中的所有元素
    • 获取节点
      • 子:父节点.children / 父节点.childNodes
      • 父:子节点.parentNode
      • 首:父节点.firstElementChild || 父节点.firstChild
      • 尾:父节点.lastElementChild || 父节点.lastChild
      • 上一个兄弟:参考节点.previousElementSibling ||参考节点.previousSibling
      • 下一个兄弟:参考节点.nextElementSibling ||参考节点.nextSibling
    • 创建节点
      • 创建标签节点:document.createElement(“标签名”)
      • 创建文本节点:document.createTextNode(“文本内容”)
    • 添加节点
      • 追加:父节点.appendChild(子节点)
      • 插入:父节点.insertBefore(newChild,refChild)
    • 删除
      • 删除元素本身:节点.remove()
      • 删除子节点:父节点.removeChild(子节点)
    • 替换
      • 父节点.replaceChild(newChild,refChild)
    • 复制
      • 被复制的节点.cloneNode(boolean)
3.2 jQuery的DOM操作
3.2.1 查找
  • 找子节点:
    • $(父节点).children(selector) : 找子代
    • $(父节点).find(selector) : 找后代
  • 找父节点
    • $(子节点).parent(selector) : 找直接父节点
    • $(子节点).parents(selector):找所有的父辈节点
  • 找兄弟节点
    • $(参考节点).prev(selector) : 上一个兄弟节点
    • $(参考节点).prevAll(selector) : 上面所有的兄弟节点
    • $(参考节点).next(selector) : 下一个兄弟节点
    • $(参考节点).nextAll(selector) : 下面所有的兄弟节点
    • $(参考节点).siblings(selector) : 所有的兄弟节点
3.2.2 添加
  • 创建节点
  • 语法:$(“节点”)

     //1.创建节点
    var $li = $("<li>我是内容</li>");
    console.log($li);
    
  • 追加节点

    • 语法1:$(父节点).append(子节点)

    • 语法2:$(子节点).appendTo(父节点)

      //2.追加:在父元素末尾添加
      //语法1:$(父节点).append(子节点)
      $("ul").append($li); //添加已经创建好的标签
      $("ul").append("<li>iphone13</li>"); //直接添加字符串形式的标签
      
      //语法2:$(子节点).appendTo(父节点)
      $("<li>华为保时捷</li>").appendTo("ul");
      
  • 前置:在父元素的头部添加

    • $(“父元素”).prepend(“子元素”)

    • $("子元素”).prependTo(“父元素”)

      //2.前置添加:父元素的头部
      $("input").keydown(function(ev){
          if(ev.keyCode == 13){
              //2.1 $("父节点").prepend("子节点")
              $("ul").prepend("<li>"+$("input").val()+"</li>");
      
              //2.2 $("子节点").prepend("父节点")
              $("<li>"+$("input").val()+"</li>").prependTo("ul");
          }
      });
      
  • 插入:在某个元素之前

    • $(“参考元素”).before(“新元素”)

    • $(“新元素”).insertBefore(“参考元素”)

      //3.插入:在某个元素之前插入
      //3.1 $("参考节点").before("新节点");
      $("li:eq(3)").before("<li>总结、复习</li>");
      
      //3.2 $("新节点").insertBefore("参考节点")
      $("<li>总结、复习</li>").insertBefore("li:eq(3)");
      
  • 插入:在某个元素之后

    • $(“参考元素”).after(“新元素”)

    • $(“新元素”).insertAfter(“参考元素”)

      //3.插入:在某个元素之后插入
      //3.1 $("参考节点").after("新节点");
      $("li:eq(3)").after("<li>总结、复习</li>");
      
      //3.2 $("新节点").insertAfter("参考节点")
      $("<li>总结、复习</li>").insertAfter("li:eq(3)");
      
3.2.3 删除节点
  • $().detach():删除元素,返回被删除元素的引用,方便下次使用,保留事件

  • $().remove():删除元素,返回被删除元素的引用,方便下次使用,不保留事件

  • $().empty():清空子元素

    $("li").click(function(){alert(this)});
    
    // $().detach():删除元素,返回被删除元素的引用,方便下次使用,保留事件
    $("button:eq(0)").click(function(){
        var detLi = $("li").detach();
    
        setTimeout(function(){
            $("ul").append(detLi);
        },500);
    })
    
    //$().remove():删除元素,返回被删除元素的引用,方便下次使用,不保留事件
    $("button:eq(1)").click(function(){
        var detLi = $("li").remove();
        setTimeout(function(){
            $("ul").append(detLi);
        },500);
    });
    
    $("ul").empty();
    
    
3.2.4 替换节点
//1.替换
//$("被替换的节点").replaceWith("替换的")
$("li:last").replaceWith("<li>下班</li>");

//$("替换的").replaceAll("被替换的")
$("<li>工作</li>").replaceAll("li:eq(4)");
3.2.5 复制节点
//2.复制
$("li:first").click(function(){alert("开心")})
$("li:first").clone(false).appendTo("ul");  //复制标签
$("li:first").clone(true).appendTo("ul");  //复制标签和js中的事件

4.事件

4.1 事件对象相关
4.1.1 事件对象jQ
  • 原生js:
    window.event:事件对象,事件触发时浏览器会将事件相关的信息存储的事件对象中
    var ev = window.event || eve

  • jQ
    直接通过事件处理函数的第一个参数传入(不需要兼容)

    /*原生js:
    	事件对象:event,事件发生时浏览器将所有和事件相关的信息存储在事件对象中 
    	事件处理函数:事件发生时调用的函数
    	事件对象的属性:
    		type:事件类型
    		target||srcElement : 事件目标
    		clientX+clientY : 鼠标位置
    jQuery的事件对象
    	事件对象:从事件处理函数的第一个参数传入
    */
    $(document).click(function(ev){ //从事件处理函数的第一个参数传入  jq处理过的
        console.log(ev); //jQ处理过的事件对象
        console.log(ev.originalEvent); //原生事件对象
    
        console.log(ev.type); //事件类型
        console.log(ev.target); //事件目标
        console.log(ev.clientX); //鼠标位置
    });
    
4.1.2 冒泡
  • DOM事件流:事件发生时的执行过程

  • 事件捕获机制:事件发生的时候先从window开始,依次向子元素传递,一直到目标元素(从外到内传递)

  • 事件冒泡机制:目标元素处理事件,将事件依次传递给父元素,如果父元素也有对应类型的事件也会触发,一直传递到window(从里到外传递)

  • 阻止事件冒泡:

    • 原生:event.stopPropagation ? event.stopPropagation():event.cancelBubble=true;

    • jQ: ev.stopPropagation(); return false

      //2.事件冒泡:目标元素开始处理事件,然后依次将事件往父元素传递,一直到window(从里到外)
      //原生JS阻止事件冒泡:ev.StopPropagation ? ev.StopPropagation():ev.cancelBubble = true
      //jQ阻止事件冒泡:ev.stopPropagation();
      
      // return false : 阻止事件冒泡,阻止事件默认行为
      $("button").click(function (ev) {
          console.log("我是一个小按钮");
          ev.stopPropagation();
      });
      
4.1.3 事件默认行为
  • 事件默认事件:自带的功能

  • 阻止事件默认行为

    • 原生:ev.preventDefault ?ev.preventDefault():ev.returnValue = false

    • jQ阻止事件默认事件:ev.preventDefault();

      //3.事件默认事件:自带的功能
      //原生JS阻止事件默认事件:ev.preventDefault ?ev.preventDefault():ev.returnValue = false
      //jQ阻止事件默认事件:ev.preventDefault();
      // return false : 阻止事件冒泡,阻止事件默认行为
      $("a").click(function (ev) {
          ev.preventDefault();
          // return false;
      })
      
4.2 事件绑定
4.2.1 原生JS的事件绑定
  • 普通添加:
    • 语法:标签.事件名 = function(){}
    • 问题:添加相同事件会覆盖
  • 事件绑定
    • 解决:添加相同事件会叠加执行
    • 语法:
      • 标签.addEventListener/removeEventListener(事件类型,事件处理函数,是否捕获)
      • 标签.attachEvent/detachEvent(事件类型,事件类型函数)
4.2.2 jQuery的事件绑定
  • 普通添加:$().事件名() — 添加多次会叠加执行
1).事件绑定的基本用法
  • 语法:$(selector).on(事件类型,事件处理函数)

    //1.给一个标签添加多个相同的事件,叠加执行
    $("div").on("click",fun1);
    $("div").on("click",fun2);
    
    
    //2.给同一个标签的不同事件添加相同的处理函数,多个事件之间用空格隔开
    $("div").on("click mouseover",fun1);
    
    
    //3.同时添加多个事件
    $("div").on({
        "click":fun1,
        "mouseover":fun2,
        "mouseout":fun1
    });
    
    //4.使用命名空间:如果项目足够大,使用了大量的第三方框架,可能会命名冲突
    var home = {};
    home.name = "首页";
    
    var list = {};
    list.name = "列表";
    
    $("div").on("click.login",fun1);
    $("div").on("click.close",fun2);
    
    
    
    //5.自定义事件
    $("div").on("sleep",function(){
        console.log("睡觉");
    });
    //自动触发
    setTimeout(function(){
        $("div").trigger("sleep");
    },3000);
    
2) 事件代理
  • 原理:事件代理:将事件添加给父元素,子元素发生事件的时候,会通过事件冒泡将事件传递给父元素,在事件处理函数中,找到具体的子元素去处理事件

  • 好处:提高效率,节约性能,事件可以发生在未来

  • 原生js实现

    var oUl = document.getElementsByTagName("ul")[0];
    oUl.onclick = function(ev){
        var ev = window.event || ev;
        var target = ev.target || ev.srcElement; //找到具体的子元素去触发事件
        target.style.background = "red";
    }
    oUl.innerHTML += "<li>1111</li>";
    
  • jQ实现

     //jQ事件绑定:$(父元素).on(事件类型,"子元素",事件处理函数)
    $("ul").on("click","li",function(){
        console.log(this); //this就是触发事件的子元素
        $(this).css("background","red").siblings().css("background","");
    });
    $("ul").append("<li>222222</li>")
    
4.3 事件取消
  • 添加

    • $(selector).事件名()
    • $(selector).on(事件类型,事件处理函数)
  • 取消

    • $().off()
    //3.取消事件   $().off();
    $("div").off();   //取消这个标签上的所有事件
    $("div").off("click");  //取消这个标签上的对应类型的事件
    $("div").off("click",fun2); //取消其中一个点击事件
    

jQuery高级

1. 预置动画

1.1 显示隐藏—宽高透明度
  • 显示隐藏方法(宽高透明度):show():显示 hide(): 隐藏 toggle():开关

  • 语法:$(selector).show(speed,easing,callback)

  • 参数:

    • speed:动画过渡所需事件,可能的值:num(ms),关键字:“fast”:200,“normal”:400,“slow”:600

    • easing:运动方式,可能的值:linear:匀速,swing:慢-快-慢

    • callback:回调函数

      //1.点击显示 
      $(".show").click(function(){ 
          $("div:eq(0)").show(500,"linear"); 
          // $("div:eq(1)").show(500,"swing",function(){ 
          // alert("回调执行"); 
          // }); })
      //2.点击隐藏 
      $(".hide").click(function(){ 
          $("div").hide(1000); 
      })
      //3.开关 
       $(".toggle").click(function(){ 
           $("div").toggle(400); 
       })
      
1.2 滑入滑出–高
  • 滑入滑出方法(高):slideUp():滑出 slideDown():滑入 slideToggle():开关

  • 语法:$(selector).slideDown(speed,easing,callback)

  • 参数:

    • speed:动画过渡所需要的时间,可能的值:num(ms),关键字:“fast":200,“normal”:400,“slow”:600

    • easing:运动方式,可能的值:linear:匀速,swing:缓动在开始结束

    • callback:回调函数

      //1.点击滑入 
      $(".slideDown").click(function(){ 
          $("div").slideDown(1000); 
      })
      //2.点击滑出 
      $(".slideUp").click(function(){ 
          $("div").slideUp(1000); 
      })
      //3.开关 
      $(".slideToggle").click(function(){ 
          $("div").slideToggle(1000); 
      })
      
1.3 淡入淡出
  • 淡入淡出(透明度):fandIn():淡入 fadeOut():淡出 fadeToggle():开关 fadeTo():透明度

  • 语法:$(selector).slideDown(speed,easing,callback)

  • 参数:

    • speed:动画过渡所需的时间,可能的值:num(ms),关键字:“fast”:200,“normal”:400,“slow”:600
    • easing:运动方式,可能的值:linear:匀速,swing:缓动在开始结束
    • callback:回调函数
  • 语法:$(selector).fadeTo(speed,to,easing,callback)

    • to:指定透明的数值 范围0-1

      //1.点击淡入 
      $(".fadeIn").click(function(){ 
          $("div").fadeIn(1000); 
      })
      //2.点击开关 
      $(".fadeToggle").click(function(){ 
          $("div").fadeToggle(1000); 
      })
      //3.透明到 
      $(".fadeTo").click(function(){ 
          $("div").fadeTo(1000,0.3); 
      })
      

2. 自定义动画

2.1 语法1:第一种用法
  • 语法:$(标签).animate({attr},speed,easing,callback)

    //1.queue动画队列,每一个animate都会自动加入到动画队列,排队执行
    $("div").animate({"width":500});
    $("div").animate({"height":500});
    
    //2.同时运动多个属性
    $("div").animate({"width":500,"height":500});
    
    //3.自带累加效果
    $("div").click(function(){
        $("div").animate({"left":"+=100"})
    })
    
2.2 第二种用法
  • 语法:$(标签).animate({attr},{props})

  • 参数props

    • duration - 设置动画的速度

    • easing - 规定要使用的easing函数

    • callback - 规定动画完成之后要执行的函数

    • queue - 布尔值,指示是否在效果队列中放置动画,如果为false,则动画将立即开始

      //$("div").animate({"width":500},600);  紧跟在后面的动画会一起执行
      $("div").animate({ "width": 500 }, { "duration": 1000, "queue": false });
      $("div").animate({ "height": 500 }, { "duration": 1000, "queue": false });
      $("div").animate({ "opacity": 0.5 }, { "duration": 1000 }); 
      
2.3 动画方法
  • stop(clearQueue,gotoEnd):停止动画

    • 参数:

      • clearQueue:是否停止动画队列中的所有动画,默认是false:停止当前正在运动的动画,true:停止所有的动画

      • gotoEnd:停止动画是当前运动的属性是否立刻到达目标值,默认是false:点哪到哪,true:停止时立刻到达目标点

         $(".start").click(function(){
             $("div").animate({"width":500},1000);
             //3.delay():延迟执行
             $("div").delay(1000);
             $("div").animate({"height":500},1000);
         });
        
        $(".stop").click(function(){
            $("div").stop(false,true);
        });
        
  • finish():停止动画,所有动画全部停止,并且都到达目标点

    //2.finish() : 停止动画,所有动画全部停止,并且都到达目标点
    $("div").finish();
    
  • is(":animated"):判断当前元素上是否有动画,有–true 没有–false

    $(".is").click(function(){
        //如果元素上有动画,不加,没有再加
        if($("div").is(":animated") == false){
            $("div").animate({"width":"toggle"});
        } 
    })
    
2.4 运动scrollTop
//2.点击top回到顶部
$("p").click(function(){
    $("html,body").animate({"scrollTop":0})
})

3. $.extend

3.1 浅拷贝
  • 浅拷贝:拷贝的数据中,存储引用数据类型,直接拷贝地址,一改全改

  • 数组的浅拷贝

    //深浅拷贝:对象和数组
    var arr1 = ["A","B","C",["haha","hehe"]];
    
    //1.浅拷贝:拷贝的地址,一改全改
    //声明一个空的数组【属于自己的存储空间】
    var arr2 = [];  
    
    //将arr1的值,一个一个拷贝到arr2
    for(var i = 0;i<arr1.length;i++){
        arr2[i] = arr1[i];
    }
    console.log(arr1,arr2);
    
    //普通的数据类型没有问题
    arr1.push("D"); // ["A", "B", "C","D"]
    console.log(arr2); // ["A", "B", "C"]
    
    
    //引用数据类型,拷贝的地址,一改全改
    arr2[3].push("heihei");
    console.log(arr2); //["A","B","C",["haha","hehe","heihei"]]
    console.log(arr1);
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xegq3a2H-1635473057010)(C:\Users\20199\Desktop\笔记\第二阶段\img\数组浅拷贝.png)]

  • 对象的浅拷贝

    //2.对象
    var obj1 = {
        "name":"苗苗",
        "age":18,
        "detail":{"height":160}
    }
    //声明一个空的对象【属于自己的存储空间】
    var obj2 = {};
    //循环将对象中的属性一个一个添加过来
    for(var key in obj1){
        obj2[key] = obj1[key];
    }
    console.log(obj1,obj2);
    
    obj2.name = "大苗苗";
    console.log(obj1); //{name: "苗苗", age: 18}
    
    //复制的是对象地址,一改全改
    obj2.detail.height = 170;
    console.log(obj1); //{name: "苗苗", age: 18, detail: {"height":170}}
    
3.2 深拷贝
  • 深拷贝:拷贝的是值,(如果发现拷贝的内容也是引用数据类型,则这个部分再进行深拷贝),相互之间没有练习,不会一改都改

    //获取数据的具体的数据类型,并且返回
    function getType(data) {
        // console.log(Object.prototype.toString()); //返回数据具体的数据类型
        // .call() 改变this的指向
        // console.log(Object.prototype.toString.call(data).slice(8,-1));
        return Object.prototype.toString.call(data).slice(8, -1)
    }
    function deepCopy(data) {
        //1.先声明一个空数组,空对象
        if(getType(data) == "Array"){
            var res = [];
        }else if(getType(data) == "Object"){
            var res = {};
        }else{
            return data;
        }
    
        //2.循环将原有数据中的内容,一个一个复制到空数据里面
        for(var key in data){
    
            //4.如果复制的值还是 引用数据类型,这个部分也需要进行深拷贝
            if(getType(data[key]) == "Array" || getType(data[key]) == "Object"){
                res[key] = deepCopy(data[key]);
            }else{
                res[key] = data[key];
            }
        }
    
        //3.返回复制好的对象
        return res;
    
    }
    
3.3 $.extend
  • $.extend():复制对象的属性

  • 语法:$.extend(deep,targetObj,obj1,obj2,…)

  • 作用:将后面的对象中的属性,复制到目标对象中,返回一个新的对象

  • 参数:

    • deep:是否深拷贝

    • targetObj:目标对象

    • obj:将要被复制的对象

      var obj1 = {
          "name": "苗苗",
          "age": 18,
          "detail": { "height": 160 }
      }
      
      //1.浅拷贝;拷贝的是地址,会一改全改
      var obj2 = $.extend({}, obj1);
      console.log(obj2); //{name: "苗苗", age: 18, detail: {"height":160}}
      
      obj2.detail.height = 130;
      console.log(obj2);//{name: "苗苗", age: 18, detail: {"height":130}}
      console.log(obj1);//{name: "苗苗", age: 18, detail: {"height":130}}
      
      
      
      //2.深拷贝:拷贝的是值,不会相互干扰
      var obj3 = $.extend(true,{}, obj1);
      console.log(obj3); //{name: "苗苗", age: 18, detail: {"height":130}}
      
      obj3.detail.height = 170;
      console.log(obj3);//{name: "苗苗", age: 18, detail: {"height":170}}
      console.log(obj1);//{name: "苗苗", age: 18, detail: {"height":130}}
      
3.4 实现深拷贝
  • 深拷贝:拷贝的是值,相互没有关系,不会一改全改

  • 原生js实现深拷贝(递归思想)

    //2.声明一个函数,获取数据的具体的数据类型
    function getType(data){
        return Object.prototype.toString.call(data).slice(8,-1);
    }
    
    //1.声明一个函数,实现深拷贝
    function deepCopy(data){
        //1.声明一个空区间,根据数据类型创建对象的空区间
        if(getType(data)) === "Array"{
            var res=[];
        }else if(getType(data) === "Object"){
            var res={};
        }else{
            return data;
        }
        
        //2.循环将原有数据的内容,一个一个赋值到空区间中
        for(var key in data){
            // 如果拷贝的值是引用数据类型(array,object),这部分内容需要再次进行深拷贝
            if(getType(data[key]) === "Array"||"Object"){
                res[key] = deepCopy(data[key]); //创建一个空区间,循环
            }else{
                res[key] = data[key];
            }
        }
        //或者
        //for(var key in data){
        //    res[key]=deepCopy(data[key]);
        //}
        
        
        //3.返回复制好的数据
        return res;
    }
    
  • jQuery实现深拷贝:$.extend()

    • 语法:$.extend(true,目标对象,原对象)

       //2.$.extend()
      var obj1 = {"name":"web","detail":{"class":"0824"}};
      var obj2 = $.extend(true,{},obj1);
      console.log(obj2); //{"name":"web","detail":{"class":"0824"}};
      
      obj1.detail.class = "0924";
      console.log(obj2);//{"name":"web","detail":{"class":"0824"}};
      
  • JSON方法实现深拷贝

    • JSON.stringify(obj):将对象转为字符串格式

    • JSON.parse(str):将字符创的对象值转为对象格式

       var obj1 = {"name":"web","detail":{"class":"0824"}};
      
      var obj2 = JSON.parse(JSON.stringify(obj1));
      console.log(obj2); //{"name":"web","detail":{"class":"0824"}};
      
      obj1.detail.class = "0924";
      console.log(obj2); //{"name":"web","detail":{"class":"0824"}};
      

jQuery插件与zepto

  • jQuery插件:在jQuery原有功能 基础上,扩展的一些其他的方法,jQuery插件依赖于jQuery

1. 使用第三方插件

2. 自定义插件

2.1 扩展类级别插件
  • 类级别插件:$.map() $.each() $.trim() $().extend()

  • 扩展语法:$.extend({“方法名”:function(){ 实现代码 }})

    $.extend({
        // 数组去重
        "qc": function (arr) {
            //拿第一个和后面所有的进行比较,如果有相同,删除后面的那一个
            for (var i = 0; i < arr.length; i++) {
                for (var j = i + 1; j < arr.length; j++) {
                    if (arr[i] == arr[j]) {
                        arr.splice(j, 1);
                        j--;
                    }
                }
            }
            return arr;
        }
    });
    
    var arr = $.qc([1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4]);
    console.log(arr); // [1, 2, 3, 4]
    
2.2 对象级别插件
  • 对象级别拓展:$(selector).css() $(selector).click()

  • 拓展语法:$.fn.extend({“方法名”:function(){ 实现代码 }})

    $.fn.extend({
        //排他
        "pt":function(){
            //console.log(this);  //$("ul") 选择器选择的标签  S.fn.init(10) [li.active]
            this.children().click(function(){
                //console.log(this); //<li>2</li>
                $(this).addClass("active").siblings().removeClass("active");
            });
            return this; //对象级别扩展的时候,返回当前操作的对象,为了链式操作
        }
    });
    
    $("ul").pt().css("background","pink");
    $(".box").pt();
    

zepto

zepto.js和jQuery.js类似,zepto.js为了实现轻量级,将不同的功能分成一个一个单独的js文件,需要的时候引入对应的js文件即可。

  • 和jQ的区别

    <script src="./js/zepto.min.js"></script>
    <script src="./js/fx.js"></script>
    <!-- <script src="./js/jquery.js"></script> -->
    <script>
        $("div").css("background","teal");
    	$("div").click(function(){
            // $("div").css("background","deeppink");
            //需要引入额外的动画模块
            $("div").animate({"width":500})
    	});
    
    //没有innerWidth,outerWidth  实际大小,如果元素隐藏获取不到元素的宽高位置
    console.log($("div").width()); 
    
     //{left: 0, top: 0, width: 0, height: 0}  多了width,height
    console.log($("div").offset());
    </script>
    
  • touch手势

    /* 
     'swipe':滑动, 'swipeLeft':左滑, 'swipeRight', 'swipeUp':上滑, 'swipeDown',
     'doubleTap':双击, 'tap':点击, 'singleTap':单击, 'longTap':长按
    */
    $("div").on("tap",function(){
        console.log("点击");
    })
    $("div").on("singleTap",function(){ //300ms
        console.log("单击");
    })
    $("div").on("doubleTap",function(){
        console.log("双击");
    })
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值