鸿蒙开发之JavaScript学习(一文掌握)

JavaScript

一、任务概述

编程语言是一个复杂的、繁琐的、原理概念居多的内容,不是几天就可以完全掌握的,需要不断的编写、练习、处理各种错误来积累经验,逐步加强对语言的理解与编程能力。

本章节的宗旨在于帮助学员了解程序,了解编程语言,掌握应用程序开发的核心思想,锻炼分析、逻辑等各方面。这些都是开发者必须要拥有的最基本的能力。
同时,鸿蒙系统也是基于js语言为核心的,掌握JavaScript对鸿蒙开发尤其重要。

二、任务目标

  • 了解语言概念、标准、原理
  • 掌握语言的特性,数据的处理
  • 掌握语言与计算机以及用户之间的交互
  • 锻炼思路、逻辑、提升应用程序的开发能力
  • 养成良好的代码编写习惯,了解企业级应用开发标准

三、任务步骤

1、语言概述
JavaScript(以下简称:js)是互联网中,最流行的脚本语言,由美国ECMA小组负责维护的。

在2015年,ECMA发布了6.0的标准,全称:**ECMAScript 6.0**,它与之前的标准完全不同,代表着一个全新的时代,直到今天,**ES6**依然是后续版本的一个重要的基础标准。

ES6引入了许多新特性,旨在使js适用于编写复杂的大型应用程序,并成为企业级开发语言。这些特性提高了编码效率和代码质量,使JavaScript语言更加成熟和完整。

js是弱语言,解释执行的,它由浏览器中的js引擎负责读取,解释,运行。浏览器js引擎会读取一行,解释一行,执行一行,因此,js代码的先后顺序尤其需要注意。
2、js的十大优越性
  1. 易学易用: JavaScript的语法与许多其他编程语言相似,特别是与C和Java有很多相似之处。这使得许多开发人员能够相对容易地学习和使用JavaScript。
  2. 广泛的支持: JavaScript是Web开发的核心语言之一,几乎所有现代浏览器都支持JavaScript。这使得JavaScript成为前端开发的首选语言。
  3. 多范式: JavaScript是一种多范式的编程语言,支持面向对象编程(OOP)、函数式编程(FP)和命令式编程。这种灵活性允许开发人员采用不同的编程风格来解决问题。
  4. 动态类型: JavaScript是一种动态类型语言,不需要显式声明变量的类型。这简化了代码编写过程,同时也增加了灵活性。
  5. 强大的标准库: JavaScript拥有丰富的标准库,包括用于处理字符串、日期、数组、对象等的内置函数。这些内置函数提供了大量功能,使得开发任务更加高效。
  6. 跨平台: JavaScript不仅在Web浏览器中运行,还可以用于服务器端开发(Node.js),实现了前后端代码的共享,提高了开发效率。
  7. 活跃的社区: JavaScript拥有庞大而活跃的开发社区,提供了丰富的教程、库和工具。这使得开发人员能够快速解决问题和获取支持。
  8. JSON支持: JavaScript对象表示法(JSON)是一种轻量级的数据交换格式,与JavaScript密切相关。JavaScript原生支持JSON,这在Web应用程序中用于数据交换非常有用。
  9. 事件驱动: JavaScript是事件驱动的语言,适用于创建响应用户交互的Web应用程序。这种特性使得JavaScript非常适合构建富交互性的应用程序。
  10. 动态网页交互: JavaScript使得网页可以动态地响应用户的操作,从而提供更丰富和交互性更强的用户体验。
3、js脚本的定义方式
  • 第一种:内联js
    在一个html文档的任意位置,嵌入script标签。js代码写在其中。
    优点:加快页面加载的速度,减少服务器的请求
    缺点:js代码只对当前页面有效
<script type="text/javascript">
        //这里定义js代码
</script>
  • 第二种:外联js脚本
    首先将js代码单独定义到一个外部的,.js结尾的文件中,通常我们都会放入js目录下
    然后在页面的任意位置,定义script标签,导入代码。
    优点:js单独的脚本,代码易于管理,易于维护,所有网页都可以使用
    缺点:浏览器需要单独下载这个文件到本地
<!--
    外部文件:  js/index.js
    外部文件是导入到这里的,两个标签中定义的任何内容都将被覆盖
-->
<script src="js/index.js" type="text/javascript"></script>

type=“text/javascript”:是用来告知浏览器,标签内部是什么内容,浏览器应该如何处理,现在高版本的浏览器,这个属性标签都可以不用定义
它默认就是:文本形式的/js脚本代码

总结:
这两种方式都是优选的方式,按照当前具体的需要而决定。
如果页面比较独立,且希望用户能快速的打开预览到,推荐使用第一种:内联
如果是一些共用的功能,很多页面都需要使用的,那么就用第二种:外联
两种方式可以同时存在,且定义多个。像京东首页:

在这里插入图片描述

注意

如果是直接执行的代码,不管是内联还是外联,通常定义在网页的尾部,以确保网页内容全部被浏览器读取到再执行。

如果是定义的函数等,不是默认就执行的代码,需要定义在网页的标签中。

4、注释

注释对于初学者或者开发者而言都是非常重要的要素。高质量的代码中,至少要保证20%左右的注释。注释的作用是为了简介明了的标记代码的作用、功能等。提升代码的可阅读性。

对于初学者而言,注释能帮助我们明确代码的作用,梳理开发的流程,提升我们的思路与条理性。

<script>

    //单行注释:脚本运行时,自动忽略

    /*
        多行注释:
        脚本运行时,自动忽略
    */

</script>
5、控制台与输出

js代码在编写的时候,支持将指定的内容输出到html页面或浏览器的控制台中,方便开发者进行代码调试、预览数据等操作。

5.1、输出到网页中
<script>
    //将指定内容输出到网页中
    //小括号内,如果是字符内容,需要添加单或双引号
    //数值内容可以直接输出
    //允许使用 +加号 进行内容的组合
    //允许输出html标签,浏览器会进行解析
    document.write('字符内容');
    document.write(123456);
</script>

在这里插入图片描述

5.2、输出到控制台

需要在浏览器中,按键盘 [F12],进入开发者模式,选择<控制台>标签

<script>
    //将指定内容输出到控制台
    //小括号内,如果是字符内容,需要添加单或双引号
    //数值内容可以直接输出
    //控制台仅用于输出结果的预览
    console.log('字符内容');
    console.log(123456);
</script>

在这里插入图片描述

总结

document.write():输出到页面的操作,通常都用于脚本通过网页与用户进行的一个交互,实际开发中,都是输出一些网页标签内容,应用不多。

console.log():输出到控制台的操作,用于开发者在脚本开发过程中,测试或预览数据,是常用的输出操作。

6、数据类型
类型说明
number所有的数值(整数、浮点小数)
string由单引号或双引号包括的一组字符内容
boolean布尔类型,只有2个值,都是关键字:true, false
undefined特殊类型,定义了变量,但是从来没有赋值过
null特殊类型,定义了变量,但是它的引用不存在
Object对象类型,执行一个大括号{}包住的实体
Symbol()特殊类型,用于标记或符号

我们可以通过 typeof() 这个方法预览到指定数据的类型。

<script>
      //基本的数据,可以通过 typeof()方法,预览到它的类型
      console.log( typeof(123) );
      console.log( typeof(3.14) );
      console.log( typeof('aaa') );
      console.log( typeof("abc") );
      console.log( typeof(true) );
      console.log( typeof(false) );

      //特殊类型,由特定情况导致,可以直接输出预览
      console.log( undefined );
      console.log( null );
      console.log( Object() );
      console.log( Symbol() );
</script>

在这里插入图片描述

7、全局变量、局部变量 与 常量
7.1、标识符
在脚本程序在运行过程中,我们需要将操作的数据存放在内存上,这时,我们会得到一个内存地址,类似:0x0000000A 1000000F。首先,这个地址会改变的,其次就是让开发者记住这个地址也不现实,因此,语言就允许开发者自己定义一个名称,它来帮我们对应到这个内存地址,这个就是标识符。
标识符的命名规则:
    1、区分大小写
    2、不可以使用关键字
    3、首字母可以是:字母、下划线、$
       其余部分可以是:字母、数字、下划线
    4、标识符应该有一定的描述性或意义

正确的标识符:
    id, username, NickName, city01, cate_id
7.2、全局变量
//语法格式
var 标识符 =;

var声明的变量,js会将它放入当前浏览器窗口对象:window下面。只要当前页面不关闭,其他网页和脚本都可以通过:(window.标识符) 获取到。当某些特定的数据,需要跨页面跨脚本使用的时候,我们才会考虑它,在项目开发时,尽量少用或不用。

由于它的特殊性,var是允许重复声明同名的变量的。新的覆盖老的。

<script>
    //创建全局变量
    var name = '葫芦娃';

    //当前页面脚本自己使用    
    console.log(name);          //自动查找,会找到window下面
    console.log(window.name);   //指定window下
</script>
7.3、局部变量
let 标识符 =;

局部变量是ES6新增的一个特性,使用let声明。局部变量可以更好的保护数据,同时降低浏览器的内存消耗。在正常的脚本开发时,都应该首选局部变量。

let 不允许重复声明同名的变量。

<script>
    //创建局部变量:只用于当前网页或脚本
    let name = '葫芦娃';

    //当前页面脚本自己使用    
    console.log(name);          //当前位置调用
    console.log(window.name);   //【不存在,不显示内容】

</script>
7.4、常量
const 标识符 =;

常量也是ES6新增加的特性,它与局部变量一样,作用于当前范围,唯一的区别就是 const声明的变量,必须在声明时赋值,且一旦有值,就禁止修改。因此称之为:常量。常量通常定义一些比较特殊的重要或固定数据,禁止任意操作,只允许使用的时候

const 不允许重复声明同名的变量。

<script>
      //创建常量
      const name = '葫芦娃';

      //当前页面脚本自己使用    
      console.log(name); 

      //尝试修改:直接控制台Error
      //Uncaught TypeError: Assignment to constant variable.
      name = '蝎子精';
</script>
7.5、格式化输出

当我们有了变量之后,就可以使用格式化输出的功能:

<script>

    //定义变量
    let id = 555;
    let name = '葫芦娃';

    //格式化输出
    //利用反引号定义整个语句
    //利用${}作为占位符,占据这个位置
    //${}定义变量名称,将指定变量的值替换到当前位置
    console.log(`编号:${id};姓名:${name}`);

    //显示结果:
    //    编号:555;姓名:葫芦娃;

</script>
8、运算符

计算机只执行运算,所有的操作与结果,都是通过计算机运算出来的。不同的数据,计算机的运算方式不同。运算符存在优先级状态。

如果遇到无法计算的时候,显示结果:NaN

8.1、算数运算符
运算符说明
()优先执行内部的运算
*乘积
/除法,得到的是结果,如果除不尽将会得到一个精度
%莫,得到的是余数
+加法,如果存在单双引号的字符串,则变成内容拼接
-减法
  • 注意:
    由于js是弱语言,即使提供的是带有单或双引号的字符串,如果引号中的内容可以进行当前计算,它还是会计算出结果的。
<script>    
    //运算注意点

    //除法:得到的是结果,如果除不尽,得到一个精度结果
    console.log(10/3);    //3.3333333333333335

    //莫:得到的是余数
    console.log(10%3);    //1  (商3,余1)
    console.log(5%6);     //5  (商不存在,余5)

    //如果加法中带有引号内容,将变成字符串组合
    console.log(5 + '6');   //56

</script>
8.2、关系运算

计算左右两边最终结果的关系是否成立,返回boolean类型的结果:true 或 false

运算符说明附加
<小于
<=小于等于
>大于
>=大于等于
==值等只判断值
===恒等不仅判断值,同时数据类型也必须相同
!=值不等只判断值
!===恒不等不仅判断值,同时类型也必须不同
  • 注意:
    如果只是临时的数据判断处理,推荐使用值判断,速度快。
    如果是一些重要的核心数据,推荐使用恒判断,更安全。
<script>
    //运算注意点

    //值等:只判断值
    console.log(5=='5');  //结果:true
    console.log(5!='6');  //结果:true

    //恒等:不仅值相同,类型也判断
    console.log(5==='5');  //结果:false
    console.log(5!==6);    //结果:false (值成立的,但是类型相同了)

</script>
8.3、逻辑运算

计算左右两边最终结果的逻辑是否成立,返回boolean类型的结果:true 或 false

运算符说明附加
!逻辑结果取反,true的时候返回false,false的时候返回true
&&与、并且左右两边都是true时为true,其他都是false
|或者
<script>
    //运算注意点

    //以下三个逻辑表达式,第三个往往会绕进去,我们这样理解:
    //true表示苹果,false表示西瓜,现在要一杯苹果汁:
    true  &&  true         //true
    true  &&  false        //false
    false &&  false        //false

</script>
8.4、三目(元)运算

