概述
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(匹配){ case 值1 : 匹配到值1以后执行的代码;break case 值2 : 匹配到值2以后执行的代码;break case 值3 : 匹配到值3以后执行的代码;break default:前面的都没有匹配到执行的代码 } 注意:值要求必须是一个具体的不变的值 ***break防止穿透,如果没有break,匹配到值以后后面的代码就不会再判断,会立刻执行*** 条件是一些简单的固定的符号或数字,会选择使用switch
循环结构
for循环
- for循环
什么时候需要用?:多次重复执行,多次有规律重复执行
for的作用?:可以让特定的代码执行指定次数
- 语法:
for(表达式1;表达式2;表达式3){ 循环体(需要重复执行的代码) }
for(初始化循环变量;循环条件;更新循环变量){ 循环体(需要重复执行的代码)}
for(var i=0;i<10;i+){ 循环体(需要重复执行的代码)}
- 列子
for(var 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:UsersibmAppDataRoamingTyporatypora-user-images1629107394896.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:Users20199Desktop笔记第二阶段imgQQ截图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:Users20199Desktop笔记第二阶段imgQQ截图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 = /^1d{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 = "nabncde"; 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 = /^dddddd$/; 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:Users20199Desktop笔记第二阶段imgDOM树.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:Users20199Desktop笔记第二阶段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:Users20199Desktop笔记第二阶段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
- 屏幕分辨率的高: window.screen.height
/*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); }
- document.documentElement.clientWidth/Height
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:Users20199Desktop笔记第二阶段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:UsersibmAppDataRoamingTyporatypora-user-images1634864518770.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
- attr() :操作自定义属性
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)
- 获取DOM元素
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:Users20199Desktop笔记第二阶段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("双击"); })
最后
以上就是淡然铃铛为你收集整理的JavaScript笔记JavaScript的全部内容,希望文章能够帮你解决JavaScript笔记JavaScript所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复