学习javascript数据结构和函数

网页三剑客

  • HTML是内容和结构,相当于身体
  • CSS是外观样式和布局,相当于衣服装饰
  • javaScript是活动,相当于灵魂和动作

javascript组成

由三部分组成BOM、DOM、ECMAScript,主要作用是用ECMAScript语法去操作BOM和DOM。

  • BOM-操作浏览器发生变化的属性和方法,例如滑动到首页,滚动条是浏览器的

  • DOM-操作文档流发生变化的属性和方法,比如文字内容改变,倒计时

  • ECMAScript-JS的书写语法和书写规则,比如什么时候加连接符,

JavaScript书写位置

行内式、内嵌式、外链式

  • 行内式,是直接把代码书写在标签内,分为a标签和非a标签的书写格式

    • a标签书,写在href属性上,需要导入JavaScript包
    <a href="javasript: alert('hello world');">点我试试</a>
    //在浏览器弹出一个提示框,alert();
    • 非a标签,写在属性上,添加行为属性
    <a href="#" onclick="alert('hello world');">点我试试</a>
  • 内嵌式,是把放在标签对内

    <sript>
    代码
    </script>
  • 外链式,把代码书写在.js文件内,在HTML通过引入,src属性专门引入

<sript src=".js文件路径"></script>
一般放在body最后

数据结构

JavaScript变量

  • 关键字 var或let,准备一个容器

  • 书写方式 var 名字 = 数据;

  • 一个变量只能存储一个值,当再次赋值值,会替换内容!

  • 变量名称是标识符

注释

  • 单行 //

  • 多行 /* */

打印

alert('打印内容');浏览器弹出框

console.log('打印内容');控制台

document.write('打印内容');页面中

数据类型

基本数据类型

  • 数值Number:十进制,科学计数法,其它进制0x 0o

  • 字符串String:一切以单引号’ ‘或双引号“ ”包裹的内容

  • 布尔Boolean:ture或false两个值,其中undefind、null、””、0、NaN、false都是假值;

  • Null:赋值为null;

  • 未定义Undefined:变量未赋值;

运算后得到的值,进行不知道类型,进行类型检测

- 使用 typeof 关键字来进行数据检测,运算结果是该变量的数据类型

    - `typeof 待检测的值`

数据类型转换

​ 处理数据值,数据类型不对,比如当输入框提交的数据为文本,想转化为数字进行运算!

  • ==转数值==:把其它类型值,转化为数值!
  1. Number:Number(); 括号内待转值,结果为转换的数值,如果可以转,结果就是数字,不可以则是NaN
  2. parseInt:parseInt();括号内待转值,结果为转换的数值,同理!当数字和文本结合时,一个一个字符读取转换,当碰到可以转换时就是数字,不可以就停止,最终结果就是可以转换的数字!
  3. parseFloat:parseFloat();与上同理;能解析到小数部分!
  • ==转字符串==:同理
  1. String:String();括号内待转值,结果为转换的字符串
  2. toString:.toString();前面填待转值,括号内不用填,结果为转换的字符串
  • ==转布尔==:同类
  1. Boolean:Boolean()括号内待转值,结果为转换的布尔值!除6种false,其它都是true!