三目运算,又叫做问号表达式,它带有判断功能,可以简单的通过一个判断得到需要的结果。
问号左边是一个关系或逻辑运算,得到true或false的结果
true的时候,返回冒号左边的结果。false的时候,返回冒号右边的结果。

<script>
    //定义变量
    let a = 5;
    let b = 6;

    //三目运算
    //先执行关系运算,得到结果:false
    //然后返回冒号右边,b的结果:6
    let max = a>b?a:b;

    //结果
    console.log(max);  //6

</script>
8.5、组合运算

在当前的基础上,直接进行后面一个数据的算数运算:

<script>
    //组合运算包括:+=  -=  *=  /=  %=  

    //变量
    let a = 5;

    //组合运算:加法
    a += 6;            //在a现有的基础上,再加上6

    //结果
    console.log(a);    // 11

</script>
8.6、累加累减

再原有的基础上 +1 或 -1。由于符号前后位置不同,会导致在具体运算公式里面,产生的结果也不同。

运算符说明赋值或运算公式中
++aa+1先执行完毕,在执行赋值或运算
–aa-1先执行完毕,在执行赋值或运算
a++a=a+1先用原来的值进行运算或赋值,之后再进行+1
a–a=a-1先用原来的值进行运算或赋值,之后再进行-1
<script>
    //声明变量
    let a = 1;

    //单独执行,都是独立的,不存在特殊操作
    a++;
    a++;
    ++a;
    ++a;

    //结果
    console.log(a);   //5

</script>
<script>
    //当遇到赋值的时候,说明后做递增
    //先赋值,再执行+1
    let a = 1;
    let x = a++;            // x=a,   a=a+1
    console.log(x);         // 1

    //说明先执行递增,然后再执行赋值
    let b = 1;
    let y = ++b;            // b=b+1, 然后再赋值
    console.log(y);         // 2

</script>
9、流程控制-选择结构

选择结构的作用是让程序在运行过程中,通过判断来决定到底执行那一部分的代码,可以决定一个脚本程序最终的走向。

9.1、if判断

if判断适合需要考虑多个不同条件,涉及到复杂的逻辑或需要灵活性,针对一个区间的情况。它主要以一个boolean类型的结果来决定是否执行代码。

//if单分支
//小括号中的最终结果为true的时候,就执行内部代码
//通常用于定义在特定情况下,要执行的代码操作
if(关系或逻辑){
    //代码块
}
//if双分支
//当小括号结果是true是执行if的代码,false的时候执行else的代码
//这种属于二选一的情况,也就是说,在当前位置,两端代码必须执行其一
if(关系或逻辑){
    //true:代码块
}
else{
    //false:代码块
}
//if多分支
//从第一个if开始进行判断,当某一个if的结果为true时,就执行当前的代码
//false的时候,就跳过,进入下一个
//else if用于增加新的可能性,新的情况,允许定义N
//当以上所有if都不成立,就执行else的代码
//这属于多选一的情况,当满足特定条件就执行指定代码,否则执行else默认代码
if(关系或逻辑){
    //true:代码块
}
else if(关系或逻辑){
    //true:代码块
}
else{
    //false:代码块
}

代码案例

<script>
        //判断变量x的值是否是偶数?
        var x=5;

        if(x%2==0){
            //true
            document.write('偶数');
        }
        else{
            //false
            document.write('奇数');
        }

        //【如果只有一行代码,js是允许不写大括号的】
        //【不推荐】
        if(x%2==0)
            document.write('偶数');
        else
            document.write('奇数');
</script>
<script>
    //按照分数划分等级:
        // 60分以下:不及格
        // 60-69:差
        // 70-79:一般
        // 80-89:还可以
        // 90以上:优秀
        var sco=100;

        if(sco>=0 && sco<=59){
            document.write('不及格');
        }
        else if(sco>=60 && sco<=69){
            document.write('差');
        }
        else if(sco>=70 && sco<=79){
            document.write('一般');
        }
        else if(sco>=80 && sco<=89){
            document.write('还可以');
        }
        else if(sco>=90 && sco<=100){
            document.write('优秀');
        }
        else{
            document.write('分数异常,请核实!');
        }
</script>
<script>
    // 只要语法格式正确,可以相互嵌套
        //x的值是否在1-50之间,他是奇数还是偶数?
        var x=66;

        if(x>=1&&x<=50){
            document.write('在:');
            if(x%2==0){
                document.write('偶数');
            }
            else{
                document.write('奇数');
            }
        }
        else{
            document.write('不在:');
            if(x%2==0){
                document.write('偶数');
            }
            else{
                document.write('奇数');
            }
        }
</script>
<script>
    //给定年和月,返回这个月有多少天?
        var y=2000, m=2;

        //如果每一个月都有特殊操作代码:1个if,11个elseif,再加else
        //如果类同的情况,代码是一样的
        if(m==1||m==3||m==5||m==7||m==8||m==10||m==12){
            document.write('31天');
        }
        else if(m==4||m==6||m==9||m==11){
            document.write('30天');
        }
        else if(m==2){
            //闰年
            if(y%4==0 && y%100!=0 || y%400==0){
                document.write('29天');
            }
            else{
                document.write('28天');
            }
        }
        else{
            document.write('没有这个月份!');
        }
</script>
9.2、switch判断

switch判断比较适合情况不多,而且都是单个固定数据的判断。

//语法格式
//switch会先执行小括号中的表达式,得到最终结果
//然后将最终结果带入内部,与每一个case后的值进行 == 的判断
//如果成立,就执行代码,然后遇到break跳出判断
//如果不成立,就进行下一个case的判断,如果都没有满足,就执行default的代码
//注意:
//    1、case后面,必须是一个具体的值
//    2、default可有可无
switch(表达式){
    case1:
        //代码块
        break;
    case2:
        //代码块
        break;
    ......
    default:
        //代码块
        break;
}

代码案例

<script>
    // 有三个等级A,B,C,显示对应的奖励。
        var level='A';

        switch(level){
            case 'A':
                document.write('免死金牌!');
                break;
            case 'B':
                document.write('罚抄3遍笔记!');
                break;
            case 'C':
                document.write('罚抄300遍笔记!');
                break;
            default:
                document.write('??????');
                break;
        }
</script>

在实际开发中,使用switch的情况不多,开发者不愿意使用switch,代码可读性与编辑不如if方便。

但是switch有一个特殊的能力,是if代替不了的 :【switch贯穿】
当case中,没有break,代码从一个case执行到另一个case。

<script>
        //实例:利用switch贯穿,实现年月返回天数?
        var y=2000, m=11;

        switch(m){
            case 1: 
            case 3: 
            case 5: 
            case 7: 
            case 8: 
            case 10: 
            case 12:  document.write('31天'); 
                      break;            
            case 4: 
            case 6: 
            case 9: 
            case 11: document.write('30天'); 
                      break;            
            case 2: 
                if(y%4==0 && y%100!=0 || y%400==0){
                    document.write('29天');
                }
                else{
                    document.write('28天');
                }
                break;

            default:
                document.write('月份错误!');
                break;
        }
</script>
<script>
        // 给定年,月,日,
        // 利用switch贯穿机制,运算出,这一天是这一年的第几天
        var y=2020, m=8, d=6;

        //提示:
        //    1、需要一个变量,进行统计的,累加天数
        //    2、1月-7月全部天数 + 6: m-1
        //    3、注意case的顺序,1----?月

        //统计变量
        var sum=0;

        //利用贯穿统计天数:1-7
        switch(m-1){
            //case 12: sum+=31;
            case 11: sum+=30;
            case 10: sum+=31;
            case 9: sum+=30;
            case 8: sum+=31;
            case 7: sum+=31;
            case 6: sum+=30;
            case 5: sum+=31;
            case 4: sum+=30;
            case 3: sum+=31;
            case 2: 
                if(y%4==0 && y%100!=0 || y%400==0){
                    sum+=29;
                }
                else{
                    sum+=28;
                }
            case 1: sum+=31;
        }

        //再追加当前月的天数:8
        sum=sum+d;

        //结果
        document.write(sum);
</script>KLASDF       
10、流程控制-循环结构

循环结构的主要功能是让程序,在某一个具体的位置,自动重复执行指定的代码,大大减少代码的编写以及提高开发效率。

CPU:100%
注意:
    学习循环语法结构的时候,同学们一定要慢一点,仔细一点,以免导致循环逻辑
    错误,进入《无限循环》。

    如果进入无限循环,此时浏览器会抢占CPU,导致CPU 100%,此时必须赶紧
    关闭浏览器,释放CPU。如果浏览器卡住,需要强制终止进程。
10.1、continue 和 break

在循环的代码块中,我们会使用到2个关键字 continue 和 break,用于循环过程中,跳过当场循环或直接跳出循环,以达到终止的目的。

  • continue:终止后续代码执行,直接进入下一次循环

  • break:终止后续代码执行,直接跳出循环

10.2、while循环
//语法格式
//小括号中的运算表达式最终结果true就执行,false就终止
while(关系或逻辑){
    //代码块
    //continue 或 break
}

while循环的语法格式比较简单,只要小括号的结果是true就执行代码,false就终止。代码块中支持 continue 或 break。

代码案例

<script>
    //循环输出1-5

    //声明控制变量
    let i = 1;

    //定义循环
    while(i<=5){
        console.log(i);   //输出循环控制变量
        i++;              //【重点】:控制变量的更改,最终目的是让
                          // 循环的判断得到false,已达到终止循环的目的
    }
</script>
<script>
    //循环输出1-10,但是不要5
    let i=1;

    while(i<=10){

        if(i==5){
            i++;       //【重点】:如果这里不++,会导致无限循环
            continue;  //跳过当前循环,直接进入下一次
        }

        console.log(i);
        i++;

    }
</script>
10.3、for循环
//语法格式
//表达式一:
//    它是一个循环控制变量的声明,当第一次进入循环时,它会执行一次,仅此一次
//表达式二:
//    它是一个关系或逻辑操作,用于得到true或false已达到执行或终止循环的目的
//表达式三
//    它是对循环控制变量的操作,目的是为了满足表达式二可以得到false
for(表达式一; 表达式二; 表达式三){
    //代码块
    //continue 或 break
}

for循环的语法格式比较固定,这样对于循环的执行操作就更加明晰,在实际开发中,for循环使用较多。

代码案例

<script>
    //循环输出1-5    
    for(let i=1; i<=5; i++){
        console.log(i);
    }

    //【注意】【注意】【注意】:
    //    当前案例运行完毕,控制台显示的结果 1 2 3 4 5
    //    也就是说,当判断成立:true
    //    就进入循环,执行代码,
    //    代码结束后再执行 i++ 的

</script>
<script>
    //循环输出1-10,但是不要5
    for(var i=1; i<=10; i++){
        if(i==5){
            continue;    //跳过,代码结束,自动执行i++,然后进入下一次循环
        }
        console.log(i);
    }
</script>
10.4、循环逻辑锻炼
<script>
    //利用for循环实现 1-100 的累加之和

    //循环输出1-100之间的所有的偶数

    //循环输出1-100之间,所有的,可以同时被3、5整除的数值

    //果园里面有一堆桃子和一只猴子,
    //第一天,猴子吃了一半的桃子,然后丢掉了一个坏的
    //第二天,猴子又吃了一半的桃子,也丢掉了一个坏的
    //如此类推,到了第七天,只有1个桃子
    //问:果园里一开始,一共有多少个桃子?
    //提示:逆向思维,已经知道最后的结果,那么就倒推

</script>
10.5、逻辑锻炼答案
<script>
    //利用for循环实现 1-100 的累加之和
    let sum = 0;
    for(let i=1; i<=100; i++){
        sum += i;
    }
    console.log(sum);


    //循环输出1-100之间的所有的偶数
    for(let i=1; i<=100; i++){
        if(i%2==0){
            console.log(i);
        }
    }


    //循环输出1-100之间,所有的,可以同时被3、5整除的数值
    for(let i=1; i<=100; i++){
        if(i%3==0 && i%5==0){
            console.log(i);
        }
    }


    //果园里面有一堆桃子和一只猴子,
    //第一天,猴子吃了一半的桃子,然后丢掉了一个坏的
    //第二天,猴子又吃了一半的桃子,也丢掉了一个坏的
    //如此类推,到了第七天,只有1个桃子
    //问:果园里一开始,一共有多少个桃子?
    let t = 1;                         //第七天的1个桃子
    for(let d=6; d>=1; d--){           //往前推,逆向思维
        t = (t+1)*2;                   //当天的桃子 = (剩下的桃子+1)*2
    }
    console.log(t);

</script>
11、嵌套循环

只要语法格式正确,循环是可以嵌套的,当嵌套循环产生时,代码的执行次数会几何式的增长,嵌套循环的使用,可以帮我们解决更加复杂的逻辑需求。

代码案例

