JavaScript
一、任务概述
编程语言是一个复杂的、繁琐的、原理概念居多的内容,不是几天就可以完全掌握的,需要不断的编写、练习、处理各种错误来积累经验,逐步加强对语言的理解与编程能力。
本章节的宗旨在于帮助学员了解程序,了解编程语言,掌握应用程序开发的核心思想,锻炼分析、逻辑等各方面。这些都是开发者必须要拥有的最基本的能力。
同时,鸿蒙系统也是基于js语言为核心的,掌握JavaScript对鸿蒙开发尤其重要。
二、任务目标
- 了解语言概念、标准、原理
- 掌握语言的特性,数据的处理
- 掌握语言与计算机以及用户之间的交互
- 锻炼思路、逻辑、提升应用程序的开发能力
- 养成良好的代码编写习惯,了解企业级应用开发标准
三、任务步骤
1、语言概述
JavaScript(以下简称:js)是互联网中,最流行的脚本语言,由美国ECMA小组负责维护的。
在2015年,ECMA发布了6.0的标准,全称:**ECMAScript 6.0**,它与之前的标准完全不同,代表着一个全新的时代,直到今天,**ES6**依然是后续版本的一个重要的基础标准。
ES6引入了许多新特性,旨在使js适用于编写复杂的大型应用程序,并成为企业级开发语言。这些特性提高了编码效率和代码质量,使JavaScript语言更加成熟和完整。
js是弱语言,解释执行的,它由浏览器中的js引擎负责读取,解释,运行。浏览器js引擎会读取一行,解释一行,执行一行,因此,js代码的先后顺序尤其需要注意。
2、js的十大优越性
- 易学易用: JavaScript的语法与许多其他编程语言相似,特别是与C和Java有很多相似之处。这使得许多开发人员能够相对容易地学习和使用JavaScript。
- 广泛的支持: JavaScript是Web开发的核心语言之一,几乎所有现代浏览器都支持JavaScript。这使得JavaScript成为前端开发的首选语言。
- 多范式: JavaScript是一种多范式的编程语言,支持面向对象编程(OOP)、函数式编程(FP)和命令式编程。这种灵活性允许开发人员采用不同的编程风格来解决问题。
- 动态类型: JavaScript是一种动态类型语言,不需要显式声明变量的类型。这简化了代码编写过程,同时也增加了灵活性。
- 强大的标准库: JavaScript拥有丰富的标准库,包括用于处理字符串、日期、数组、对象等的内置函数。这些内置函数提供了大量功能,使得开发任务更加高效。
- 跨平台: JavaScript不仅在Web浏览器中运行,还可以用于服务器端开发(Node.js),实现了前后端代码的共享,提高了开发效率。
- 活跃的社区: JavaScript拥有庞大而活跃的开发社区,提供了丰富的教程、库和工具。这使得开发人员能够快速解决问题和获取支持。
- JSON支持: JavaScript对象表示法(JSON)是一种轻量级的数据交换格式,与JavaScript密切相关。JavaScript原生支持JSON,这在Web应用程序中用于数据交换非常有用。
- 事件驱动: JavaScript是事件驱动的语言,适用于创建响应用户交互的Web应用程序。这种特性使得JavaScript非常适合构建富交互性的应用程序。
- 动态网页交互: 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。由于符号前后位置不同,会导致在具体运算公式里面,产生的结果也不同。
运算符 | 说明 | 赋值或运算公式中 |
---|---|---|
++a | a+1 | 先执行完毕,在执行赋值或运算 |
–a | a-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(表达式){
case 值1:
//代码块
break;
case 值2:
//代码块
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():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回 true。
var 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():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回 true。
var 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() 方法会按照一个可指定的深度递归遍历数组,
并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
该方法返回一个新数组,对原数据没有影响。
参数: 指定要提取嵌套数组的结构深度,默认值为 1。
const 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语言,掌握各知识点的内容,能够清楚的理解数据、类型、面向对象的思想,同时拥有一定的逻辑和分析能力,有一定的程序开发能能力,可以实现简单的流程控制操作,为鸿蒙开发积累更多的基础。