运算符

  • ==算术运算符==:+ - * / %

    • +:加法运算
      • 当两边都是数字,两边都是布尔,进行数学运算
      • 当任意一边是字符串,进行字符串拼接,结果是个字符串
    • 其它:- * / %只能进行数学运算!
  • ==赋值运算符==:= += -= *= /= %= 先运算再赋值

    • =:赋值操作
  • ==关系运算符==:大小关系运算 > < >= <=、等值运算== === != !==,结果一定是布尔值

    • > < >= <=
    • == === != !==:两个等号,不考虑数据类型,只看值,三个等号,要考虑数据类型!
  • ==逻辑运算符==:&& || !与、或、非(取反),单目

  • ==自增自减运算==:++ --单目运算

    • 前置并参与运算时,先自增(减),再参与其它运算
    • 后置并参与运算时,先参与其它运算,再自增(减)
  • ==条件运算符==:布尔表达式?值1:值2三目运算,运算结果为值1或者值2的结果!

  • a!='undefined' ? a=a : a=0;
    a = a>1 ? a++ : a--; 
    
    ## 	引用数据类型

    # 函数

    ## 结构

    ### 分支结构

    #### if语句

    - `if(){}`:根据()内的布尔值,决定是否执行接着的内容!

    - ()里面写的是条件,一般是逻辑运算、关系运算;
    - {}里面写的是满足条件时,执行的代码,一般是处理命令,算法步骤;

    - `if(){}else{}`:根据()内的布尔值,true时执行if后的{};false时执行与之相邻的else后的{}!

    - 衍生`if(){}else if(){}`:哪个条件满足就执行哪个,前面执行了,后面就不执行了

    - ```javascript
    if(){

    }else
    if(){

    }
    - 衍生`if(){}else if(){}else{}`:依次判断,都不满足,执行最后else的代码! - ```javascript if(){ }else if(){ }else{ }
      
    - 可以嵌套使用!

    ​ **案例**:判断平年,还是闰年

    ```javascript
    //可以被4整除的,且不能被100整除,或者能被400整除的都是闰年!
    //条件:(year%4===0 && year%100!==0) || year%400===0
    //执行语句:year+'是闰年' 否则 year+'不是闰年'
    let year = 2078;
    if(year%4===0 && year%100!==0 || year%400===0){
    console.log(year+'是闰年');
    }else{
    console.log(year+'不是闰年');
    }

switch语句

switch(){case 比较值1: case 比较值2: }:根据()内的已知条件,与case后的值进行比较,完全匹配后,执行对应的代码!也可以改写成if第3种模式[^if(){}else if(){}else{}],本质执行的就是if语句!

switch(已知条件){
case 比较值1:

case 比较值2:

}

使用==break;==,结束语句,跳出选择框!如果没有break;且其中某个值匹配,后面的语句直接穿透执行!即忽视后面case的值,直接执行case对应的语句!从第一个满足条件的位置向下穿透,直到出现break!

switch(已知条件){
case 比较值1:

break;
case 比较值2:

break;
}

使用default:,在所有选项都不符合时,执行默认语句!

switch(已知条件){
case 比较值1:

break;
case 比较值2:

break;
default:

}

案例,几月几日是这一年的第几天?

//通过加法计算,几月几日中,每一个【月的天数】相加,最后加上单独的【日的天数】!
//利用switch的穿透,先计算几个月的天数相加,最后加上日!
//case有几个月 totalDays=totalDays+当月天数,如果是1月,则月份上需要加0天,直接计算日的天数,如果是2月,则过去的的1个月天数相加,如果是12月,则是过去的前11个月天数相加,例如"12月5日=11月天数+10月天数+9月天数....1月天数+最后加上5日"所以先写12,向下穿透执行每月相加!
case 12: totalDays=totalDays+30;
case 11: totalDays=totalDays+31;
case 10: totalDays=totalDays+30;
case 9: totalDays=totalDays+31;
case 8: totalDays=totalDays+31;
case 7: totalDays=totalDays+30;
case 6: totalDays=totalDays+31;
case 5: totalDays=totalDays+30;
case 4: totalDays=totalDays+31;
case 3: totalDays=totalDays+30;
case 2: totalDays=totalDays+31;
//再最后,判断平年和闰年,给2月加上不同的天数!
if(year%4===0 && year%100!==0 || year%400===0){
totalDays=totalDays+29;
}else{
totalDays=totalDays+28;
}
//最后totalDays=totalDays+日的天数
totalDays=totalDays+day;
//定义年月日三个变量!分别赋值!

循环结构

while语句

  • while(){}:当()中为真,则执行{}语句,依次执行结束后,再返回判断()中是否为真!

    • 当()的布尔值与{}中的语句==无关==时,则一直执行,或者从不执行,于是,一般放一个待改变的值!
    • ()中的布尔值,在{}中的执行语句改变其值,从而跳出循环!()内一般是关于变量的关系运算!
    • break终止上一层循环!
    定义初始值;
    while(初始值>n){
    执行语句1
    执行语句2
    ......
    改变初始值;
    }
    //初始值、(条件判断)、改变初始值步数,三者都可以改变循环次数!
    //循环过程中,初始值变量是规律变化的,从而得到规律的步长值!
    • while()循环时,当执行到()为真时,则开始循环;为假时,则结束循环;不改变则是死循环!
    • 定义==控制变量初始值==多少、==条件判断==、执行语句中==改变初始值步数==多少,都可以控制循环次数,且==控制变量==是有规律的变化!

    案例:求10的阶乘!1*2*3*4*5*6*7*8*9*10

    //积=积*(变量+1)
    let i = 1;
    let number=1;
    while(i<11){
    number =number * (i+1);
    i++;
    }
    //10! 10*9*8*7*6*5*4*3*2*1
    //最左积=最左积*(控制变量);利用有规律变化的控制变量,从9变化到1,简写成total *=控制变量;
    total=total*i;
    //控制变量初始值为9
    let total=10;
    let i=total-1;
    //改变初始值
    i--;
    //条件判断来控制变量改变到多少,改变到最小为1就行!
    (i>0)

    do-while语句

  • do{}while();与while()可以互换,

    • 不同的是,是先执行{}中的语句,再判断(),{}中的语句至少执行一次,适合连贯的节奏!

    案例:在浏览器弹出个问题和输入框prompt(),回答正确,结束;回答错误,继续回答!

    //浏览器弹出输入框prompt(),(中为提示内容,可以显示在框上面!)
    //输入的内容,就是prompt()的运算结果!
    //分析,首先弹出输入框,回答问题,判断输入的文本,是否为设置的结果,不是,就继续弹出!
    let answer;
    do{
    answer = prompt('你是不是狗?');
    }while(answer !== '是');
    alert('真的狗');

    for语句

  • for(){}:与while()一样,==定义变量==;==条件判断==;==改变初始值==循环三要素,再加上要循环的代码!

    • for()中的小括号,把(定义变量;条件判断;改变初始值)三要素包裹在一起,{}放重复执行的代码!
    • 执行顺序与while()一致,优势是避免忘记,设置改变初始值,避免死循环!
    • 可以嵌套使用!
    for(定义变量;条件判断;改变初始值){
    重复执行的代码;
    }
    //执行顺序与while()一致,先定义变量,再条件判断,再重复执行的代码,最后才是改变初始值,再然后条件判断,再重复执行的代码,再改变初始值,再条件判断......

    案例:在控制台输出1~100,所有3的倍数!

    //能整除3,余数为0
    //拿到1~100的所有数字,这里借助初始值变量,按步长变化,得到1~100个数!
    for(let i=1;i<=100;i++)
    //是3的倍数就输出,否则什么也不做
    if(i%3===0){
    console.log(i);
    }
    最终程序
    for(let i=1;i<=100;i++){
    if(i%3===0){
    console.log(i);
    }
    }
    //使用while()改写
    let i = 1;
    while(i<=100){
    if(i%3===0){
    console.log(i);
    }
    i++;
    }

    循环嵌套练习

    案例:页面中打印9行9列*,呈现为正方形

    //在页面中输出一个*号
    document.write('*');
    //在页面中输出一行9个*号,执行9次document.write('*');
    //还可以用&nbsp来调整间隔,使用h5标签
    for(let i=0;i<9;i++){
    document.write('*&nbsp&nbsp&nbsp');
    }
    //在页面中输出一行9个*号,再输出一行9个*号...直到9行,把一行的执行9次,每次后换行标签!
    for(let j=0;j<9;j++){
    for(let i=0;i<9;i++){
    document.write('*');
    }
    document.write('<br/>');
    }
    //改写为while()
    let j=0; //定义外层初始变量
    while(j<=9){
    let i=0; //定义内层初始变量
    while(i<=9){
    document.write('*&nbsp&nbsp&nbsp');
    i++; //改变初始变量
    }
    document.write('<br/>');
    j++;
    }
    //本质和for一致,先在循环体前定义变量,紧接着就是判断条件,然后是循环语句,最后是改变变量!

    案例:页面中打印9行9列*,呈现为三角形

    //第一行1个*,第二行2个*...,第九行9个*
    //第一行
    for(i=1;i<=1;i++){
    document.write('*&nbsp&nbsp&nbsp');
    }
    document.write('<br/>');
    //第二行
    for(i=1;i<=2;i++){
    document.write('*&nbsp&nbsp&nbsp');
    }
    document.write('<br/>');
    //再用一个循环,来控制判断条件中的小于等于变量j,每循环一次,执行j++;
    for(let j=1;j<=9;j++){

    }
    //最终代码如下,内层循环打印*,外层控制行,内层控制列!一行1列,2行2列,用外层变量控制内层次数,改变内层循环的判断条件,外层循环既实现循环9次,又用初始变量实现控制内存的循环次数!
    for(let j=1;j<=9;j++){
    for(i=1;i<=j;i++){
    document.write('*&nbsp&nbsp&nbsp');
    }
    document.write('<br/>');
    }
  • 两层循环嵌套,==外层循环==的==初始变量==作为==内层循环==的判断条件!

    • for(){for(){}}==外层循环==既实现==内层循环==循环9次,==初始变量==实现控制==内层循环==的循环次数!
    • 内层for()的条件判断,i<=j是由两个变量构成,共同来控制循环次数,重点是右侧的j是变化的,也就意味着,内层的循环次数,也是由外层初始变量控制!即第1次执行外层,内层循环1次;第2次执行外层,内层循环2次;第3次执行外层,内层循环3次;
    • 到最后,外层执行一次,内层执行9次!==外层执行一次,内层执行j次!==
    //使用while()实现
    let j = 1;
    while(j<=9){
    let i = 1;
    while(i<=j){
    document.write('*&nbsp&nbsp&nbsp');
    i++;
    }
    document.write('<br/>');
    j++;
    }

    案例:页面打印九九乘法表

    //利用上方程序,可以控制每行排列,再用循环控制输出,显示的内容!
    //第一个内容为1*1=1,三个变量,这三个变量,其中两个变量和循环的初始变量一致!再设个结果变量
    document.write('i');
    document.write('*');
    document.write('j');
    document.write('=');
    document.write('sum');
    //或者用`+`连接字符和变量!
    document.write(i+'*'+j+'='+sum);
    //总体代码
    let sum;
    for(let j=1;j<=9;j++){
    for(i=1;i<=j;i++){
    sum=i*j;
    document.write(i+'*'+j+'='+sum+'&nbsp&nbsp&nbsp');
    }
    document.write('<br/>');
    }

    案例:寻找最大公约数!输入框

    //公约数,就是同时被两个数字整除,余为0,关系为且
    //最大,也就是众多公约数中,最大的那个公约数,存在范围是,小于两个数较小那个,大于1
    //输入两个数,判断大小
    let x = prompt('第一个数');
    let y = prompt('第二个数');
    //用循环来一个数一个数试,范围是从1开始,直到两个数较小那个,用三目判断大小!
    for(let i=1;i<=(x>y?y:x);i++)

    //最终程序,从1到其中较小一个数,依次验证
    let x = prompt('第一个数');
    let y = prompt('第二个数');
    let j;
    for(let i=1;i<=(x>y?y:x);i++){
    if(x%i===0&&y%i===0){
    j=i;
    }
    }
    document.write(j);

    //最终程序2,从大到小的验证,第一个满足条件的就是最大的!更方便,从新改写,用break终止循环!
    let x = prompt('第一个数');
    let y = prompt('第二个数');
    for(let i=(x>y?y:x);i>=1;i--){
    if(x%i===0&&y%i===0){
    document.write(i);
    break;
    }
    }

    案例:寻找最小公倍数!

    //公倍数:能同时整除两个数,余为0,关系且,最小就是众多公倍数最小那个!
    i%m===0 && i%n===0
    //设置m、n两个变量,公倍数范围是大于两个数,至无限!最小公倍数范围是较大数至m*n内,利用for的初始变量,来遍历这个范围,利用if判断结果,利用break提前退出循环!找到最合适遍历范围!
    //最终程序
    let m = prompt('第一个数');
    let n = prompt('第二个数');
    for(let i=(m>n?m:n);i<=m*n;i++){
    if(i%m===0 && i%n===0){
    document.write(i);
    break;
    }
    }
    //最终程序2,最小公倍数范围是较大数至m*n内,且最小公倍数除较大数,是1、2、3这种整数才行,也就是说,这个范围还可以缩小,去掉不是较大数的倍数!所以改变步长为较大数`i+较大数`
    let m = Number(prompt('第一个数'));
    let n = Number(prompt('第二个数'));
    let larger = m>n?m:n;
    for(let i=larger;i<=m*n;i=i+larger){
    if(i%m===0 && i%n===0){
    document.write(i);
    break;
    }
    }

函数

一种==数据类型==,只不过可以存储一大段代码,用function关键字定义,分定义和调用!

  • 函数定义阶段-声明函数:把代码装进盒子,不执行函数体内代码
  • 函数调用阶段:把盒子里面的代码执行
function 标识符取名字(){

装在盒子里的代码
...

}

定义阶段

  • 关键字function后写函数名()内可以放变量,叫做==形参==,{}内可以存放代码。
    • 形参是个特殊的变量,只能函数内部使用,值由调用时,实参决定!

调用阶段

  • 函数名();调用就能执行{}内的代码,()可以输入值,叫做==实参==,也就是给形参赋值!运行后可以返回值!也就是函数的运行结果!

为什么需要函数?函数一般可以设置为一种通用方法,用来完成某项任务或者计算,把执行这种方法的代码封装在{}函数体内,比如求阶乘,求最小公倍数。一个函数解决一类问题,只需要输入值,就能输出计算后的结果!

案例:求10的阶乘函数!

//定义函数
function factorial(n){
let sum=1;
while(n>=1){
sum =sum*n;
n--;
}
document.write(sum);
}
//调用函数
factorial(10);

调用函数factorial();括号内可以给任意正整数!就可以求相应整数的阶乘,一个函数实现一项完整功能!

案例:11的阶乘输出到控制台,18的阶乘输出到页面中!

function factorial(n){
let sum=1;
while(n>=1){
sum =sum*n;
n--;
}
return sum;
}
document.write(factorial(18));//调用函数,赋值为18,计算结果为18的阶乘,并显示在页面上
console.log(factorial(11));//调用函数,赋值为11,计算结果为11的阶乘,显示在控制台上
  • return 值;把函数看成是一个值,调用函数时,函数本身就是一个值!一个有输入,有输出的值!
  • 这才是函数的本体,最重要的功能,像一个处理工厂,给原料,就能加工成成品!只是搬运工!不完整的计算,只处理运算,输出的结果再由另外的代码处理!
  • ==没有返回值时,主要把函数看成一个完整功能,有返回值时,可以把函数制当成一个值(处理值的值)!==

函数的返回值

当函数调用时,添加结果!作为函数的返回值!即运算后是一个值!又变成了一个数据!

//看看之前用到的函数
let num = Number('666');//输入值'666',返回值666,参与其它运算,赋值给num!
let str = String(7);

//同理,上一个求阶乘函数
let fac = factorial(18);//输入值18,返回值18的阶乘结果,参与其它运算,赋值给fac!

递归函数

函数的一种应用方式,==递==:向下逐层传递,==归==:向上逐层返回

  • 在调用函数的时候,把问题逐层解决!比如排队时,想知道自己是第几个,问前一个直到第一个,再逐层返回答案;特点是,你的问题变成了前一个人的问题,逐层类推,你的问题变成大家的问题,大家的问题解决了,你的问题就解决了!只要前面有一个人知道答案,后面直到你都能知道答案!
    • 位置(我)=位置(前一个人)+1
    • 我和前一人是同一类型问题,同一函数就可以解决!且我的位置要,在前一位置的结果上计算!并且在前面的函数有返回值,让函数本身变成一个值,参与运算,继续返回值,最后得出结果!
    • 函数本身即是一串代码集合,又是一个值!递的过程就是累计代码,归的过程就是函数返回值!巧妙在于,返回的是问题的结果,每个结果又被当作是运算的一部分!
    • 当一个问题可以设计成问题本身参与运算时,便可以用递归,设计时先想结果!即返回值形式!

案例:100的阶乘

100!=100*99*98*97*96*95*94...*3*2*1

100!=100*99*98*97*96*95*94...*3*2*1
100!=100*99! //100!和99!是同一类型问题,一类函数就可以解决,此时100!是我们需要的答案!也就是函数返回值!然后自己调用自己!
99!=99*98!
...
2!=2*1

//递进关系
function factorial(n){
return n*factorial(n-1);
}

==递归==:一个函数调用了它自身,这种现象就称为递归!

//最终函数,求10!
function factorial(n){
if(n===1) return 1; //设置折返点!不然无穷向下递进,没有归的过程!1的阶乘不需要计算
return n*factorial(n-1);
}
document.write(factorial(10));

==递归函数==:一个函数调用自身,并设置了结束条件,这个函数才是一个正确的递归函数!

案例:斐波那契数列!求数列第n位是多少?

//规则:第一位和第二位必然是1,第三位开始,每位是前两个数之和!
1 1 2 3 5 8......
//第n位是函数返回值,也就是函数的计算结果!且第n位是第(n-1)位与第(n-2)位之和
fbl(n)=fbl(n-1)+fbl(n-2);
return fbl(n-1)+fbl(n-2);
//每个fbl()都可以拆成fbl(-1)+fbl(-2),子辈也可以看成是新的fbl(),无限套娃!
fbl(n)=fbl(n-1)+fbl(n-2);
=fbl(n-2)+fbl(n-3)+fbl(n-3)+fbl(n-4);
...
=fbl(n-m)+fbl(n-m-1)+fbl(n-m-2)+...+fbl(n-2m);

//其中n和m都是已知量,无非是以下形式,能消则消,不能消就继续拆!
...
fbl(5)=fbl(4)+fbl(3) //fbl(4)+fbl(3),还是无法消除
fbl(4)=fbl(3)+fbl(2) //返回fbl(3)+1,消除了一个
fbl(3)=fbl(2)+fbl(1) //返回1+1,消除了两个

//每个fbl()形式都可以转换成无数个更小的两个fbl()之和,最终会转换到fbl(2),fbl(1)!赋值fbl(2)和fbl(1)为1,就可以消去函数,变为数字1;
//就像下雨,从天上分散下来,落到地面就消失,fbl()拆分时遇到fbl(2)和fbl(1)形式就变成数字1

//最终程序!
function fbl(n){
if(n===1 || n===2) return 1; //最终是fbl(2)或fbl(1)时,返回1;
return fbl(n-1)+fbl(n-2);
}
let m=Number(prompt('请输入需要求的斐波那契数列第几位'));
document.write(fbl(m));

作用域

一个变量可以在什么范围内使用?

作用域

  • 范围:有层级关系,像倒树状!父子,兄弟!
    • 全局作用域:一个页面,就是一个全局
    • 私有作用域:只在==函数==才能生成私有作用域!
  • 使用
    • 定义:声明在什么位置的变量,就作用于哪个范围,就是哪一个作用域的变量!
    • 访问:获取变量的存储的值,自己没有就用父级,以此类推,全局都没有就报错!
    • 赋值:变量赋值,自己没有这个量,就父级找,以此类推,都没有就定义一个全局变量再赋值!

对象

就是一个可以装很多数据的盒子,就像个书架,可以放很多书,按对应书名就可以查看书!

  • ==创建==对象:let obj = {},和创建变量类似,制作个盒子,不同的是有个大括号{};现在是个空对象,里面可以存放键值对,就是名:值对象相当于键值对的集合!每个键值对用逗号隔开!
  • 对象的==操作==:对象内==键值对==的操作!
    • 增:对象内添加一个键值对
      • obj.name = '小可爱'
      • obj['name'] = '小可爱'[]内是字符串格式
    • 删:使用delete关键字,删除对象内一个键值对
      • delete obj.name
      • delete obj['name']
    • 改:修改对象内一个键值对的,与增的语法一致,有则改,无则增!
    • 查:访问对象内一个键值对的
      • obj.name
      • obj['name']

数组

有序的数据的集合!

  • ==创建==数组:let arr = [],和创建变量类似,制作个盒子,不同的是有个大括号[],直接把想要储存的数据写里面,不需要取名字!因为每个值都有序号,这是有顺序的集合,每个值用逗号隔开!可以存储==任何数据类型==!
    • 索引(下标):从0开始,依次加1;
  • 数组的==操作==:
    • 长度的操作
      • 获取长度:数组名.length
      • 设置长度:数组名.length=数字,赋值就行,少于原始长度时,后续值删除!
    • 数据的操作
      • 获取:数组名[索引]
      • 设置:数组名[索引]=值,赋值就行
  • 数组的==遍历==:依次访问数组中每个数据!利用循环,步长为1,从0开始!变量为索引!

冒泡排序

把数据为乱序的数组,排列成顺序数据,冒泡是其中的一种方法!

  • 冒泡排序是把前两个数据,比较大小,设置前>后,当为真时,交换位置,重复操作!操作数倒三角
//a=[6,4,7,3,1,9,2,5,8],从前都后,两两比较,大则交换,一轮结束,最大在最后,重复操作!
//设置两个变量,比较,交换值!
//let a=[6,4,7,3,1,9,2,5,8];
//执行操作,两个数交换位置,即需要第三个杯子!什么时候交换,需要if语句
if(a[0]>a[1]){
cup = a[0];
a[0] = a[1];
a[1] = cup;
}
//谁和谁交换,设置个变量,来选择第几位数!
//满足倒三角,需要两层循环变量!并调整其初始值和步长,成为选择数组的下标!
//最终程序,创建个中间变量,负责交换中存放值!
let a=[6,4,7,3,1,9,2,5,8];
let aleng = a.length;
for(let k=aleng;k>=1;k--){ //外层循环是,需要排(数组长度)-1个最大值!
for(let i=0,j=1;i<k;i++,j++){ //内层循环是遍历一遍,排好一个最大值
let cup;
if(a[i]>a[j]){ //if语句复制判断交换,j可以不用设置,使用i+1;
cup = a[i];
a[i] = a[j];
a[j] = cup;
}
}
}
console.log(a);
//最终版2
//最终程序,创建个中间变量,负责交换中存放值!
let a=[6,4,7,3,1,9,2,5,8];
let cup;
for(let k=a.length;k>1;k--){ //外层循环是,需要排(数组长度)-1个最大值!
for(let i=0;i<k-1;i++){ //内层循环是遍历一遍,排好一个最大值,第k-1个数与k交换
if(a[i]>a[i+1]){ //if语句复制判断交换,j可以不用设置,使用i+1;
cup = a[i];
a[i] = a[i+1];
a[i+1] = cup;
}
}
}
console.log(a);

选择排序

牢记:不要过多数据,需要关注==索引==

设第一个为最小值,依次比较,遇到更小的数,把索引记下来,让这个数继续依次比较至末尾,最后把最小的数字与假设的值交换!

//假设最小数字的索引为:0,真实最小数字的索引为:5
//更小的数的索引,记录下来
let min;
if(a[0]>a[1]){
min=1;
}
//设置变量,利用循环依次比较,下标对应的变量,比较一轮,找出最小数的下标
let min = 0;
for(i=1;i<a.length;i++){
if(a[min]>a[i]){
min=i;
}
}
//利用下标,交换'真实最小数'与'设定的最小数'的位置!
let cup;
cup = a[0];
a[0] = a[min];
a[min] = cup;
//用嵌套执行下一轮,利用嵌套循环的变量,决定下一轮从新开始比较的位置,也就是设定新的最小值!
//最终程序
let a=[6,4,7,3,1,9,2,5,8];
let sizenum = a.length;
let cup;
for(j=0;j<sizenum-1;j++){ //让变量j当设置的最小值下标!
let min = j;
for(i=j+1;i<sizenum;i++){ //循环一轮,找出这轮最小值下标
if(a[min]>a[i]){
min=i;
}
}
cup = a[j]; //把这轮最小值与设定的最小值交换!
a[j] = a[min];
a[min] = cup;
}
console.log(a);

数组常用方法

帮助我们对数组进行快速,记住就行,没有逻辑

  • push()方法,将数据追加到数组末尾
    • 语法:数组.push(数据)
    • 返回值:数组最新的长度
  • pop()方法,删除数组末尾数据
    • 语法:数组.push()
    • 返回值:被删除的数据,一个数据值!
  • unshift()方法,数组最前面添加一个数据
    • 语法:数组.unshift(数据)
    • 返回值:数组最新的长度
  • shift()方法,删除数组最前面的数据
    • 语法:数组.shift()
    • 返回值:被删除的数据,一个数据值!
  • reverse()方法,将数组反转
    • 语法:数组.reverse()
    • 返回值:反转后的数组,一个数组
  • splice()方法,删除数组中若干数据,并选择是否插入新的数据!截取并拿走,会改变数组
    • 语法:数组.splice(开始索引,多少个,要插入的数据)
      • 开始索引:默认为0
      • 多少个:默认为0
      • 要插入的数据:默认没有,如果写的话,从哪儿删除,从哪儿插入
    • 返回值:以数组的形式,返回被删除的数据
  • sort()方法,对数组进行排序
    • 语法有三种:
      • 数组.sort(),结果为位排序
      • 数组.sort(function(a,b){return a-b}),传递一个函数作为参数,结果为升序
      • 数组.sort(function(a,b){return b-a}),传递一个函数作为参数,结果为降序
    • 返回值:排序好的数组

  • join()方法,将数组变成一个字符串,形式为数据+连接符,原数组无变化!

    • 语法:数组.join(连接符)
    • 返回值:连接好的字符串
  • concat()方法,将其它数组和原始数组拼接在一起!两个数组合并成一个数组。

    • 语法:数组.concat(其它数组)
    • 返回值:合并好的数组
  • slice()方法,截取数组中部分数据,相当于切片面包

    • 语法:数组.slice(开始索引,结束索引)
      • 开始索引:默认为0
      • 结束索引:默认为数组长度,注意是索引包括之前,不包括索引之后的数据。
    • 返回值:以数组形式,返回截取的数据
  • indexOf()方法,查找数据,在数组中,的索引

    • 语法:数组.indexOf(数据)
    • 返回值:一个数字
      • 有该数据,返回第一次出现的索引位置;
      • 没有该数据,返回-1
  • forEach()方法,遍历数组

    • 语法:数组.forEach(function(item,index,arr){})
    • 传递一个函数作为参数,数组有多少个数据,这个函数就执行多少次!
      • item:数据的每一项
      • index:索引
      • arr:原始数组
    • 返回值:无
    let arr=[1,2,3,4,5,6,7,8]
    arr.forEach(function(item,index,arr){
    console.log(item);
    console.log(index);
    console.log(arr);
    })
  • map()方法,映射数组

    • 语法:数组.map(function(item,index,arr){})
    • 添加一个映射条件即可,以return的方式书写
      • item:数据的每一项
      • index:索引
      • arr:原始数组
    • 返回值:映射好的数组
let arr=[1,2,3,4,5,6,7,8]
let retnum=arr.map(function(item,index,arr){
return item*10; //以return的方式书写映射条件
})
console.log(retnum);
  • filter()方法,过滤数组

    • 语法:数组.filter(function(item,index,arr){})
    • 添加一个过滤条件即可,以return的方式书写
      • item:数据的每一项
      • index:索引
      • arr:原始数组
    • 返回值:过滤好的数组
    let arr=[1,2,3,4,5,6,7,8]
    let retnum=arr.filter(function(item,index,arr){
    return item>5; //以return的方式书写过滤`条件`
    })
    console.log(retnum);
  • every()方法,判断数组中每个数据是否满足条件,都满足则返回ture

    • 语法:数组.every(function(item,index,arr){})
    • 添加一个条件即可,以return的方式书写
      • item:数据的每一项
      • index:索引
      • arr:原始数组
    • 返回值:一个布尔值,代表是否每一项都满足条件
    let arr=[1,2,3,4,5,6,7,8]
    let retnum=arr.every(function(item,index,arr){
    return item>5; //以return的方式书写判断`条件`
    })
    console.log(retnum); //返回false
    let arr=[1,2,3,4,5,6,7,8]
    let retnum=arr.every(function(item,index,arr){
    return item>0; //以return的方式书写判断`条件`
    })
    console.log(retnum); //返回ture
  • some()方法,判断数组中,是否有数据满足条件,有一个满足则返回ture

    • 语法:数组.some(function(item,index,arr){})
    • 添加一个条件即可,以return的方式书写
      • item:数据的每一项
      • index:索引
      • arr:原始数组
    • 返回值:一个布尔值,代表至少有一项满足条件
    let arr=[1,2,3,4,5,6,7,8]
    let retnum=arr.some(function(item,index,arr){
    return item>5; //以return的方式书写判断`条件`
    })
    console.log(retnum); //返回ture
  • 总结,前7个方法都会直接改变数组,后9个不改变原始数组!

字符串常用方法

字符串可以看成是数组,也是按照索性进行排列的,一个字符就是一个索引位置!这就是字符串的排列!

  • charAt()方法,获取字符串索引位置的字符,从索引是从0开始计数。
    • 语法:字符串.charAt(索引)
    • 返回值:对应索引的字符
  • toLowerCase()方法,将字符串中字母全部转换成小写
    • 语法:字符串.toLowerCase()
    • 返回值:转换好的字符串
  • toUpperCase()方法,将字符串中字母全部转换成大写
    • 语法:字符串.toUpperCase()
    • 返回值:转换好的字符串
  • replace()方法,替换字符串,将字符串内,第一个 满足换下内容的片段替换成换上内容
    • 语法:字符串.replace(换下内容,换上内容)
    • 返回值:替换好的字符串
  • trim()方法,去掉字符串首尾空格!中间空格不会去掉!
    • 语法:字符串.trim()
    • 返回值:去掉首位空格的字符串
  • split()方法,按照分隔符,将字符串,切割成一个数组!这个分隔符存在于字符串中!
    • 语法:字符串.split(分隔符)
    • 返回值:切割数据后的字符串数组!
  • 统一说三个方法,都是截取字符串,返回截取出来的字符串
    • substr()
      • 语法:字符串.substr(开始索引,==多少个==);
    • substring()
      • 语法:字符串.substring(开始索引,结束索引);
    • slice()
      • 语法:字符串.slice(开始索引,结束索引);
  • 总结,都不会改变原来的字符串,以返回值方式使用!

数字常用方法

  • random(),获取0~1之间的随机小数,包含0,但不包含1,小数点后最多保留17位!

    • 语法:Math.random()
    • 返回值:0~1之间的随机小数!
  • round(),对数字进行四舍五入的取整

    • 语法:Math.random()
    • 返回值:四舍五入后的整数
    console.log(Math.random(10.4));
    //打印10
  • 两个方法取整

    • Math.ceil(),向取整
      • 语法:Math.ceil(数字)
      • 返回值:向上取整后的整数
    • Math.floor(),向取整
      • 语法:Math.floor(数字)
      • 返回值:向下取整后的整数
  • pow(),幂运算

    • 语法:Math.pow(底数,指数)
    • 返回值:运算结果
  • sqrt(),算术平方根

    • 语法:Math.sqrt(数)
    • 返回值:运算结果
  • abs(),绝对值

    • 语法:Math.abs(数)
    • 返回值:运算结果
  • max(),最大值

    • 语法:Math.max(数1,数2,数3···)
    • 返回值:运算结果
  • min(),最小值

    • 语法:Math.min(数1,数2,数3···)
    • 返回值:运算结果
  • PI,Π值,这是个属性

    • 语法:Math.PI
    • 返回值:运算结果

算术案例

案例1:获取一个范围内的随机整数

  • 获取0到10之间的随机整数
//获取随机数
Math.random();
//更改至需要范围
let num = Math.random()*10;
//更改为整数
Math.round(num);

//但是,数字0和数字10取到的概率更小
//更改范围,更改取整方法
let num = Math.random()*11;
Math.floor(num);
  • 获取0到20之间的随机整数
let num = Math.random()*21;
Math.floor(num);
  • 总结,获取0~X之间的随机数,Math.random()*(X+1),再向下取整!
  • 获取X~Y之间的随机整数
//借助0~X之间的随机数的方法思想
Math.random()*(X+1);
//从X起步难,那就截去X
//从X~Y差值的整数,比如23~28的差值是5,那就取0~5之间的整数
Math.random()*(Y-X+1);
//最后加上X
let num = X+Math.random()*(Y-X+1);
Math.floor(num);
//完整程序
let X = Number(prompt('第一个数'));
let Y = Number(prompt('第二个数'));
let num = X+Math.random()*(Y-X+1);
document.write(num);
document.write('<br/>');
document.write(Math.floor(num));
  • 封装函数
function randomNum(min,max){
return Math.floor(min+Math.random()*(max-min+1));
}

时间常用方法

时间(Date)也是JS中的一个==数据类型==

  • 创建时间变量,new Date()创建当前终端时间,new Date(代表年的数字,月,日,时,分,秒),注意月
let time = new Date()

方法

获取时间

  • 时间对象.getFullYear(),获取年份
  • 时间对象.getMonth(),获取月份,返回数值!0代表一月,以此类推!
  • 时间对象.getDate(),获取日期
  • 时间对象.getHours(),获取时
  • 时间对象.getMinutes(),获取分
  • 时间对象.getSeconds(),获取秒
  • 时间对象.getDay(),获取星期几,0代表周日!
  • 时间对象.getTime(),获取时间戳,单位为ms毫秒

设置时间

把上述get变成set,没有设置星期,是按日期自动匹配,带有与日期相关的数值参数!

  • 时间对象.setFullYear(数字),获取年份
  • 时间对象.setMonth(数字),获取月份,返回数值!0代表一月,以此类推!
  • 时间对象.setDate(数字),获取日期
  • 时间对象.setHours(数字),获取时
  • 时间对象.setMinutes(数字),获取分
  • 时间对象.setSeconds(数字),获取秒
  • 时间对象.setTime(数字),把数字的时间戳单位为ms毫秒,转化为年月日时分秒,传递给时间对象

案例

封装函数,获取两个时间节点之间的时间差!

在时间轴上,有个``格林威治时间`起点:1970-1-1 0:0:0