<script>
    //利用嵌套循环,在网页上输出以下图形
    //*****
    //*****
    //*****
    //*****
    //*****

    //解题思路
    //    1、外层循环负责行,这里有5行,循环5次
    //    2、内层循环负责列,每一行是5列
    //    3、当一行中,所有的列输出完毕后,输出一个<br />换行

    for(let row=1; row<=5; row++){
        for(let col=1; col<=5; col++){
            document.write('*');
        }
        document.write('<br />');
    }

</script>
11.1、逻辑锻炼
<script>
    //在页面中绘制出以下图形
    //注意外层与内层循环的关系,循环控制变量是可以使用的,彼此可以对应
    //逆向思维,不要老想着1-5,5-1也是5次哦

    //图形一
    *
    **
    ***
    ****
    *****

    //图形二
    *****
    ****
    ***
    **
    *
</script>
11.2、逻辑锻炼-答案
<script>
    //利用嵌套循环,在网页上输出以下图形
    //*
    //**
    //***
    //****
    //*****

    //解题思路
    //    1、外层循环负责行,这里有5行,循环5次
    //    2、内层循环负责列,列的数量和行号对应,执行的次数就和行一样
    //    3、当一行中,所有的列输出完毕后,输出一个<br />换行

    for(let row=1; row<=5; row++){
        for(let col=1; col<=row; col++){
            document.write('*');
        }
        document.write('<br />');
    }

</script>
<script>
    //利用嵌套循环,在网页上输出以下图形
    //*****
    //****
    //***
    //**
    //*

    //解题思路
    //    1、和上一题一样的,只是倒过来了
    //       那么就是逆向思维,不要只想着1-5,5次
    //       5-1,也是5次,把行倒过来,从大到小
    //    2、当一行中,所有的列输出完毕后,输出一个<br />换行

    for(let row=5; row>=1; row--){
        for(let col=1; col<=row; col++){
            document.write('*');
        }
        document.write('<br />');
    }

</script>
12、数组Array
12.1、什么是数组?

将若干个数据,按照有序的方式,排列在一起的对象,称之为:数组。
数组中,每一个元素都是变量,他们都是独立的,可以是任意数据类型。

12.2、有序的方式-索引

在计算机中,非负即正,0是正数,0是偶数,0是第一个数值。
数组中,每一个元素就是使用数值来进行排列的,我们称之为:索引/下标

索引从0开始,升序。0就表示数组中的第一个元素,以此类推。

12.3、数组的定义
//创建一个全新的空的数组,里面没有元素
let arr = new Array();

//创建一个新数组,里面有3个元素,索引:0-2
let arr = new Array('aaa', 'bbb', 'ccc');

ES6中,允许快速创建数组,直接利用中括号定义:

//创建一个全新的空的数组,里面没有元素
let arr = [];

//创建一个新数组,里面有3个元素,索引:0-2
let arr = ['aaa', 'bbb', 'ccc'];
12.4、数组的操作

注意:

在js中,语言是允许数组不定义,直接使用的。
但是在企业级的开发中,这种情况是:【明确禁止】
//声明一个数组,默认提供3个元素的值
//这个时候,会创建数组,并且有3个元素,索引:0, 1, 2
//let arr = new Array('aaa', 'bbb', 'ccc');
let arr = ['aaa', 'bbb', 'ccc'];


//调用方法,获取数组元素的【个数】
//索引index: 0 ~ 个数-1
document.write( arr.length );


//获取get 或 设置set 数组指定索引的元素
arr[2] = '葫芦娃';
document.write( arr[2] );


//如果不知道数组有多少个元素,就要最后一个的值
// arr.length-1
document.write( arr[arr.length-1] );
//创建一个空的数组
//let arr = new Array();
let arr = [];

//添加/设置元素
arr[0] = '张三';

//如果自己再添加的时候,跳索引了,中间缺失的,会自动补齐
arr[555] = '李四';            

//元素个数:556个元素,索引:0-555
document.write( arr.length + '个<br />');

//获取
document.write(arr[0] + '<br />');

//自动补齐的元素,值是:undefined
//表示:我帮你创建好了元素,但是你没有提供过值
document.write('自动补齐的:' + arr[100] + '<br />');
12.5、循环遍历

我们可以利用for循环进行数组元素的遍历,这样的操作可以让我们具体的找到数组中的元素,然后进行操作。

//创建数组,5个元素,索引0-4
//let arr = new Array(111, 222, 333, 444, 555);
let arr = [111, 222, 333, 444, 555];

//循环遍历
for(let i=0; i<arr.length; i++){
    document.write( arr[i] + '<br />');
}
12.6、迭代遍历

通过语法定义,自动把每一个元素的值拿出来,赋予自定义的变量
优点:速度块,自动结束,保护数组,数组内容不会被干预
缺点:只能操作那个自定义的变量,无法操作数组元素
关键字:
of : 提取元素的值
in : 提取元素的索引

//定义数组
//let arr = new Array('师傅', '大师兄', '二师兄', '三师弟', '白龙马');
let arr = ['师傅', '大师兄', '二师兄', '三师弟', '白龙马'];

//迭代遍历:of提取值
//name是一个临时遍历,用于接收每一个元素的
for(let name of arr)
{
    //自动从arr中,提取每一个元素的值,
    //赋值给自定义的name变量
    //只能操作变量,和数组无关
    document.write(name + '<br />');
}


//迭代遍历:in提取值
//index是一个临时遍历,用于接收每一个元素的索引
for(let index in arr)
{
    //自动从arr中,提取每一个元素的索引,
    //赋值给自定义的index变量
    document.write(index + '<br />');
}
12.7、数组循环操作案例
//遍历查找
//查找出数组中的最大值以及最大值的索引和最小值及最小值的索引

//解题:
//    数组中,数据与索引是对应的,因此,只要记住索引
//    那么该元素的位置、数据都在了
//    当数组中,只有一个元素的时候,最大、最小、总和、平均值都是
//    当出现新的元素时,就可以开始比较了    

//任意数组
//let arr = new Array(13, 4, -75, -8, 22);
let arr = [13, 4, -75, -8, 22];

//最大最小值的索引变量:默认为第一个元素
let max = 0;
let min = 0;

//开始循环,从第二个元素开始比较
for(let i=1; i<arr.length; i++){
    //判断循环到的元素的值 与 记录索引元素的值
    //如果成立,就更新记录的索引
    if(arr[i]>arr[max]){
        max = i;
    }
    if(arr[i]<arr[min]){
        min = i;
    }
}

console.log(`最大值:${arr[max]};索引:${max}`);
console.log(`最大值:${arr[min]};索引:${min}`);
12.8、冒泡排序法

冒泡排序法是一种叫法,主要的功能就是将数组中的数据,按照从小到大或从大到小的顺序进行排列。

冒泡排序特别适合锻炼逻辑能力,但是它的运行效率非常非常低,实际开发中通常都是禁止使用的。

冒泡排序原理
    当前元素和下一个元素进行比较,如果满足条件,就两个元素交换数据,
    然后往后移动一位,继续和下一个元素进行比较,直到倒数第二个元素为止。
    这样一轮比较完毕后,可以得到一个最大或最小的值放在数组的末尾。
    有多少个元素就执行多少遍,最终实现数据排序
冒泡排序的代码需求
    1、需要两层循环,外层循环主要针对数组中的元素个数,
       内层循环负责元素比较的次数
    2、元素不能直接交换数据的,必须使用第三个临时变量进行过度

代码解析

//外层循环主要针对数组中有多少个元素需要拿出来进行操作的
//  <arr.length 是为了对应好索引
//  -1 是优化,当其他元素都排好了,最后一个元素就不用管
for(int j=0; j<arr.length-1; j++){

    //内层循环主要是针对两个两个元素比较,需要比较多少次
    //  <arr.length 是为了对应好索引
    //  -1  排除错误,最后一个元素不能比较,它后面没有了
    //  -i  是优化,每做完一轮,就已经处理好一个数据了,下一次就不用管了
    for(int i=0; i<arr.length-1-i; i++){
        //判断:用于决定从小到大还是从大到小
        if(arr[i] > arr[i+1]){
            //结束临时变量,将两个元素的值进行交换
            int temp = arr[i];
            arr[i] = arr[i+1];
            arr[i+1] = temp;
        }
    }
}
12.9、数组常用方法
join()
join()方法用于把数组中的所有元素转换一个字符串。
元素是通过指定的分隔符进行分隔的。默认使用逗号作为分隔符

    var arr = [1,2,3];
    console.log(arr.join());      // 1,2,3
    console.log(arr.join("-"));   // 1-2-3
    console.log(arr);             // [1, 2, 3](原数组不变)
push()
push() 方法从数组末尾向数组添加元素,可以添加一个或多个元素。

    var arr = ["Lily","lucy","Tom"];
    var count = arr.push("Jack","Sean");
    console.log(count);  // 5
    console.log(arr);    // ["Lily", "lucy", "Tom", "Jack", "Sean"]

pop()
pop() 方法用于删除数组的最后一个元素并返回删除的元素。

    var item = arr.pop();
    console.log(item);   // Sean
    console.log(arr);    // ["Lily", "lucy", "Tom", "Jack"]
shift()
shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。

    var item = arr.shift();
    console.log(item);   // Jack
    console.log(arr);   // ["Sean", "Lily", "lucy", "Tom"]


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

    var arr = ["Lily","lucy","Tom"];
    var count = arr.unshift("Jack","Sean");
    console.log(count);   // 5
    console.log(arr);   //["Jack", "Sean", "Lily", "lucy", "Tom"]
sort()
sort() 方法用于对数组的元素进行排序。
排序顺序可以是字母或数字,默认排序顺序为按字母升序。

    var arr1 = ["a", "d", "c", "b"];
    console.log(arr1.sort());   // ["a", "b", "c", "d"]

    arr2 = [13, 24, 51, 3];
    console.log(arr2.sort());   // [13, 24, 3, 51]
    console.log(arr2);          // [13, 24, 3, 51](元数组被改变)

reverse()
reverse() 方法用于颠倒数组中元素的顺序。

    var arr = [13, 24, 51, 3];
    console.log(arr.reverse());   //[3, 51, 24, 13]
    console.log(arr);             //[3, 51, 24, 13](原数组改变)
concat()
concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

    //传入的不是数组,则直接把参数添加到数组后面
    var arr = [1,3,5,7];
    var arrCopy = arr.concat(9,[11,13]);
    console.log(arrCopy);   //[1, 3, 5, 7, 9, 11, 13]
    console.log(arr);       //[1, 3, 5, 7](原数组未被修改)

    //传入的是一个二维数组,元素的追加
    var arrCopy2 = arr.concat([9,[11,13]]);
    console.log(arrCopy2);      //[1, 3, 5, 7, 9, Array[2]]
    console.log(arrCopy2[5]);   //[11, 13]
slice()
slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。
slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。
在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。
如果有两个参数,该方法返回起始和结束位置之间的项,但不包括结束位置的项。
当出现负数时,将负数加上数组长度的值(6)来替换该位置的数

    var arr = [1,3,5,7,9,11];
    var arrCopy = arr.slice(1);
    var arrCopy2 = arr.slice(1,4);
    var arrCopy3 = arr.slice(1,-2);  //相当于arr.slice(1,4)
    var arrCopy4 = arr.slice(-4,-1); //相当于arr.slice(2,5)
    console.log(arr);        //[1, 3, 5, 7, 9, 11](原数组没变)
    console.log(arrCopy);    //[3, 5, 7, 9, 11]
    console.log(arrCopy2);   //[3, 5, 7]
    console.log(arrCopy3);   //[3, 5, 7]
    console.log(arrCopy4);   //[5, 7, 9]
splice()
splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。

    //删除元素,并返回删除的元素
    //可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。
    //例如, splice(0,2)会删除数组中的前两项。
    var arr = [1,3,5,7,9,11];
    var arrRemoved = arr.splice(0,2);
    console.log(arr);           //[5, 7, 9, 11]
    console.log(arrRemoved);    //[1, 3]


    //向指定索引处添加元素
    //可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。
    //例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入 4 和 6。
    var array1 = [22, 3, 31, 12];
    array1.splice(1, 0, 12, 35);  //[]
    console.log(array1);          //[22, 12, 35, 3, 31, 12]


    //替换指定索引位置的元素
    //可以向指定位置插入任意数量的项,且同时删除任意数量的项,
    //只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。
    //插入的项数不必与删除的项数相等。
    //例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入 4 和 6。
    const array1 = [22, 3, 31, 12];
    array1.splice(1, 1, 8);   //[3]    
    console.log(array1);      //[22, 8, 31, 12]
indexOf()lastIndexOf()
接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。

indexOf():从数组的开头(位置 0)开始向后查找。
lastIndexOf():从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。
在比较第一个参数与数组中的每一项时,会使用恒等操作符 ===var arr = [1,3,5,7,7,5,3,1];
    console.log(arr.indexOf(5));       //2
    console.log(arr.lastIndexOf(5));   //5
    console.log(arr.indexOf(5,2));     //2
    console.log(arr.lastIndexOf(5,4)); //2
    console.log(arr.indexOf("5"));     //-1
