javascript第二周学会写轮播

将将将将~我们来到了第二周的学习,只要学过了,就都不会觉得,这周我们会学习API,简化底层,但轮播还是得自己写

一、***数据类型转换

为什么?页面上的一切数据都是字符串类型,有可能做些操作的时候(+运算)不适合,需要先转换,再操作

1、强制类型转换:

  1. 转字符串 a.XX.toString;
    b.String(xx);
    (都没什么用,因为页面的一切元素都是字符串)
  2. 转数字

a.**parseInt(xx);

从左到右依次读取,碰到非字符串就停下,不认识小数点;

b.**parseFloat(xx);

同parseInt,但认识第一个小数点; c.Number(xx);--不如隐式转化

  1. 转布尔
    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. 闭包

四、分支结构

  1. if分支
  2. switch分支
switch(变量/表达式){
              case1:
              操作1;
              break;
              case2:
              操作2;
              break;
              default:
              默认操作;
       }

特殊:1、case的比较不带隐式转换,加parseInt(prompt)
面试题:if  vs  switch

         1、switch...case...
缺点:必须要知道准确的结果才能使用,不能做范围判断(也就是case  +具体值)
好处:执行效率相对较高

         2、if...else
缺点:执行效率相对较低
优点:可以是范围判断(也就是>xxx等)

五、循环结构

  1. while
var 循环变量=几;
           while(循环条件){
                循环体;
                循环变量的变化;
          }
  1. do...while
var 循环变量=几;
           do{
                循环体;
                循环变量的变化;
          } while(循环条件)

面试题:while 和 do...while的区别

只看第一次:如果第一次大家都满足,两者没有区别
如果第一次不满足,while一次都不执行,do...while至少会执行一次

  1. 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">&#xe6af;</i></button>
        <button><i class="iconfont">&#xe6ac;</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>