//两个时间戳相减,再换算成时间即可
//创建时间变量
let timeBegin = new Date(1996,2,19,6,10,53);
let timeEnd = new Date(2023,4,19,18,9,26);
//转换为时间戳
let chMS1 = timeBegin.getTime();
let chMS2 = timeEnd.getTime();
let num = chMS2-chMS1;
//转换为时间,毫秒换算成秒
let s = Math.ceil(num/1000);
//秒再换算成天
let day = Math.floor(s/(60*60*24));
//在天的基础上,天除不尽的,再想办法换算成小时、以此类推,再换算成分钟、秒
//以秒计算的,余数的单位也是秒,在秒的基础上换算成小时
let hours = Math.floor((s%60*60*24)/(60*60));
//以秒计算的,余数的单位也是秒,余数的单位是秒,在秒的基础上换算成分钟
let minutes = Math.floor((s%60*60)/60);
//以秒计算的,余数的单位也是秒,余数的单位是秒,不用换算
let seconds = s%60;
console.log(day+'天'+hours+'时'+minutes+'分'+seconds+'秒');

let timeBegin = new Date(1996,2,19,6,10,53);
let timeNow = new Date(2023,4,19,18,9,26);
let birth = new Date();
birth.setTime(timeNow.getTime()-timeBegin.getTime());
year = birth.getFullYear() - 1970;
month = birth.getMonth() - 1;
date = birth.getDate() - 1;
hour = birth.getHours();
minutes = birth.getMinutes();
seconds = birth.getSeconds();
console.log('现在是'+year+'岁'+month+'月'+date+'天'+hour+'时'+minutes+'分'+seconds+'秒');
//最终程序
function spaceTime(time1,time2){
let s = Math.ceil((time2.getTime()-time1.getTime())/1000);
let day = Math.floor(s/(60*60*24));
let hours = Math.floor((s%60*60*24)/(60*60));
let minutes = Math.floor((s%60*60)/60);
let seconds = s%60;
ruture {day:day,hours:hours,minutes:minutes,seconds:seconds}
}

let timeBegin = new Date(1996,2,19,6,10,53);
let timeEnd = new Date(2023,4,19,18,9,26);
console.log(spaceTime(timeBegin,timeEnd));