forEach()
forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。
这个方法没有返回值。参数都是 function(遍历的数组内容, 第对应的数组索引, 数组本身)

    var arr = [11, 22, 33, 44, 55];
    arr.forEach(function(x, index, a){
        console.log(x +  |  + index +  |  + (a === arr));
    });

    //输出为:
     11|0|true
     22|1|true
     33|2|true
     44|3|true
     55|4|true
map()
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
该方法不会改变原数组

    var arr = [1, 2, 3, 4, 5];
    var arr2 = arr.map(function(item){
        return item*item;
    });
    console.log(arr2);   //[1, 4, 9, 16, 25]
filter()
filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    var arr2 = arr.filter(function(x, index) {
        return index % 3 === 0 || x >= 8;
    });
    console.log(arr2);  //[1, 4, 7, 8, 9, 10]
fill() es6 新增
fill()方法能使用特定值填充数组中的一个或多个元素。

    //当只是用一个参数时,该方法会用该参数的值填充整个数组。
    let arr = [1, 2, 3,  cc , 5];
    arr.fill(1);
    console.log(arr);   //[1,1,1,1,1];

    //如果不想改变数组中的所有元素,而只是想改变其中一部分,
    //那么可以使用可选的起始位置参数与结束位置参数(不包括结束位置的那个元素)
    let arr = [1, 2, 3,  arr , 5];
    arr.fill(1, 2);
    console.log(arr);   //[1,2,1,1,1]

    //3个参数: 填充数值,起始位置参数,结束位置参数(不包括结束位置的那个元素)
    arr.fill(0, 1, 3);
    console.log(arr);   //[1,0,0,1,1];
every()
every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回 truevar arr = [1, 2, 3, 4, 5];
    var arr2 = arr.every(function(x) {
        return x < 10;
    });
    console.log(arr2);  //true

    var arr3 = arr.every(function(x) {
        return x < 3;
    });
    console.log(arr3);  // false
some()
some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回 truevar arr = [1, 2, 3, 4, 5];
    var arr2 = arr.some(function(x) {
        return x < 3;
    });
    console.log(arr2);  //true

    var arr3 = arr.some(function(x) {
        return x < 1;
    });
    console.log(arr3);  // false
includes() [es7 新增]
includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则 false//参数有两个,其中第一个是(必填)需要查找的元素值,第二个是(可选)开始查找元素的位置
    const array1 = [22, 3, 31, 12,  arr ];
    const includes = array1.includes(31);
    console.log(includes); // true

    const includes1 = array1.includes(31, 3); // 从索引3开始查找31是否存在
    console.log(includes1); // false

    //需要注意的是:includes使用===运算符来进行值比较,仅有一个例外:NaN 被认为与自身相等。
    let values = [1, NaN, 2];
    console.log(values.indexOf(NaN));  //-1
    console.log(values.includes(NaN)); //true
toString()
将数组转换为字符串

    const array = [22, 3, 31, 12];
    const str = array.toString();
    console.log(str);  // 22,3,31,12
20、copyWithin() [es6 新增]
copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
该方法会改变现有数组

    //将数组的前两个元素复制到数组的最后两个位置
    let arr = [1, 2, 3,  arr , 5];
    arr.copyWithin(3, 0);
    console.log(arr);   //[1,2,3,1,2]


    //默认情况下,copyWithin()方法总是会一直复制到数组末尾,
    //不过你还可以提供一个可选参数来限制到底有多少元素会被覆盖。
    //这第三个参数指定了复制停止的位置(不包含该位置本身)。
    let arr = [1, 2, 3,  arr , 5, 9, 17];
    //(从索引3的位置开始粘贴,从索引0的位置开始复制,遇到索引3时停止复制)
    arr.copyWithin(3, 0, 3);
    console.log(arr);    //[1,2,3,1,2,3,17]
flat() [es6 新增]
flat() 方法会按照一个可指定的深度递归遍历数组,
并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
该方法返回一个新数组,对原数据没有影响。
参数: 指定要提取嵌套数组的结构深度,默认值为 1const arr1 = [0, 1, 2, [3, 4]];
    console.log(arr1.flat());   // [0, 1, 2, 3, 4]

    const arr2 = [0, 1, 2, [[[3, 4]]]];
    console.log(arr2.flat(2));  // [0, 1, 2, [3, 4]]

    //使用 Infinity,可展开任意深度的嵌套数组
    var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
    arr4.flat(Infinity);        // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    // 扁平化数组空项,如果原数组有空位,flat()方法会跳过空位
    var arr4 = [1, 2, , 4, 5];
    arr4.flat();                // [1, 2, 4, 5]


flatMap() [es6 新增]
flatMap()方法对原数组的每个成员执行一个函数,
相当于执行Array.prototype.map(),然后对返回值组成的数组执行flat()方法。
该方法返回一个新数组,不改变原数组。

    // 相当于 [[2, 4], [3, 6], [4, 8]].flat()
    [2, 3, 4].flatMap((x) => [x, x * 2])   // [2, 4, 3, 6, 4, 8]


12.10、多维数组

由于数组中,每一个元素都是独立的,因此,元素可以还是一个数组,这时就产生了多维数组的概念,多维数组通常都用于储存比较复杂的数据。

多维数组,依然是按照每一维元素的索引进行操作的。

//二维数组
//let arr = new Array( new Array(111, 222, 333), new Array(444, 555, 666) );
let arr = [ [111, 222, 333], [444, 555, 666] ];

//理解
[0,0]=111   [0,1]=222   [0,2]=333
[1,0]=444   [1,1]=555   [1,2]=666

//显示数据555
document.write( arr[1,1] );
13、json 与 集合
13.1、json数据对象(JavaScript Object Notation)

json是一种轻量级的数据交换格式,全称为“JavaScript对象表示法”。

JSON是基于JavaScript语言的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。JSON的语法简洁明了,易于阅读和编写,同时也易于机器解析和生成。

JSON数据以键值对的形式组织,其中键必须是字符串,值可以是任意类型。

//定义json对象
let user = {"id":555, "name":"葫芦娃", "sco":97.8};

//获取姓名
document.write( user.name );

//设置或追加属性
user.id = 123;         //id已存在,替换现有的值
user.height = 191;     //height没有,自动追加进去

//移除成绩
delete user.sco;

//json转字符串
let str = JSON.stringify(user);

//字符串转json
//字符串必须是json格式的内容
let jsonString = '{"name":"John", "age":30, "city":"New York"}';
let jsonObject = JSON.parse(jsonString);
13.2、集合对象:map

集合对象map是ES6新增加的特性之一。

map集合中,存放的数据 是键值对的方式,即 key与value的关系。

            //创建一个map集合
            var m = new Map();

            //添加元素:set(key,value)
            // key:如果重复:更新值,没有添加一个
            // value:可以是任意内容
            m.set('id',25);
            m.set('name','张三');
            m.set('sex','男');

            //按照key获取值
            document.write( m.get('name') );

            //set方法,如果同名key,就会更新值
            m.set('name','王五');


            //删除指定key的value值
            m.delete('name');

            //获取键值对的 数据对数
            document.write( m.size );


            //==========================================
            document.write('<br />');


            //同样只能迭代遍历数据

            //只要key
            for(let key of m.keys()){
                document.write(key+'<br />');
            }

            //只要value
            for(let value of m.values()){
                document.write(value+'<br />');
            }

            //全部
            for( let [k,v] of m ){
                document.write(k+'----'+v+'<br />');
            }
13.3、集合对象:set

集合对象set是ES6新增加的特性之一。

set集合中,存放的数据 没有索引,没有顺序,不会重复。

            //创建集合set
            let s = new Set();

            //添加元素
            s.add('张三');
            s.add('李四');

            //重复内容不会加入
            s.add('张三');  //重复,忽略
            s.add('王五');  //没有,追加

            //获取元素个数
            document.write( s.size );

            //删除指定元素
            s.delete('李四');

            //清空
            s.clear();


            //判断是否存在指定数据
            if( s.has('李四') ){
                document.write('有');
            }
            else{
                document.write('没有');
            }


            //迭代提取
            for(let temp of s){
                document.write(temp);
            }

            //==========================================

            //特殊操作
            //    支持数组方式初始化赋值
            //    会自动去除重复的

            let st = new Set([11,22,33,11,22,33]);

            //迭代提取
            for(let temp of st){
                document.write(temp);
            }
14、函数function
14.1、什么是函数?

把零散的变量与代码,包装到一个独立的运行单元,这个单元就是函数。

14.2、函数的种类
  • 普通函数
    以function关键字定义,通常提供程序在特定状态(事件)时调用
    它通常都是公用的操作,很多状态(事件)都需要调用的。
function 函数名称(参数列表) {
    //代码块
    //return 结果
}

// 函数名称:标识符的一员,自定义,全部小写,按照某种命名规范也可以
// 参数列表:可有可无,自定义的变量名称,表示接收外部传入的值,提供函数内部使用

// return:可有可无,函数运行完毕,会不会返回什么结果
//        有结果:写return
//        没有: 不用写
  • 匿名函数
    匿名函数是在一个特定状态(事件)的时候,直接提供,它没有名字,之后当前可以使用
//当窗体加载完毕后 = 这里直接提供一个匿名函数
//这个匿名函数的操作,只有当前状态可以使用
window.onload = function(){}
  • 箭头函数【重点】
    箭头函数是ES6新增的特性,它提供了一种更加简洁明了的函数定义。
    由于可以单独先定义函数名称,就支持了:var、let
//语法格式
var 函数名称 = (参数列表) => {}

//调用函数
函数名称();


//当箭头函数只有1个参数时,可以不写小括号
var getId = id => {}

//当箭头函数没有参数或多个参数时,就必须有小括号
var getName = () => {}
var getId = (name, pass) => {}
//普通函数========================================
function f(a){
    return a;
}
//调用函数,传入1,返回1
f(1);

//匿名函数========================================
var f = function(a){
    return a;
}
//调用函数,传入1,返回1
f(1);================================================
//箭头函数:标准定义,由于存在大括号,内部可以定义多行代码
var f = (a) => {
    return a;
}

//箭头函数:简明定义
//    1、只有1个参数,允许不定义小括号
//    2、没有大括号,=>后面只能定义一行代码,自动return最终结果
var f = a => a;


//调用函数:传入10,返回10
f(10); 

注意:

三种函数各有各的特点,针对鸿蒙系统,使用更多的是ES6新增特性:箭头函数

按照参数列表与返回,函数可以分为四类:
无参数,无返回
无参数,有返回
有参数,无返回
有参数,有返回

14.2、代码案例
//无参数,无返回:
    //这种函数通常只执行自己的固定代码操作

    //普通函数
    function test1() {
        document.write('函数test1执行了!<br />');
    }

    //箭头函数
    var test1 = () => {
        document.write('函数test1执行了!<br />');
    }


    //调用函数
    test1();
//无参数,有返回
    //要返回就要写return,
    //return后面可以是一个表达式,程序会自动运算,返回最终的结果

    //普通函数
    function test2() {
        let message = '运行了!';
        return '函数test2' + message;
    }

    //箭头函数:由于有多行代码,就不能缺少大括号
    var test2 = () => {
        let message = '运行了!';
        return '函数test2' + message;
    }

    //调用有返回的函数。
    let result = test2();
    document.write(result);
    //有返回的函数,可以直接当作一个具体的值
    document.write( test2() );
//无返回,有参数
    //需要外部提供数据,执行固定操作
    // 这里的x和y表示需要外部提供2个参数

    //普通函数
    function test3(x, y) {
        document.write(x+y);
    }

    //箭头函数
    var test3 = (x,y) => {
        document.write(x+y);
    }

    //调用测试
    test3(5, 6);

    let a=3, b=6;
    test3(a, b);
//有参数,有返回
    //这类函数通常是一个通用的处理过程,提供脚本通用

    //普通函数
    function test4(name1, name2) {
        if(name1==name2) {
            return true;
        }
        else {
            return false;
        }
    }

    //箭头函数
    var test4 = (name1,name2) => name1==name2?true:false;

    //调用函数,输出返回结果
    document.write( test4('张三', '张三') );
15、脚本与网页

js是脚本,当html网页通过浏览器解释之后,在渲染页面的时候,js默认会创建2个最大的对象

  • window对象:
    里面是当前浏览器窗口对象,自动获得浏览器窗口的各种参数
    提供对浏览器窗口的各种操作

  • dom对象:
    他是网页文档对象,默认只提供一些最基本的页面操作
    同时提供了大量的方法,让我们可以自定义操作网页元素或内容

15.1、window对象功能

window对象主要提供的都是针对浏览器窗口的功能,这里列举两个简单的操作:

