将将将将~我们来到了第二周的学习,只要学过了,就都不会觉得,这周我们会学习API,简化底层,但轮播还是得自己写
一、***数据类型转换
为什么?页面上的一切数据都是字符串类型,有可能做些操作的时候(+运算)不适合,需要先转换,再操作
1、强制类型转换:
- 转字符串
a.XX.toString;
b.String(xx);
(都没什么用,因为页面的一切元素都是字符串) - 转数字
a.**parseInt(xx);
从左到右依次读取,碰到非字符串就停下,不认识小数点;
b.**parseFloat(xx);
同parseInt,但认识第一个小数点; c.Number(xx);--不如隐式转化
- 转布尔
Boolean(xx);--条件中自带隐式转化,只需记住哪几个为false,其余都未true————
(null,NaN,"",0,undefined,false)
2、隐式转换:
多半都在运算符之中
二、运算符和表达式
1、算数运算
(+-/%)
带有隐式转化
默认:都会转为数字再运算
**特殊:1.+:碰上一个字符串,就会变为拼接
2.-/:碰上非纯数字会转化为NaN
2、比较运算
(> < <= >= != == !== ===)
结果:布尔值
带有隐式转化
默认:都会转为数字再运算
特殊:1. 左右都是字符串:ascii码或unicode号按位PK
(0-9——48-57、A-Z——65-90、a-z——97-122)
2.NaN参加任何比较运算都为NaN,故只能用
!isNaN——true(是有效数字)
3.undefined===null用三等才能区分;
3、逻辑运算符
带有隐式转换:条件会悄悄的都变为布尔,然后综合比较得出结论
1.&& 都满足才为TRUE
**短路:简化简单的if分支
条件&&(操作)
2.|| 一个满足就为true
3.!
4、位运算
m<<n:m左移了n位===m*2^n
没用,底数只能为2
5、赋值运算
一句话执行了两个操作,先运算,再赋值
(+= -= *= /= %= ++ --)
**笔试时:++ 分为 ++i 和 i++
1、单独使用时,没有参与别的表达式,放前放后都一样
2、如果参与了别的表达式:
变量中的值其实都会+1
++i,返回的是递增后的【新值】
i++,返回的是递增前的【旧值】
6、 ***三目运算
简化分支:if(){}else{} if(){}else if()else{}
语法:
1、条件?操作1:默认操作;
2、条件1?操作1:条件2?操作2:默认操作;
注意:
1、只能简化简单的分支 - 三目的操作也只能有一句话,不怕,很多情况操作就只有一句话
2、默认操作不能省略 - 哪怕条件都不满足,至少还要做一件事
扩展:解决舍入误差:parseFloat(num.toFixed(n))
三、*****自定义Function
1. 创建和调用
1.创建
*a.【声明方式】创建函数
function 函数名(形参,...){
函数体;
return 返回值/结果;
}
b.【直接量方式】创建函数 - 无用
var 函数名=function(形参,...){
函数体;
return 返回值/结果;
}
2.调用
var 接住返回的结果=函数名(实参,...);
2. 作用域
1.全局作用域:
全局变量 和 全局函数,在页面的任何一个位置都可以使用
2.函数/局部作用域:局部变量 和 局部函数,在【当前函数调用时内部可用】
*变量的使用规则:优先使用自己的,自己没有找全局,全局没有报错
特殊:缺点:1、千万不要在函数中对着未声明的变量直接赋值 - 全局污染
2、局部可以用全局的,但是全局不能用局部的 - 解决:看上面return
3. 声明提前
在程序正式执行之前 将var声明的变量(轻)和function声明的函数(重) 都会悄悄集中定义在当前作用域的顶部 但是赋值留在原地
何时使用:永远不会自己使用,垃圾干扰我们判断 - 只会在笔试中遇到,为什么平时开发根本不可能遇到它?
只要你遵守以下原则:
1、变量名和函数名尽量的不要重复
2、先创建后使用
3、如果鄙视时需要先试用后创建,多半都是在考你声明提前
4. 按值传递
如果传递的是原始类型的值: 修改一个变量,另一个变量是不会受到影响的,其实是复制了一个【副本】给对方
如果传递的是引用类型的对象: 修改一个变量,另一个变量是会受到影响的,因为大家操作其实是同一个【地址值】
5. 重载
6. 匿名函数
7. 闭包
四、分支结构
- if分支
- switch分支
switch(变量/表达式){
case 值1:
操作1;
break;
case 值2:
操作2;
break;
default:
默认操作;
}
特殊:1、case的比较不带隐式转换,加parseInt(prompt)
面试题:if vs switch
1、switch...case...
缺点:必须要知道准确的结果才能使用,不能做范围判断(也就是case +具体值)
好处:执行效率相对较高
2、if...else
缺点:执行效率相对较低
优点:可以是范围判断(也就是>xxx等)
五、循环结构
- while
var 循环变量=几;
while(循环条件){
循环体;
循环变量的变化;
}
- do...while
var 循环变量=几;
do{
循环体;
循环变量的变化;
} while(循环条件)
面试题:while 和 do...while的区别
只看第一次:如果第一次大家都满足,两者没有区别
如果第一次不满足,while一次都不执行,do...while至少会执行一次
- for
for(var 循环变量=几;循环条件;变量的变化){
循环体;
}
六、数组
1. 基础概念
什么是数组:在一个内存(变量)中保存了多个数据的一个集合结构
何时:只要存储的多个相关的数据,都要用数组集中保存;
为什么:一个好的数据结构,可以极大的提升我们程序员的开发效率
2. 创建
*1、直接量:var arr=[值1,...];
2、构造函数:var arr=new Array(值1,...);
第二种方式还有一个坑:var arr=new Array(num);//创建一个长度num的空数组 (num为纯数字)
3. 访问和修改
访问:数组名[下标]; -- 当前元素
添加/修改:数组名[下标]=新值;
特殊:读取元素,下标越界 -- 返回undefined
添加元素,下标越界 -- 下标不在连续,导致变成一个稀疏数组
4. 数组的三大不限制
1、不限制长度 2、不限制类型 3、不限制下标越界(不好)
5. 数组的唯一属性
数组名.length:获取当此数组的长度
三个固定套路:
1、末尾添加:arr[arr.length]=新值;
2、获取倒数第n个:arr[arr.length-n];
3、删除倒数n个:arr.length-=n
6. 遍历数组
对数组中每个元素执行相同 或 相似的操作
for(var i=0;i<arr.length;i++){
arr[i];//当前次元素
}
7. 释放一个引用类型
请你看清楚你的这个引用类型的数据有几个变量引用着,每个变量都要释放才会真正释放干净
建议:我们的代码都要封装在一个函数中,函数中的变量会自动释放
8. 关联(hash)数组
索引数组:下标都是由数字组成的数组
关联数组:下标是可以自定义的
为什么自定义:索引数组的下标无具体的意义,不便于查找
如何使用:
1、创建:2步
a.创建空数组:var arr=[];
b.为数组添加下标并且添加元素:arr["自定义下标"]=新值;**
2、访问元素:arr["自定义下标"]
3、强调:hash数组length永远失效,永远为0!
遍历hash数组,不能使用for循环,必须使用for in循环 - 专门用于遍历数组的
for(var i in arr){
i; //i为下标
}
for in虽然不能定义从哪里开始,到哪里结束,专门用于遍历数组的,既可以遍历索引数组也可以遍历hash数组
4、***hash数组的原理:
hash算法:将字符串,计算出一个尽量不重复的数字(地址值),字符串内容相同,则计算出来的数字也一定是相同的
添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到这个地址之中
获取元素:将指定的自定义下标交给hash算法,得到一个和当初保存时一样的数字(地址值),通过地址就找到当前保存的数据
5、js里面的一切东西都是对象,除了undefined和null,一切对象的底层都是hash数组
9. 二维数组
数组的元素,又引用着另一个数组
何时:在一个数组内,希望再次细分每个分类
创建:
var arr=[ [数组1],
[数组2],
[数组3],
...
];
访问:arr[行下标][列下标];
特殊:列下标越界,返回undefined
行下标越界,报错,因为undefined不能使用[]
遍历二维数组:必然两层循环:外层循环控制行,内层循环控制列
for(var r=0;r<arr.length;r++){
for(var c=0;c<arr[r].length;c++){
console.log(arr[r][c])
}
}
七、数组的API
1. 数组转字符串——arr.join("自定义连接符")
1、笔试题:将数组里面的内容拼接为一句话/单词;
无缝拼接:var str=arr.join("");
2、将数组拼接为DOM页面元素
var arr=["北京","南京","西京","东京","重庆"]
//转为字符串,并且拼接好标签
var str= **"<** **开始>"+arr.join("</结束><开始>")+"</结束>";**
//渲染到DOM树上
elem.innerHTML=str;
2. 数组拼接——arr.concat("新元素")
3. 截取子数组——arr.slice(starti,endi+1)
1、不修改原数组,只会返回一个新子数组
2、含头不含尾
3、endi可以省略不写,会从starti位置一直截取到末尾
4、其实两个实参都可以省略 - 从头截到尾,深拷贝,和以前的按值传递(浅拷贝)不同,一个修改不会影响到另一个
5、支持负数参数,-1代表倒数第一个
***以上的API都不是会修改原数组,其余都会修改原数组
4. 删除、插入、替换——arr.splice(starti,n,...)
删除:var dels=arr.splice(starti,n); //n代表删除的个数
插入:arr.splice(starti,0,值1,...);
替换:var dels=arr.splice(starti,n,值1,...);
5. 翻转数组——arr.reverse-没用
6. 排序——arr.sort(function(a,b){return a-b})
1、面试/笔试:手写冒泡排序:从第一个元素开始,依次比较相邻的两个元素,只要前一个元素>后一个元素,两者就交换位置
for(var j=1;j<arr.length;j++){
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
var middle=arr[i];
arr[i]=arr[i+1];
arr[i+1]=middle;
}
}
}
2、正式开发中:排序的API
arr.sort(function(a,b){return a-b;})
7. 栈和队列
添加元素和删除元素的新方法
1、栈:其实就是数组,只不过是一端封闭,只能从另一端进出的数组
何时:优先使用最新的数据,现实生活中,情况不多:公交车、电梯...
如何:
开头进:arr.unshift(新值,...);//添加元素的新方式,向前添加,缺陷:导致其余元素的下标发生改变
开头出:var first=arr.shift();//删除元素的新方式,向前删除,缺陷:导致其余元素的下标发生改变
结尾进:arr.push(新值,...); //添加元素的新方式,向后添加,完全等效于arr[arr.length]或者arr.concat,但arr.push更简单,一般用这个
结尾出:var last=arr.pop();//删除元素的新方式,向后删除
2、队列:其实就是数组,只不过是一端进,另一端出
何时:根据先来后到的顺序,现实中多得很
开头进:arr.unshift(新值,...);
结尾出:var last=arr.pop();
*结尾进:arr.push(新值,...);
开头出:var first=arr.shift();
案例:淡入谈出轮播--未封装版
记得更换图片路径,引入iconfont
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="font/iconfont.css">
<style>
/* <!-- 轮播 --> */
.banner {
height: 450px;
position: relative;
}
.banner .imgs {
position: relative;
height: 450px;
}
.banner img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: all 0.6s;
}
.banner ul {
position: absolute;
bottom: 40px;
left: 50%;
margin-left: -60px;
width: 120px;
text-align: center;
}
.banner img.active {
opacity: 1;
}
.banner li.active {
background: rgba(255, 255, 255, 0.9);
}
.banner li {
width: 10px;
height: 10px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
display: inline-block;
margin: 0 5px;
cursor: pointer;
}
.banner button {
border: 0;
width: 50px;
height: 50px;
border-radius: 50%;
background: rgba(4, 4, 4, 0.1);
position: absolute;
cursor: pointer;
position: absolute;
top: 50%;
margin-top: -25px;
}
.banner button:nth-of-type(1) {
left: 50px;
}
.banner button:nth-of-type(2) {
right: 50px;
}
.banner button:hover {
background: rgba(4, 4, 4, 0.4);
}
.banner button:active {
background: rgba(3, 3, 3, 0.8);
}
.banner .iconfont {
font-size: 30px;
color: #fff;
}
</style>
</head>
<body>
<div class="banner">
<div class="imgs">
<img class="active" src="images/index/lunbo-4.jpg" alt="">
<img src="images/index/lunbo.jpg" alt="">
<img src="images/index/lunbo-3.jpg" alt="">
<img src="images/index/lunbo-2.jpg" alt="">
<img src="images/index/lunbo-1.jpg" alt="">
</div>
<button><i class="iconfont"></i></button>
<button><i class="iconfont"></i></button>
<ul>
<li class="active" yj="0"></li>
<li yj="1"></li>
<li yj="2"></li>
<li yj="3"></li>
<li yj="4"></li>
</ul>
</div>
<script>
//轮播
var ban = document.getElementsByClassName("banner")[0], btnS = ban.getElementsByTagName("button"), imgS = ban.firstElementChild.children, liS = ban.getElementsByTagName("li"), j = 0;
for (var i = 0; i < btnS.length; i++) {
btnS[i].onclick = function () {
if (this.firstElementChild.innerHTML == "") {
j--;
j == -1 && (j = liS.length - 1);
for (var i in liS) {
imgS[i].className = "";
liS[i].className = "";
}
imgS[j].className = "active";
liS[j].className = "active";
} else {
j++;
j == liS.length && (j = 0);
for (var i in liS) {
imgS[i].className = "";
liS[i].className = "";
}
imgS[j].className = "active";
liS[j].className = "active";
}
}
}
for (var i in liS) {
liS[i].onclick = function () {
j = this.getAttribute("yj");
for (var i in liS) {
imgS[i].className = "";
liS[i].className = "";
}
imgS[j].className = "active";
liS[j].className = "active";
}
}
timer = setInterval(function () {
j++;
j == liS.length && (j = 0);
for (var i in liS) {
imgS[i].className = "";
liS[i].className = "";
}
imgS[j].className = "active";
liS[j].className = "active";
}, 3000)
ban.onmouseenter = function () {
clearInterval(timer);
}
ban.onmouseleave = function () {
timer = setInterval(function () {
j++;
j == liS.length && (j = 0);
for (var i in liS) {
imgS[i].className = "";
liS[i].className = "";
}
imgS[j].className = "active";
liS[j].className = "active";
}, 2500)
}
</script>
</body>
</html>