//警告框
//不同浏览器呈现方式不同,它会锁定页面
//多用于:开发测试阶段 或 必须要强烈警告用户的操作!
//  window.alert(); 其中window可以不用写
alert('警告框!');


//提示框:提供2个按钮,确定或取消
//确定:true,取消:false
//可以直接用于判断            
//window.confirm(); 其中window可以不用谢
if( confirm('确定删除这条数据码?') ){
    document.write('删除中....');
}
else{
    document.write('操作已取消');
}
15.2、dom对象

DOM对象,全称Document Object Model,即文档对象模型,是Web开发中的一个重要概念。通过DOM,开发者可以访问和操作页面中的各个元素,例如添加、删除或修改元素,改变元素的属性或样式,处理事件等。

JavaScript可以通过document.getElementById()获取页面中的特定元素,并对其进行操作。

<!--网页中的div元素,必须提供id值-->
<div id="dv1"></div>    

<script>
    //按照元素的id值获取元素对象
    let dom = document.getElementById("dv1");

    //基于对象,设置标签中的内容
    dom.innerHTML='我是div元素';

    //基于对象,设置样式  
    dom.style.color='#ff0000';
    dom.style.backgroundColor='#ffaaaa';
    dom.style.textAlign='center'; 
</script>

在这里插入图片描述

当我们通过: document.getElementById('') 获取到一个元素之后
我们就在js中得到了这个元素的dom对象
基于这个dom对象,我们可以通过点的方式,设置 或 获取这个元素的任意属性
//以下方法也是按照不同的情况获取网页元素的dom对象
//它们得到的结果都是一个数组

//按照标签名称:获取网页中所有div元素数组
let arr = document.getElementsByTagName('div');

//按照name属性:获取所有性别元素数组
let arr = document.getElementsByName('gender');

//按照class属性:获取所有使用该样式的网页元素数组
let arr = document.getElementsByClassName('red');
16、事件Event

事件指的是在一个特定的状态下,系统自动执行的一个操作,在html中,事件与js是对应的。
当触发了一个特定的状态时,也就是事件,我们需要通过js提供它一个具体执行的操作,这个
具体的操作就是一个函数。

16.1、窗体事件
//针对当前窗体,支持的操作与事件

    //操作:重新设定地址栏请求,显示指定路径的页面
    // 实际路径,虚拟路径
    window.location.href = "http://www.baidu.com";


    //操作:打开一个新的窗口【很多浏览器自动屏蔽该代码】
    //  通常都不使用了
    window.open('http://www.taobao.com');


    //【重要】【事件Event】:当前窗体渲染完毕之后--呈现之前
    // 它是window对象的一个属性
    // 给它赋予的一个值,必须是一个函数
    //    有两种:方法委托,匿名方法

    //方法的委托:
    //    定义的是一个独立的函数,
    function aaa(){
        alert('页面加载完毕!');
    }
    //把方法当作一个参数,给onload            
    window.onload = aaa;


    //匿名函数:使用最多
    window.onload = function(){
        alert('页面加载完毕!');
    };

    //箭头函数
    window.onload = ()=>{
        alert('页面加载完毕!');
    }
16.2、鼠标事件
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            .dv1{
                width:200px;
                height:200px;
                border:1px solid #ff0000;
            }
        </style>
        <script type="text/javascript">

            //针对网页鼠标操作事件Event:
            /*
                onmouseover:    鼠标移动上去
                onmouseout:        鼠标离开
                onmousemove:    鼠标在内部移动
                onclick:        鼠标单击(任意键)
                ondblclick:        鼠标双击(任意键)
                onmousedown:    鼠标按下
                onmouseup:        鼠标弹起
            */
            //这些事件,网页中任何一个元素都可以使用
            //事件一旦触发了,就要提供一个特定的方法
            //委托给事件去执行

            //按钮鼠标单击
            function aaa(){
                alert('事件触发了!');
            }


            //Button的单击事件
            // obj是自定义的,表示一个接收到的参数
            // 外部传入的是this,这里obj接收到的 == document.getElementById()
            function bbb(obj){
                obj.style.color='#ff0000';
                obj.value='操作成功!';
            }

            //鼠标移动上去
            function shang(obj){
                obj.style.backgroundColor='#ffaaaa';
            }

            //鼠标离开
            function kai(obj){
                obj.style.backgroundColor='#ffffff';
            }

            //鼠标按下
            function mdown(obj){
                obj.style.backgroundColor='#aaffaa';
            }

        </script>
    </head>
    <body>

        <input type="button" value="按钮" onclick="aaa()" />
        <br /><br />

        <!--
            οnclick="bbb(this)"
            this是关键字,表示事件源对象

            事件源对象:
                触发这个事件的源头对象,
                谁触发的这个事件,就把这个对象,整个传入

            这里传入的,就是这个input对象
            就不用在写代码:document.getElementById()查找了
        -->
        <input type="button" value="Button" onclick="bbb(this)" />

        <!--
            如果要操作当前对象,
            可以使用this关键字
        -->
        <div class="dv1" onmouseover="shang(this)" onmouseout="kai(this)" onmousedown="mdown(this)">

        </div>


    </body>
</html>


16.3、键盘事件

只有允许键盘操作的网页元素可以使用,大部分集中于表单控件。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">
            //键盘事件
            /*
                onkeydown:   按下
                onkeyup:     弹起
            */

            function aaa(obj){
                //获取对象的value
                let val = obj.value;
                //显示出来
                document.getElementById("dv1").innerHTML = val;
            }

            //有一个操作是可以获取按键的编码的:
            // ASCII码
            function bbb(){

                //获取当前事件源的 键盘按键的 编码
                let code = event.keyCode;                
                document.getElementById('dv1').innerHTML += code+' ';

            }

        </script>
    </head>
    <body>

        <input type="password" onkeyup="aaa(this)" />        
        <div id="dv1"></div>

        <input type="text" onkeyup="bbb()" />            

    </body>
</html>
16.4、表单事件
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">

            //针对表单元素,特有的事件
            /*
                onfocus: 获得焦点
                onblur:  失去焦点
                onchange:失去焦点且value值改变,下拉列表select
            */

            //获得焦点
            function huode(obj){
                if(obj.value=='请输入用户名'){
                    obj.value='';
                }
            }

            //失去焦点
            function shiqu(obj){
                if(obj.value==''){
                    obj.value='请输入用户名';
                }
            }

        ii'yongyonou</script>
    </head>
    <body>        

        <input type="text" value="请输入用户名" onfocus="huode(this)" onblur="shiqu(this)" />

    </body>
</html>
17、正则表达式

JS正则表达式是一种语法格式,是每一个前端开发者必须会的基本功。
正则用于匹配一个指定的字符串内容,是否满足规定格式。


    /a/          匹配的内容中,只要有a就true,否则就是false
    /aba/        内容中必须有aba三个连续在一起的
    /^a/         ^不匹配字符,表示开始的位置,指定的内容必须是a开始的
    /m$/         $不匹配任何字符,表示结束的位置,指定内容必须m结束
    /^admin$/    开始必须a,结束必须n,中间是dmi,等同于内容必须是admin


    ----------------------------------------------------------
    转义符号:            
    \w             表示:数字,小写字母,大写字母,下划线中的任何一个            
    \d             表示:任何一个数字            

    /^\d\d\d\d\d\d$/    
    开始,结束,中间必须是6个数字 == 邮政编码


    -------------------------------------------------------
    特殊符号:            
    .        点,表示任何内容            
    |        表示或者,            
    ()        表示一个完整的部分


    /^a./        必须a开始,后面可以是任意内容,长度不限            
    /^x|X$/      指定内容只能是一个字母,小写x或大写X            
    /^a(5|6)a$/  开始和结束都是a,中间是5或者6  a5a  a6a


    -----------------------------------------------------
    特殊字符匹配:            
        如果需要匹配的是特殊的符号,
        在符号前面追加一个\,就可以去除特有的概念,而保留这个符号本身

    \.   表示这个点本身
    \^
    \%
    \\
    \/
    \|

    /^\d\d\d\d\d\.qq\.com$/   5位数字.qq.com

    ----------------------------------------------------------
    选择:
    []    表示里面的任何一个内容        
    [^]      表示 除 里面之外的任何一个内容


    /^abc[123]$/   开始必须是a,然后bc,结束在1或2或3
    /^[^a].$/      内容不能是a开始


    ---------------------------------------------------------
    区间:
        只能是 数字,小写字母,大写字母,中文可以使用
        而且,只能在 [] 或 [^] 里面

    [0-9]         0-9之间任意一个数字

    [3-8]        
    [A-Z]        
    [B-G]        
    [a-z]
    [e-h]

    字符串内容,必须字母开始:  /^[A-Za-z]/
    [\u4e00-\u9fa5]         表示任意一个中文字


    --------------------------------------------------------
    数量:        
    {m}             前面的一个内容,必须重复m遍        
    {m,}            前面的一个内容,至少重复m遍,多无限        
    {m,n}           前面的一个内容,至少m,最多n


    /^\d{6}$/        邮政编码,前面一个数字,必须6个        
    /^abc{5,}$/      必须a开始,然后b,c最少重复5次,多无限        
    /^[a-z]{5,7}$/   必须小写字母,5-7位        

    用户名,必须字母开始,字母或数字6-16位        
    /^[A-Za-z][0-9A-Za-z]{5,15}$/


    --------------------------------------------------
    ?       可有,可无,有1个         {0,1}
    +       加号表示至少1个,多无限    {1,}
    *       可有,可无,多无限         {0,}

    /^[a-z]+$/

====================================================

以上是基础概念,需要慢慢整理,然后理解,使用。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>        

        <script type="text/javascript">

            //直接调用test方法,匹配指定的字符串内容
            if( /^1[35678]\d{9}$/.test('13596857451') ){
                document.write('对的');
            }
            else{
                document.write('错误');
            }            

        </script>        

    </body>
</html>
案例-表单验证

创建 register.html 注册页面

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/register.min.js" type="text/javascript"></script>
    </head>
    <body>

        <!--
            表单:form
            属性:id, name, action, method, enctype
                id是提供脚本使用的
                name是提供服务器获取的
                action定义提交的路径:保护路径,html中不定义,通过脚本定义
        -->
        <form id="f1" name="f1" method="post">

            用户名:
            <input id="username" name="username" type="text" onblur="ckusername(this)" />
            <span id="sp_username"></span>
            <br /><br />

            密码:
            <input id="userpass" name="userpass" type="text" onblur="ckuserpass(this)" onkeyup="fuyuan()" onchange="fuyuan()" />
            <span id="sp_userpass"></span>
            <br /><br />

            确认密码:
            <input id="ruserpass" name="ruserpass" type="text" onblur="ckruserpass(this)" />
            <span id="sp_ruserpass"></span>
            <br /><br />

            <label>
                <input id="xy" type="checkbox" />
                我同意网站的注册协议
            </label>
            <br /><br />

            <input type="button" value="注册" onclick="zhuce()" />
            <input type="button" value="重置" onclick="chongzhi()" />

        </form>        

    </body>
</html>

创建 /js/register.js 脚本文件

//定义变量,对应所有用户输入对象,默认false,表示错误
//作用是提供提交按钮操作,决定是否可以提交表单
let username=false;
let userpass=false;
let ruserpass=false;


//检查用户名
function ckusername(obj){
    if(/^[A-Za-z]\w{5,15}$/.test(obj.value)){
        //对
        //    需要通过ajax技术,请求服务器,进行重名判断
        //    访问服务器接口,发送用户名的值,接口会返回 true或false
        //    目前知识点不足,默认表示正确
        username=true;
        document.getElementById("sp_username").innerText="√";
        document.getElementById("sp_username").style.color="#00ff00";
    }
    else{
        //错
        username=false;
        document.getElementById("sp_username").innerText="用户名格式错误!";
        document.getElementById("sp_username").style.color="#ff0000";
    }
}


//检查密码
function ckuserpass(obj){
    if(/^\w{6,16}$/.test(obj.value)){
        //对
        userpass=true;
        document.getElementById("sp_userpass").innerText="√";
        document.getElementById("sp_userpass").style.color="#00ff00";
    }
    else{
        //错
        userpass=false;
        document.getElementById("sp_userpass").innerText="密码格式错误!";
        document.getElementById("sp_userpass").style.color="#ff0000";
    }
}


//检查确认密码
function ckruserpass(obj){
    if(obj.value!=''){
        if(obj.value==document.getElementById("userpass").value){
            //对
            ruserpass=true;
            document.getElementById("sp_ruserpass").innerText="√";
            document.getElementById("sp_ruserpass").style.color="#00ff00";
        }
        else{
            //错
            ruserpass=false;
            document.getElementById("sp_ruserpass").innerText="两次密码不同!";
            document.getElementById("sp_ruserpass").style.color="#ff0000";
        }
    }
    else{
        //错
        ruserpass=false;
        document.getElementById("sp_ruserpass").innerText="确认密码不能为空!";
        document.getElementById("sp_ruserpass").style.color="#ff0000";
    }
}


//密码框键盘操作,鼠标复制粘贴操作
//确认密码复原
function fuyuan(){
    ruserpass=false;
    document.getElementById("ruserpass").value="";
    document.getElementById("sp_ruserpass").innerText="";
}


//重置
function chongzhi(){
    //最简单的:重新打开一次页面
    //当前重新打开的页面路径与上一次相同
    //浏览器会预先呈现缓存里面的内容
    window.location.href="注册验证实例.html";
}


//注册
function zhuce(){
    //判断是否同意免责协议
    // checkbox有状态 checked,获取到之后,得到true或false
    if( document.getElementById("xy").checked ){
        //通过定义变量决定是否可以提交表单
        if( username && userpass && ruserpass ){
            //都正确了:
            //第一步:提取整个表单
            let f1 = document.getElementById("f1");
            //第二步:设置action属性
            f1.action="http://www.baidu.com/";
            //第三步:调用方法,提交表单
            f1.submit();
        }
        else{
            alert('填写有误,请更正!');
        }
    }
    else{
        alert('您没有同意协议,不可注册!');
    }
}
18、基本常用操作

在js中,针对我们经常会使用且处理的数据,语言本身就提供了很多操作,我们可以借助这些操作,提供开发效率,完成需要的功能。

18.1、字符串string操作
    //字符串
    let str='abcd-ABCD-1234';

    //获取字符串的字符个数
    document.write( str.length +'<br />');


    //字符串中,每一个字符都有索引
    //可以直接当数组元素提取
    document.write( str[0]  +'<br />');
    document.write( str[5]  +'<br />');


    //统一转换大小写,只对英文字母有效
    document.write( str.toLowerCase()  +'<br />');
    document.write( str.toUpperCase()  +'<br />');


    //提取字符串            
    //一个参数:开始字符的索引,后面所有
    document.write( str.substring(5)  +'<br />');
    //两个参数:开始索引~结束索引-1
    document.write( str.substring(1,5)  +'<br />');


    //替换:每一次,只能替换找到的第一个
    document.write( str.replace('-','★')  +'<br />');


    //查找指定内容,找到:返回索引,没有:-1
    //从前往后照,第一次出现的
    document.write( str.indexOf('cd')  +'<br />');
    //从后往前照,最后一次出现的
    document.write( str.lastIndexOf('-')  +'<br />');


    //按照界定符,切割字符串,变成数组
    // 【北京|上海|武汉|广州|】
    // 【北京】【上海】【武汉】【广州】【】            
    let city='北京|上海|武汉|广州|';
    //切割
    let arr = city.split('|');
    //元素==5个
    document.write(arr.length +'<br />');    
    //小于对应索引,-1扣除最后一个空元素不要
    for(let i=0; i<arr.length-1; i++){
        document.write(arr[i]+'<br />');
    }
18.2、日期类操作
//日期类操作  Date

            //创建一个新的日期:系统当前时间
            var dt = new Date();        
            document.write(dt +'<br />');

            //获取当前时间的:时间戳(整数)
            // 从1970-01-01 00:00:00至今,所经历的 秒数
            // 最后三位:毫秒
            document.write(Date.now() +'<br />')

            //提取日期中的某一个部分
            //    系统当前时间:new Date()
            //  指定时间:new Date('2020-08-19')
            var dt = new Date();

            //为了解决千年虫问题
            //从1900开始计算
            //完整四位年份,需要自己手动追加1900
            document.write(dt.getYear()+1900 +'<br />');

            //月份计算,0-11,
            document.write(dt.getMonth()+1 +'<br />');

            //日期
            document.write(dt.getDate() +'<br />');

            //星期:0-6  日-六
            document.write(dt.getDay()+1 +'<br />');

            //时间都是正确的
            document.write(dt.getHours() +'<br />');
            document.write(dt.getMinutes() +'<br />');
            document.write(dt.getSeconds() +'<br />');
18.3、科学计算类操作
//科学计算类: Math

            //绝对值:
            // 获取网页文本框的值是字符串,不能做加法
            // 购物车商品数量+1,
            // 必须把文本的value,转绝对值,再+1
            document.write( Math.abs('-5') +'<br />');


            //x的y次方
            document.write( Math.pow(2,-9) +'<br />');


            //向上或向下取整
            document.write( Math.ceil(3.000001) +'<br />');
            document.write( Math.floor(5.99999) +'<br />');


            //四舍五入: 取整数
            document.write( Math.round(3.54)  +'<br />');

            //随机数
            // 从0-1之间,没有1的,一个随机浮点小数
            document.write( Math.random()  +'<br />');

            document.write('<hr />');

            //0-10之间的随机数            
            //var num = Math.round( Math.random()*10 );

            //1-10
            //var num = Math.round( Math.random()*9 + 1 );

            //25-37
            let num = Math.round( Math.random()*12 + 25 );

            document.write( num  +'<br />');
            document.write('<hr />');

            //抽奖,每人平均1‰的几率
            num = Math.round(Math.random()*1000);            
            if(num==1){
                document.write('一等奖');
            }
            else{
                document.write('谢谢参与!'+num);
            }
19、定时任务

在js中,我们可以设置定义任务,让脚本自动执行指定的操作。

19.1、定时器

定时器的作用是一次性的,到大指定时间就执行我们指定的操作。

setTimeout(方法名称委托, 毫秒时间)

30秒倒计时案例

点击[发送验证码]的按钮,按钮会锁定,然后显示30秒倒计时。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">

            //显示内容
            let t=30;

            //点击发送验证码
            function fasong(obj){
                //锁定按钮,可以看到,但是不能操作
                obj.disabled=true;
                //更改内容
                obj.value="请等待30秒";
                //变量复原
                t=30;
                //定时器,1秒后调用start方法
                setTimeout(start,1000);
            }

            //时间结束
            function start(){
                //时间--,扣除1秒
                t--;
                //判断是否时间已经到了
                if(t>=0){
                    //时间没有到:更新显示,继续等1秒,调用当前方法
                    document.getElementById("btn").value="请等待"+t+"秒";
                    setTimeout(start,1000);
                }
                else{
                    //时间到了,恢复按钮
                    document.getElementById("btn").value="发送验证码";
                    document.getElementById("btn").disabled=false;
                }
            }

        </script>
    </head>
    <body>

        <input id="btn" type="button" value="发送验证码" onclick="fasong(this)" />

    </body>
</html>
19.2、定时循环器

定时循环器的作用是定时轮询性的,到达指定时间就执行我们指定的操作。
因此,定时循环器是允许赋予一个变量,调用指定方法来停止或销毁它的。

//定义了定时循环器,且sit变量也指向这个循环器
var sit = setInterval(方法名委托, 毫秒时间)

//销毁定时循环器,终止的作用
clearInterval(sit);

定时输出内容案例

页面打开后,div中的内容,每1秒自动追加显示一个笑脸,鼠标移动上去停止,离开继续
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">

            //定义循环器:setInterval
            //使用方式与定时器一样,但是他是永久运行
            //这个操作可以赋予一个变量
            //我们可以停止这个循环过程,
            // clearInterval(变量),

            //处理方法
            function aaa(){
                document.getElementById("dv1").innerText += "☺";
            }            

            //停止
            function stop(){
                //情况循环对象
                clearInterval(flag);
            }

            //运行
            function start(){
                //【不要声明】,在给变量赋值
                flag = setInterval(aaa, 1000);
            }

            //窗体加载完毕
            window.onload=function(){
                //定时循环器
                //这里是第一次运行,var声明,全局的
                var flag = setInterval(aaa, 1000);
            };


        </script>
    </head>
    <body>

        <div id="dv1" onmouseover="stop()" onmouseout="start()" style="border:1px solid #ff0000;"></div>

    </body>
</html>
案例-轮播图

创建 index.html 网页

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">

            //声明全局的轮播图对象,提供所有方法使用
      var flag;

            //定义数组,保存每一个图片的路径
            var imgarr = [
                "img/more-app.jpg",
                "img/more-duokan.jpg",
                "img/more-game.jpg",
                "img/more-miui.jpg"
            ];

            //变量,表示索引,默认0,第一张
            var index=0;

            //图片的切换-没有效果
            function changeimg(){
                //下一个索引,下一张图片
                index++;
                //判断
                if(index >= imgarr.length){
                    index=0;
                }
                //替换
                document.getElementById("im").src=imgarr[index];
            }

      //停止
      function stop(){
          //情况循环对象
          clearInterval(flag);
      }

      //运行
      function start(){
          //【不要声明】,在给变量赋值
          flag = setInterval(changeimg, 2000);
      }

            //窗体加载完毕
            window.onload=function(){
                //默认显示第一张
                document.getElementById("im").src=imgarr[index];
                //定时循环器,这里是第一次运行
                flag = setInterval(changeimg, 2000);
            };

        </script>
        <style>
            .dv2{
                margin:50px auto;
                width:300px;
                border:1px solid #cccccc;
            }
            .dv2>img{
                width:300px;
            }
        </style>
    </head>
    <body>

        <div class="dv2" onmouseover="stop()" onmouseout="start()">
            <img id="im" />
        </div>        

    </body>
</html>


20、ES6:面向对象
20.1、什么是面向对象?

面向对象:(Object-oriented programming,简称OOP),是一种基于对象和类的编程范式。它的本意是将现实世界中,各种复杂的关系和概念,抽象出来,利用代码定义成一个个独立的个体,然后通过对象之间的分工与合作实现编程目标。

20.2、面向对象的三大特性
  • 封装:体现了代码的 可维护性

  • 继承:体现了代码的 可扩展性

  • 多态:体现了代码的 灵活性

20.3、封装-class
**封装是最基本的特性,没有封装就没有面向对象。**

ES6:提供了更大的对象概念 class类 
封装:使用class类的形式,把变量 和 函数包装成一个独立的程序单元 |
封装以后, 
    类中的变量,称之为:属性 
    类中的函数,称之为:行为 
  //封装的理解

            class 自行车 {
                //属性
                品牌="奇安特";
                型号="KT-4578";
                颜色="白";
                款式="山地";

                //行为
                刹车(){ }
                变速(){ }
            }

            //使用的时候,就需要实例化,
            //通过js解释,创建到内存上
            let zxc = new 自行车();

            //使用的时候,通过名称调用
            document.write( zxc.品牌 );
20.4、封装-访问器
访问器实际上就是特定的函数,它们提供对类中属性的操作。
get访问器:用于提供外部获取属性值的。
set访问器:用于提供外部设置属性值的
            //与用户有关的操作,全部封装到一个类中
            //类名使用 驼峰式命名
            class User
            {
                //类中的属性,就是变量
                //定义的时候不要关键字,他们默认都是 let,当前类中局部的
                //没有赋值的时候,默认值都是:undefined
                //这种定义方式,变量是对外公开的
                //任何位置都可以操作的:不安全
                //username;
                //userage;

                //推荐将类中的变量,提供getset方法操作,而不要直接定义
                //【访问器】set表示设置,get表示获取
                //这里的this表示当前类的
                //会自动创建一个私有的内部变量,储存年龄
                //外部赋值操作,会自动执行这个方法
                //但是这个私有的变量,外部是看不见的
                //【需要再名字前面添加一个下划线:表示private私有的】
                //由于存在访问器,我们就可以对数据进出进行过滤了
                set userAge(userAge)
                {
                    //数据过滤
                    if(typeof(userAge)!='number' || userAge<1){
                        alert("非法数据");
                    }
                    else{
                        this._userAge = userAge;
                    }
                }
                get userAge()
                {
                    if(this._userAge==undefined){
                        return '保密';
                    }
                    else{
                        return this._userAge;
                    }

                }                

                //自定义的行为,不用关键字
                userinfo(){
                    //直接通过this调用名称,自动运行get或set方法
                    document.write( this.userAge );
                }

            }


            //实例化对象
            let u = new User();

            //测试            
            u.userAge=18;

            document.write( u.userAge );

            u.userinfo();
20.5、封装-构造器
           class User{

                //构造函数:构造器
                //每一个类中,都有一个默认的特定方法
                //称之为构造器
                //当遇到new关键字的时候
                //创建所有内容到内存,然后执行构造器
                //通常这个方法是隐藏的,
                //如果需要自定义执行一些默认操作,就自己添加代码
                // 一个类中,只有一个,允许传参数的
                constructor(x)
                {
                    document.write('构造函数执行了'+x);
                }

            }

            //创建实例对象
            let u = new User(5);
20.6、继承-extends
**继承是第二大特性,它必须建立在封装的基础上。**

一个类,通过extends指定另一个类,来沿用它内部非私有的属性和行为,
这种操作就是继承。

继承是单一的,也就是说1个父类,可以拥有N个子类,但是一个子类只能
继承1个父类。
    //父类,根类,超类,基础类
    class Fu {
    }

    //子类,派生类,扩展类
    class Zi extends Fu {
        //父类中,所有非私有的属性和行为沿用过来
        //追加子类特有的内容
    }
20.7、继承-构造器与super
    //父类,根类,超类,基础类
    class Fu {
        //构造函数
        constructor(){
            document.write('父类构造函数');
        }
    }

    //子类,派生类,扩展类
    class Zi extends Fu {                
        //如果子类没有显示的写出构造函数
        //程序会默认自动先执行父类,在执行子类自己的

        //如果显示的写出了构造函数,
        //就可以决定是否执行父类构造函数

        //构造函数是每一个类特有的
        //子类调用父类,使用的是: super();

        //构造函数
        constructor(){
            super();//自动调用父类构造函数
            document.write('子类构造函数');                    
        }
    }

    //当实例化子类的时候
    let z = new Zi(); //父类构造函数子类构造函数
20.8、继承-方法重写

重写的意思就是重新定义,原来的作废,使用现在的。

    //父类,根类,超类,基础类
    class Fu {
        //父类特有的行为(函数:方法)
        say(){
            document.write('我是爸爸!');
        }
    }

    //子类,派生类,扩展类
    class Zi extends Fu {
        //自动沿用父类中非私有的行为
        //追加子类特有的行为:【第二大特性:代码的可扩展性】
        zisay(){
            document.write('我是宝宝!');
        }


        //如果存在同名方法,
        //子类内容会替换父类的内容,最终运行的是子类的代码
        say(){
            document.write('与父类同名方法!');
        }

    }

    //当实例化子类的时候,程序运行是先运行谁?
    let z = new Zi();

    //测试
    z.say();    //与父类同名方法!
    z.zisay();  //我是宝宝
20.9、多态

多态必须建立在继承的基础上

不同子类都继承父类,都重写父类指定方法,实例化创建不同子类,虽然调用的都是一个方法,但是运行的结果不同。

    //父类,根类,超类,基础类
    class Fu {
        //父类特有的行为(函数:方法)
        say(){
            document.write('我是爸爸!');
        }
    }

    //子类,派生类,扩展类
    class DaMao extends Fu {
        //重写父类方法
        say(){
            document.write('我是大毛!');
        }                
    }
    class ErMao extends Fu {
        //重写父类方法
        say(){
            document.write('我是二毛!');
        }                
    }
    class XiaoMing extends Fu {
        //重写父类方法
        say(){
            document.write('我是小明!');
        }                
    }

    //实例化指定子类
    let z = new DaMao();  //默认是大毛

    //如果这行执行,结果就是二毛
    //z = new ErMao();
    //如果这行执行,结果就是小明
    //z = new XiaoMing();    

    //测试
    z.say();    // 大毛 或 二毛 或 小明
20.10、static静态方法
    //类中定义的方法,每一次使用
    //都需要先实例化类对象,创建具体内存
    //然后才可以使用

    //如果有一些方法,使用很多
    //我们就可以把这些内容
    //定义成静态的 static
    //静态内容,默认就会自动创建实例,放到内存的-静态区
    //使用的时候,不用实例化,通过类名直接调用。
            class User{

                static say(){
                    document.write('执行了!');
                }

            }

            //直接通过类名调用,不用new了
            User.say();
21、原型 和 原型链

在 JavaScript 中,ES6 开始引入class的概念。

JavaScript并没有全新的创建class,而是建立在函数的原理上,重新进行包装,因此,JavaScript 中class的本质还是函数function,但是实际还是有不同之处。

21.1、什么是原型?
我们通俗一点来说明:
    当一个函数或一个类被创建到内存上的时候,
    JavaScript都会先创建好一个基本的对象,这个对象的用途是包含特定类型的
    所有实例共享的属性和方法,就好比我们创建一个数组:
        let arr = [];
    这时,arr 可以调用:split() 方法,而这个方法就是数组的
    基本对象提供的。

    js会先创建一个数组的基本对象,里面包括了数组的所有操作方法,
    然后,再创建我们定义的arr,arr中有一个指针,指向这个基本对象。
    这个对象,我们就称之为:原型对象
    //定义一个函数
    //默认就会得到一个原型内存对象,它是独立的
    function User(){
    }

    //我们可以把这个函数,当前一个对象,去new,创建实例的
    //var u = new User();

    //由于本身不是class,那么,就是中,会为每一个函数
    //定义一个 prototype 的属性
    //这个属性是对应到最原始的内容的
    //这个原始内容就是原型
    //而我们new出来的,都是自动对应到这个原始内容的

    //第一步:通过函数提供的 prototype属性,操作原型
    //这里变动了最原始的内存
    User.prototype.name = 'aaa';

    //第二步:创建两个单独的实例对象
    //js会单独再去创建2个内存
    //它不会把原型对象的内容获取过来的
    //而是对应到原型的内存
    /*
        [u1]-----|
                 |---->【原型内存对象】
        [u2]-----|
    */
    var u1 = new User();
    var u2 = new User();

    //第三步:输出实例对象的name
    //我没有操作过u1和u2,但是已经有name和他的值了
    //应为上面,代码通过 prototype,操作过原型了
    document.write(u1.name);
    document.write(u2.name);
21.2、什么是原型链?

在JavaScript中,原型链是一种重要的数据结构,用于实现对象之间的继承关系。

每个对象(实例)都有一个隐式属性__proto__,它指向创建该对象的构造函数的原型对象。同时,原型对象也有一个隐式属性constructor,它指向创建它的构造函数。这种层级关系形成了一条链,即“原型链”。当访问一个对象的属性或方法时,首先会在该对象自身中查找,如果找不到,则会沿着原型链向上一级原型对象继续查找,直到找到或到达Object的prototype为止。通过这种方式,一个对象可以继承多个对象的属性和方法。

21.3、原型链-内置操作
//类和函数都可以,使用类
    class User{
        //构造函数
        constructor(){
            document.write('构造函数');
        }

        //一个属性的get和set
        set userId(userId){
            this._userId = userId;
        }
        get userId(){
            return this._userId;
        }

        //特有方法
        say(){
            document.write('说话');
        }

    }            
    //================================

    //预览一个对象的原型:
    //就算我们使用ES6,定义的是class类
    //但是,在内存上,他创建的原型依然是:function
    //这个function是js中提供的,最大的基础类
    document.write( User.__proto__  +'<br />');

    //预览到行为组成的json个是的描述
    document.write(User.prototype  +'<br />');

    //可以预览一个具体行为方法的源代码
    document.write(User.prototype.say);
22、模块化开发

我们不可能将所有的代码或函数和类都定义在一个js文件中,我们应该有更好的代码整理方式,不同的内容应该分开定义,分别归类存放,易于代码维护。

这种开发方式就称之为:模块化开发

一个js脚本文件,就是一个模块,里面可以定义1个或多个函数或类。然后需要导出操作。

网页或脚本中,如果需要使用,就要定义导入操作,这样就把外部支持导出的代码合并到当前位置了。

22.1、export 和 import

文件名:user.js

//js脚本文件创建一个类
//文件名就是当前的类名

//export: 表示支持内容导出
//default:表示当前为默认类,自动类名与文件名相同
export default class{

    say(){
        alert('说话');
    }

}
//其他js脚本中,在开始的位置,导入
//User是自定义的名称,就是接收到的类
import User from 'user.js';

//正常操作
let u = new User();            
u.say();
<!--网页中导入:标签类型需要更改-->
<script type="module">
    //导入外部文件--类
    import User from './js/User.js';

    //正常操作
    let u = new User();            
    u.say();

</script>
22.2、解构

有时,一个模块文件中会导出多个对象,这种情况出现于函数模块,
这时,就可以通过解构的操作来决定到底需要哪一个。

文件名:student.js

//这是一个独立的js文档
//定义N个操作方法function
//如果希望使用的时候,可以决定用哪些方法

export function aaa(){}

export function bbb(){}
//其他js脚本中,在开始的位置,导入
//大括号中的名称必须和方法同名
import {aaa} from 'student.js';

//正常操作
aaa();
<!--网页中导入:标签类型需要更改-->
<script type="module">
    //大括号中的名称必须和方法同名
    import {aaa} from 'student.js';

    //正常操作
    aaa();
</script>
23、数据储存

ES6新增了浏览器缓存数据的对象:
持久化: window.localStorage

//ES6针对数据处理
      //  提供了对于浏览器,将数据持久保持的对象
      //  主要是提供脚本使用
      //  永久存在,触发手动删除浏览器数据


      //创建
      //  如果存在同名,会覆盖的
      //  key:字符串
      //  value:字符串
      window.localStorage.setItem('name', '葫芦娃');

      //获取
      let name = window.localStorage.getItem('name');
      console.log(name);      

      //移除指定的
      window.localStorage.removeItem('name');

      //清空所有:当前域名下的
      window.localStorage.clear();

会话级: window.sessionStorage

//ES6:提供了会话储存数据的对象操作
      //  会话:浏览器打开网站,这个对象在整个会话过程中,存在
      //  当关闭网站、或者关闭浏览器,它自动销毁


      //创建
      window.sessionStorage.setItem('name', '葫芦娃');

      //获取
      let name = window.sessionStorage.getItem('name');
      console.log(name);


      //移除指定的
      window.sessionStorage.removeItem('name');

      //清空所有:当前域名下的
      window.sessionStorage.clear();
24、购物车脚本功能综合案例

项目需求:
1、页面显示默认信息,自动统计购物车商品的总价与积分
2、实现商品全选功能
3、实现商品数量增减功能,同时更新总价与积分
4、实现独立商品删除功能,同时更新总价与积分
5、实现删除所选功能,同时更新总价与积分

效果图:

在这里插入图片描述

项目结构:

myCart/
    css/
        cart.css
    img/
        所有图片资源
    js/
        cart.js
    cart.html

特殊代码说明:

超链接不打开href路径,而是点击后,执行javascript代码,调用函数。
<a href="javascript:deleteSelectRow()">

参考代码:
实现项目需求有N中代码编写方式,这里的代码,主要是为大家提供一个思路和概念,同学们完全可以使用自己的方式实现。

cart.html

<!DOCTYPE html>
<html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>淘宝购物车页面</title>
    <link href="css/cart.css" rel="stylesheet" />
    <script src="./js/cart.js"></script>
  </head>

  <body>
    <div id="header"><img src="img/taobao_logo.gif" alt="logo" /></div>
    <div id="nav">您的位置:<a href="#">首页</a> > <a href="#">我的淘宝</a> > 我的购物车</div>
    <div id="navlist">
      <ul>
        <li class="navlist_red_left"></li>
        <li class="navlist_red">1. 查看购物车</li>
        <li class="navlist_red_arrow"></li>
        <li class="navlist_gray">2. 确认订单信息</li>
        <li class="navlist_gray_arrow"></li>
        <li class="navlist_gray">3. 付款到支付宝</li>
        <li class="navlist_gray_arrow"></li>
        <li class="navlist_gray">4. 确认收货</li>
        <li class="navlist_gray_arrow"></li>
        <li class="navlist_gray">5. 评价</li>
        <li class="navlist_gray_right"></li>
      </ul>
    </div>

    <div id="content">
      <table width="100%" border="0" cellspacing="0" cellpadding="0" id="shopping">
        <form action="" method="post" name="myform">
          <tr>
            <td class="title_1">
              <input id="allCheckBox" type="checkbox" value="" onclick="selectAll()" />全选
            </td>
            <td class="title_2" colspan="2">店铺宝贝</td>
            <td class="title_3">获积分</td>
            <td class="title_4">单价(元)</td>
            <td class="title_5">数量</td>
            <td class="title_6">小计(元)</td>
            <td class="title_7">操作</td>
          </tr>
          <tr>
            <td colspan="8" class="line"></td>
          </tr>
          <tr>
            <td colspan="8" class="shopInfo">
              店铺:<a href="#">纤巧百媚时尚鞋坊</a>
              卖家:<a href="#">纤巧百媚</a>
              <img src="img/taobao_relation.jpg" alt="relation" />
            </td>
          </tr>
          <tr id="product1">
            <td class="cart_td_1">
              <input name="cartCheckBox" type="checkbox" value="product1" onclick="selectSingle()" />
            </td>
            <td class="cart_td_2"><img src="img/taobao_cart_01.jpg" alt="shopping" /></td>
            <td class="cart_td_3"><a href="#">日韩流行风时尚美眉最爱独特米字拼图金属坡跟公主靴子黑色</a><br />
              颜色:棕色 尺码:37<br />
              保障:<img src="img/taobao_icon_01.jpg" alt="icon" /></td>
            <td class="cart_td_4">5</td>
            <td class="cart_td_5">138.00</td>
            <td class="cart_td_6">
              <img src="img/taobao_minus.jpg" alt="minus" onclick="changeNum('num_1','minus')" class="hand" />
              <input id="num_1" type="text" value="1" class="num_input" readonly="readonly" />
              <img src="img/taobao_adding.jpg" alt="add" onclick="changeNum('num_1','add')" class="hand" />
            </td>
            <td class="cart_td_7"></td>
            <td class="cart_td_8">
              <a href="javascript:deleteRow('product1'); ">删除</a>
            </td>
          </tr>

          <tr>
            <td colspan="8" class="shopInfo">
              店铺:<a href="#">香港我的美丽日记</a>
              卖家:<a href="#">lokemick2009</a>
              <img src="img/taobao_relation.jpg" alt="relation" />
            </td>
          </tr>
          <tr id="product2">
            <td class="cart_td_1">
              <input name="cartCheckBox" type="checkbox" value="product2" onclick="selectSingle()" />
            </td>
            <td class="cart_td_2"><img src="img/taobao_cart_02.jpg" alt="shopping" /></td>
            <td class="cart_td_3">
              <a href="#">chanel/香奈尔/香奈尔炫亮魅力唇膏3.5g</a><br />
              保障:<img src="img/taobao_icon_01.jpg" alt="icon" />
              <img src="img/taobao_icon_02.jpg" alt="icon" />
            </td>
            <td class="cart_td_4">12</td>
            <td class="cart_td_5">265.00</td>
            <td class="cart_td_6">
              <img src="img/taobao_minus.jpg" alt="minus" onclick="changeNum('num_2','minus')" class="hand" />
              <input id="num_2" type="text" value="1" class="num_input" readonly="readonly" />
              <img src="img/taobao_adding.jpg" alt="add" onclick="changeNum('num_2','add')" class="hand" />
            </td>
            <td class="cart_td_7"></td>
            <td class="cart_td_8">
              <a href="javascript:deleteRow('product2');">删除</a>
            </td>
          </tr>

          <tr>
            <td colspan="8" class="shopInfo">
              店铺:<a href="#">实体经营</a>
              卖家:<a href="#">林颜店铺</a>
              <img src="img/taobao_relation.jpg" alt="relation" />
            </td>
          </tr>
          <tr id="product3">
            <td class="cart_td_1"><input name="cartCheckBox" type="checkbox" value="product3"
                onclick="selectSingle()" /></td>
            <td class="cart_td_2"><img src="img/taobao_cart_03.jpg" alt="shopping" /></td>
            <td class="cart_td_3"><a href="#">蝶妆海晳蓝清滢粉底液10#(象牙白)</a><br />
              保障:<img src="img/taobao_icon_01.jpg" alt="icon" /> <img src="img/taobao_icon_02.jpg" alt="icon" />
            </td>
            <td class="cart_td_4">3</td>
            <td class="cart_td_5">85.00</td>
            <td class="cart_td_6">
              <img src="img/taobao_minus.jpg" alt="minus" onclick="changeNum('num_3','minus')" class="hand" />
              <input id="num_3" type="text" value="1" class="num_input" readonly="readonly" />
              <img src="img/taobao_adding.jpg" alt="add" onclick="changeNum('num_3','add')" class="hand" />
            </td>
            <td class="cart_td_7"></td>
            <td class="cart_td_8"><a href="javascript:deleteRow('product3');">删除</a></td>
          </tr>

          <tr>
            <td colspan="8" class="shopInfo">
              店铺:<a href="#">红豆豆的小屋</a>
              卖家:<a href="#">taobao豆豆</a>
              <img src="img/taobao_relation.jpg" alt="relation" />
            </td>
          </tr>
          <tr id="product4">
            <td class="cart_td_1">
              <input name="cartCheckBox" type="checkbox" value="product4" onclick="selectSingle()" />
            </td>
            <td class="cart_td_2">
              <img src="img/taobao_cart_04.jpg" alt="shopping" />
            </td>
            <td class="cart_td_3">
              <a href="#">相宜促销专供 大S推荐 最好用的LilyBell化妆棉</a><br />
              保障:<img src="img/taobao_icon_01.jpg" alt="icon" />
            </td>
            <td class="cart_td_4">12</td>
            <td class="cart_td_5">12.00</td>
            <td class="cart_td_6">
              <img src="img/taobao_minus.jpg" alt="minus" onclick="changeNum('num_4','minus')" class="hand" />
              <input id="num_4" type="text" value="2" class="num_input" readonly="readonly" />
              <img src="img/taobao_adding.jpg" alt="add" onclick="changeNum('num_4','add')" class="hand" />
            </td>
            <td class="cart_td_7"></td>
            <td class="cart_td_8">
              <a href="javascript:deleteRow('product4');">删除
              </a>
            </td>
          </tr>

          <tr>
            <td colspan="3">
              <a href="javascript:deleteSelectRow()">
                <img src="img/taobao_del.jpg" alt="delete" />
              </a>
            </td>
            <td colspan="5" class="shopend">
              商品总价(不含运费):<label id="total" class="yellow"></label><br />
              可获积分 <label class="yellow" id="integral"></label><br />
              <input name="" type="image" src="img/taobao_subtn.jpg" />
            </td>
          </tr>
        </form>
      </table>

    </div>
  </body>

</html>

cart.css

body{
    margin:0px;
    padding:0px;
    font-size:12px;
    line-height:20px;
    color:#333;
   }
ul,li,ol,h1,dl,dd{
    list-style:none;
    margin:0px;
    padding:0px;
    }
a{
    color:#1965b3;
    text-decoration: none;
    }    
a:hover{
    color:#CD590C;
    text-decoration:underline;
    }
img{
    border:0px;
    vertical-align:middle;
    }
#header{
    height:40px;
    margin:10px auto 10px auto;
    width:800px;
    clear:both;
    }
#nav{
    margin:10px auto 10px auto;
    width:800px;
    clear:both;
    }
#navlist{
    width:800px;
    margin:0px auto 0px auto;
    height:23px;
    }
    #navlist li{
        float:left;
        height:23px;
        line-height:26px;
    }
    .navlist_red_left{
        background-image:url(../images/taobao_bg.png);
        background-repeat:no-repeat;
        background-position:-12px -92px;
        width:3px;
        }
    .navlist_red{
        background-color:#ff6600;
        text-align:center;
        font-size:14px;
        font-weight:bold;
        color:#FFF;
        width:130px;
        }
    .navlist_red_arrow{
        background-color:#ff6600;
        background-image:url(../images/taobao_bg.png);
        background-repeat:no-repeat;
        background-position:0px 0px;
        width:13px;
        }
    .navlist_gray{
        background-color:#e4e4e4;
        text-align:center;
        font-size:14px;
        font-weight:bold;
        width:150px;
        }
    .navlist_gray_arrow{
        background-color:#e4e4e4;
        background-image:url(../images/taobao_bg.png);
        background-repeat:no-repeat;
        background-position:0px 0px;
        width:13px;
        }
    .navlist_gray_right{
        background-image:url(../images/taobao_bg.png);
        background-repeat:no-repeat;
        background-position:-12px -138px;
        width:3px;
        }
#content{
    width:800px;
    margin:10px auto 5px auto;
    clear:both;
    }
    .title_1{
        text-align:center;
        width:50px;
        }
    .title_2{
        text-align:center;
        }
    .title_3{
        text-align:center;
        width:80px;
        }
    .title_4{
        text-align:center;
        width:80px;
        }
    .title_5{
        text-align:center;
        width:100px;
        }
    .title_6{
        text-align:center;
        width:80px;
        }
    .title_7{
        text-align:center;
        width:60px;
        }
    .line{
        background-color:#a7cbff;
        height:3px;
        }
    .shopInfo{
        padding-left:10px;
        height:35px;
        vertical-align:bottom;
        }
    .num_input{
        border:solid 1px #666;
        width:25px;
        height:15px;
        text-align:center;
        }
    .cart_td_1,.cart_td_2,.cart_td_3,.cart_td_4,.cart_td_5,.cart_td_6,.cart_td_7,.cart_td_8{
        background-color:#e2f2ff;
        border-bottom:solid 1px #d1ecff;
        border-top:solid 1px #d1ecff;
        text-align:center;
        padding:5px;
        }
    .cart_td_1,.cart_td_3,.cart_td_4,.cart_td_5,.cart_td_6,.cart_td_7{
        border-right:solid 1px #FFF;
        }
    .cart_td_3{
        text-align:left;
        }
    .cart_td_4{
        font-weight:bold;
        }
    .cart_td_7{
        font-weight:bold;
        color:#fe6400;
        font-size:14px;
        }
    .hand{
        cursor:pointer;
        }
.shopend{
    text-align:right;
    padding-right:10px;
    padding-bottom:10px;
    }
.yellow{
    font-weight:bold;
    color:#fe6400;
    font-size:18px;
    line-height:40px;
    }

cart.js

/*改变所购商品的数量*/
function changeNum(numId, flag) {
  /*numId表示对应商品数量的文本框ID,flag表示是增加还是减少商品数量*/
  var numId = document.getElementById(numId);
  if (flag == "minus") {
    /*减少商品数量*/
    if (numId.value <= 1) {
      alert("Number of babies must be greater than 0");
      return false;
    } else {
      numId.value = parseInt(numId.value) - 1;
      productCount();
    }
  } else {
    /*flag为add,增加商品数量*/
    numId.value = parseInt(numId.value) + 1;
    productCount();
  }
}

/*制作自动计算商品的总金额、总积分、小计*/
function productCount() {
  var total = 0; //商品金额总计
  var integral = 0; //可获商品积分

  var point; //每一行商品的单品积分
  var price; //每一行商品的单价
  var number; //每一行商品的数量
  var subtotal; //每一行商品的小计

  /*访问ID为shopping表格中所有的行数*/
  var myTableTr = document.getElementById("shopping").getElementsByTagName("tr");
  if (myTableTr.length > 0) {
    /*从1开始,第一行的标题不计算*/
    for (let i = 1; i < myTableTr.length; i++) {
      if (myTableTr[i].getElementsByTagName("td").length > 2) { //最后一行不计算
        point = myTableTr[i].getElementsByTagName("td")[3].innerHTML; //积分
        price = myTableTr[i].getElementsByTagName("td")[4].innerHTML; //单价
        number = myTableTr[i].getElementsByTagName("td")[5].getElementsByTagName("input")[0].value; //数量
        integral += point * number;
        total += price * number;
        myTableTr[i].getElementsByTagName("td")[6].innerHTML = price * number;
      }
    }
    document.getElementById("total").innerHTML = total;
    document.getElementById("integral").innerHTML = integral;

  }
}

//当窗体加载完毕
window.onload = productCount;

/*复选框全选或全不选效果*/
function selectAll() {
  var oInput = document.getElementsByName("cartCheckBox");
  for (let i = 0; i < oInput.length; i++) {
    oInput[i].checked = document.getElementById("allCheckBox").checked;
  }
}

/*根据单个复选框的选择情况确定全选复选框是否被选中*/
function selectSingle() {
  var k = 0;
  var oInput = document.getElementsByName("cartCheckBox");
  for (let i = 0; i < oInput.length; i++) {
    if (oInput[i].checked == false) {
      k = 1;
      break;
    }
  }
  if (k == 0) {
    document.getElementById("allCheckBox").checked = true;
  } else {
    document.getElementById("allCheckBox").checked = false;
  }
}

/*删除单行商品*/
function deleteRow(rowId) {
  //获取当前行的索引号
  var Index = document.getElementById(rowId).rowIndex;
  //删除当前行
  document.getElementById("shopping").deleteRow(Index);
  //连带删除当前行的前一行,及店铺信息行
  document.getElementById("shopping").deleteRow(Index - 1);
  productCount();
}

/*删除选中行的商品*/
function deleteSelectRow() {
  var oInput = document.getElementsByName("cartCheckBox");
  var Index;
  for (let i = oInput.length - 1; i >= 0; i--) {
    if (oInput[i].checked == true) {
      //  获取选中行的索引号
      Index = document.getElementById(oInput[i].value).rowIndex;
      document.getElementById("shopping").deleteRow(Index);
      document.getElementById("shopping").deleteRow(Index - 1);
    }
  }
  productCount();
}

/*删除选中行的商品*/
function deleteSelectRow() {
  var oInput = document.getElementsByName("cartCheckBox");
  var Index;
  for (let i = oInput.length - 1; i >= 0; i--) {
    if (oInput[i].checked == true) {
      //  获取选中行的索引号
      Index = document.getElementById(oInput[i].value).rowIndex;
      document.getElementById("shopping").deleteRow(Index);
      document.getElementById("shopping").deleteRow(Index - 1);
    }
  }
  productCount();
}

总结:

通过本章节内容,需要同学们了解JavaScript语言,掌握各知识点的内容,能够清楚的理解数据、类型、面向对象的思想,同时拥有一定的逻辑和分析能力,有一定的程序开发能能力,可以实现简单的流程控制操作,为鸿蒙开发积累更多的基础。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值