关于JS基本语法

        第一章 JavaScript

        1.1-输入输出语句        

        //输出语句



        // 用于在浏览器中弹出警告框

        alert("未满18岁静止访问")



        // 用于控制台输出信息

        console.log("111")



        // 用于在网页中输出内容

        document.write("三月请对我好一点")



        // 输入语句



        // 在网页中弹出一个输入框

        prompt("请输入姓名")



        // 在网页中弹出一个确认框

        confirm("你真的满18岁了嘛")

        1.2-JS代码的引入方式       

        //(1)行内式:      onlick点击事件
        <button onclick="window.alert('别点了,再点人就傻了')">请点我</button>

        //(2)嵌入式:     
        <script>window.alert("内部样式")</script>

        //(3)外链式:    
        <script src="./03.外链式.js"></script>

        第二章 JS基本语法

        1.0变量

        1.1-变量的声明与赋值

        声明变量:var = 变量名;

        赋值:变量名 = 变量值       

例:

<script>

        //先声明后赋值

        var boy;

        var girl;



        console.log(boy);//undefined(未定义的)

        console.log(girl);




        //为变量赋值

        boy = "jack";

        girl = "lily";



        console.log(boy);//jack

        console.log(girl);//lily





        //声明变量同时赋值

        var myAge = "16";

        var myHeight = "188"



        console.log(myAge);

        console.log(myHeight);

    </script>

        1.2-let声明变量

        声明:let 变量名;

        赋值:变量名 = 变量值;       

 例:

 <script>

        // let是ES6(2015年新推出的ECMAScript语法)新引入的关键字,用来替代var的关键字

        var boyFriend = "1"

        var boyFriend = "2"

        var boyFriend = "3"

        console.log(boyFriend);




        //let不允许在一个代码块里有变量和他取一样的名字,但是允许修改同一个变量值

        let girlFriend = "蔡徐坤";

        girlFriend = "蔡蔡子";

        console.log(girlFriend);



        //一个花括号就是一个代码块

        {let girlFriend = "XXX"

    console.log(girlFriend);}

    </script>

        1.3-const声明变量

        注:const声明变量的同时必须赋值即初始化

例:

 <script>

        //let和var声明的变量可以改变

        //const声明的变量不能改变,即常量



        //错误写法

        // const a = 3

        // a = 4

        // console.log(a);



        // 正确写法

        const a =3

        console.log(a);



        // const b;

        // const必须在声明时就赋值

    </script>

        变量声明区别:

        (1)初始化要求不同

        使用var和let声明变量是可以先不初始化,而使用const声明变量时必须初始化

        即:const声明变量的时候必须赋值,而var和let声明变量可先声明后赋值

        (2)重复声明不同

        使用var和let声明的变量可以多次被修改,其值只与最近一次赋值一致,

        而使用const声明的变量,在整个运行过程中不能修改初值

        即:同一个变量不可多次赋值,const声明的变量一般是常量

        (3)对块级作用域的支持不同

        使用一对花括号括起来的代码成为一个代码块所谓块级作用域,

        就是指变量起作用的范围是当前代码块,离开当前代码块,变量就失效了

        使用var声明的变量支持全局作用域,使用let和const声明的变量支持块级作用域

        即:var生效范围是全代码,而let和const生效范围是当前代码块,即花括号所包括的区域

        2.0数据类型

        2.1-数据类型分为栈内存和堆内存

        其中简单数据类型存储在栈内存中,复杂数据类型存储在堆内存中,复杂数据类型的地址一般存储在栈内存中

        2.1.1-栈内存

        栈内存一般存储各种基本数据类型,如Boolean、String、Undefined、Null、Num...以及对象变量的指针(实际上是对象变量地址,且一个对象变量可以有多个指针,而他们都同时指向存储在堆内存中的对象变量,只是在时间上是先后定义的)

优点:每个变量有固定的存储空间,变量的删减不会产生内存碎片
缺点:变量的调用只能按照固定的顺序,一般是"先进后出,后进先出"的数据结构,我们只能从栈内存块的一端开始访问,我们一般称这一段为"栈顶",另一端为"栈底"

        

        2.1.2-堆内存

        堆内存一般用于存储Object这种变量类型的存储,且堆内存存储的变量在大小方面一般是未知(这也就是为什么null作为Object变量存储在栈内存中的原因)

        优点:堆内存相对于栈内存没有固定的存储空间,一般是用一块足够大的空间来存储变量,对于存储的变量大小不像栈内存那样相对固定
        缺点:栈内存在存储和调用过程中由于变量大小不固定这就使得在这个过程中会有可能产生内存碎片

        2.2-基本数字类型

        其中包括:Boolean布尔型、string字符串类型、number数字型、undefined未定义型、null空(属于Object对象类型)

        2.3-数据类型检测

        typeof()检测括号内值的数据类型 - - console.log(typeof(值))

        isNaN检测非数字类型 - - console.log(isNaN(值))

        如果括号内为数字类型,则会输入false,反之则输出true

        2.4-数据类型转换

//将数据类型转换为布尔型

        //字符串类型和数字类型都会转换为布尔型



        //Boolean()



        //Boolean()

        var a = Boolean("a")

        console.log(Boolean(a));//true



        console.log(Boolean(123));//true



        console.log(Boolean(""));//false



        console.log(Boolean(" "));//true



        console.log(Boolean(0));//false



        console.log(Boolean(NaN));//false



        console.log(Boolean(undefined));//false



        console.log(Boolean(null));//false



        // 将数字转化为字符串类型

        // 使用String()或toString()进行转换

        let num = 1;//数字类型的1

        console.log(String(num));

        let num2 = String(num);//1为字符串类型1

        console.log(num2);

       

        console.log(String(NaN));//字符串类型NaN

        console.log(String(undefined));//字符串类型undefined

        console.log(String(true))//true

        console.log(String(false));//true

       



        //将数据转化为数字型数据

        //Number()用于将数据转化为数字型数据

        console.log(Number(123));//123

        console.log(Number("123"));//123

        console.log(Number(""));//0

        console.log(Number(" "));//0

        console.log(Number("xxx"));//NaN

        console.log(Number(true));//1

        console.log(Number(false));//0

        console.log(Number(undefined));//NaN

        console.log(Number(null));//0

        3.0-运算符 

        3.1-算术运算符

        运算符:+、-、*、/、%、**、++、--

        +:加 5+5=10

        -:减 6-4=2

        *:乘 3*4=12

        /:除 3/2=1.5

        %:取余 5%7=2

        **:幂运算 3**2=9;其中3为底数,2为指数

        ++:自增 其中++可前置可后置

        --:自减 其中--可前置可后置

        3.2-字符串运算(加号遇上运算符,做拼接使用)和隐式转换(当两个数据类型不同时,JS会按照既定规则进行转换)            

例:

    console.log(1+null);//1

    console.log(1+true);//2

    console.log(1+false);//1



    console.log("12"-0);//12

    console.log(undefined+null);//NaN

    console.log(Infinity++);///Infinity



    console.log(1+"1");//11

    console.log(1+"null");//1null

        3.3-赋值运算符        

    //赋值运算:通常将前者与后者运算的结果赋值给前者,能有效减少计算机负担

    let a = 10;
    let b = 20;
  
    //加并运算/字符串拼接并赋值(将前者加上后者并把结果赋值给前者)
    console.log(a+=b);//a=30
    console.log(b+=a);//b=50
    a = "x"
    b = "xx"
    console.log(a+=b)//a=xxx
    console.log(b+=a);//b=xxxxx

    //减并运算(将前者减去后者并把结果赋值给前者)
    a = 10;
    b = 20;
    console.log(a-=b);//a=-10
    console.log(b-=a);//b=30

    //乘并运算(将前者乘后者并把两者相乘的结果赋值给前者)
    a= 10;
    b= 20;
    console.log(a*=b);//a=200
    console.log(b*=a);//b=4000

    //除并运算
    a= 75;
    b= 15;
    console.log(a/=b);//a=5
    console.log(b/=a);//b=3

    //取模并运算
    a= 20;
    b= 3;
    console.log(a%=b);//2
    console.log(b%=a);//1

3.4-比较运算符

将前者和后者进行比较,比较输出的结果时true或false

    //比较运算:将前者与后者比较,比较输出的结果是true或false
    let a = 20;
    let b = 10;

    //不等于!=
    console.log(4!=5);//true
    console.log(4!=4);//false

    //等于==
    console.log(4==4);//true

    //不全等!==
    console.log(4!=="4")//true
    console.log(4!=="5")//true

    //全等===
    console.log(4==="4");//false
    console.log(4===4);//true

    //==和!=在比较不同数据类型时,会将比较的数据转化为相同的数据类型

3.5-逻辑运算符

&&-逻辑与运算符(当&&前后都为true时,则输出结果为true.其他情况都为false.即有假则假,全真为真)

||-逻辑或运算符(当||前后都为false时,则输出结果为false,其他结果为true.即有真则真,全假为假)

<!-- &&逻辑与运算符,一假则假
      ||逻辑或运算符,一真则真 -->
  <script>
    console.log(true&&true);//true
    console.log(false&&true);//false
    console.log(true&&false);//false
    console.log(false&&false);//false

    console.log(3>2&&2>1);//true
    console.log(3<2&&2>1);//false
    console.log(3<2&&2<1);//false

    console.log(true||true);//true
    console.log(false||true);//true
    console.log(true||false);//true
    console.log(false||false);//false

    console.log(3>2||2>1);//true
    console.log(3<2||2>1);//true
    console.log(3<2||2>1);//false

    console.log(!true);//false
    console.log(!(2>1));//false
    console.log(!(2<1));//true

  </script>

3.6-三元运算符

三元运算 : 条件表达式 ? 表达式1 : 表达式2(当表达式结果为true时,则返回表达式1的执行结果,当表达式结果为false时,则返回表达式2的执行结果)

    //条件表达式 ? 表达式1 : 表达式2 
    //如果条件表达式的值为true,则返回表达式1的执行结果
    //如果条件表达式的值为false,则返回表达式2的执行结果

    var age = prompt('请输入你的年龄')
    console.log(age);
    var res = age>=18 ? "你已经是一名优秀的成年人了啦" : "你还是个宝宝"
    document.write(res);

3.7-运算符优先级

小括号>一元运算符>比较运算符>逻辑运算符(逻辑与大于逻辑与)>赋值运算符

 let a = 3 > 5 && 7 > 3 == 4;
    console.log(a);//false

    let b = 3 > 5 || 2 > 7 && 3 === "3"
    console.log(b);//false

4.0-流程控制

 4.1-选择结构

(1)if语句

if(条件表达式){代码段}

    let age = prompt('请输入你的年龄')
    if(age>18){
      document.write(你可以进入本网站)
    }

(2)if...else语句(双分支)

if(条件表达式){代码段1}else{代码段2}

    let age =prompt(请输入你的年龄)
    if (age>18 ) {
      document.write(你可以进入本网站)
    }else {
      document.write(非法访问)
    }

(3)if...else  if...else语句(多分支)

    if (条件表达式1) {
      表达式1的结果
    }else if (表达式2) {
      表达式2的结果
    }else if (表达式3的结果) {
      表达式3的结果
    }else {除去123之后的结果}

*这里还一种和(3)类似的语句,即嵌套语句

if...else{if...else{}}语句

例如下面两者使用不同结构语句写的,但是最终结果相同,这两种语句一般情况下适用与相同情况

但是个人更喜欢用嵌套语句,但是可能会导致结构混乱

if...else if...else多分支语句:

if (grade==100) {
      document.write("拿奖学金")
    }else if(100>grade>=80) {
      document.write('成绩优秀')
    }else if (80>grade>=60) {
      document.write('成绩合格')
    }else if (60>grade>=40) {
      document.write('有补考机会')
    }else if (40>grade>=20) {
      document.write('挂科')
    }else if (20>=grade) {
      document.write('留级')
    }

 if嵌套语句:

var grade = prompt('请输入你的成绩')
    if (grade==100){
      document.write("拿奖学金")
    }else {
      if (grade>=80){
        document.write('成绩优秀')
      }else {
        if (grade>=60){
          document.write('成绩合格')
        }else {
          if (grade>=40){
            document.write('有补考机会')
          }else {
            if (grade>=20){
              document.write('挂科')
            }else {
              document.write('留级')
            }
          }
        }
      }
    }

4.2-循环结构

 (1)for语句

表达式:

for (初始化变量;条件表达式;操作表达式) {循环体}

//例
    // 需求:在控制台输入1-100的整数
    // for (var i = 1;i<=100;i++) {
    //   console.log(i)
    // }

    // 需求:在控制台输出0~100的偶数
    // for (let b = 0;b<=100;b++) {
    //   if (b%2==0) {
    //     console.log(b)
    //   }
    // }

原理图如下: 

(2)while语句

表达式:

while (判断条件) {循环体}

    //  需求:输出1-100的整数
    // var i = 1;
    // while (i<=100) {
    //   console.log(i);
    //   i++
    // }
    
    // var i = confirm('我喜欢你,我们在一起好吗')
    // console.log(i);
    // while (!i) {
    //   document.write('那我明天再问')

    // }
    // document.write('那我们什么时候结婚')

    // 需求打印0-100之间所有偶数的和
    // var sum = 0;
    // var i = 0;
    // while (i<=100) {
    //   sum+=i;
    //   i+=2;
    // }
    // alert(sum)

    //  让用户输入用户名为admin且密码123456,否则重新输入
    // var name = prompt('请输入用户名')
    // var passward = prompt('请输入密码')
    // console.log(name);
    // console.log(passward);
    // while (!(name=='admin' && passward==123456)) {
    //   alert('请重新输入密码')
    //   name = prompt('请输入用户名')
    //   passward = prompt('请输入密码')
    // }
    // alert('登陆成功')

    //或者
    // var name = prompt('请输入用户名')
    // var passward = prompt('请输入密码')
    // console.log(name);
    // console.log(passward);
    // while (name!='admin' || passward!=123456) {
    //   alert('请重新输入密码')
    //   name = prompt('请输入用户名')
    //   passward = prompt('请输入密码')
    // }
    // alert('登陆成功')

原理图如下:

(3)do...while语句

 表达式:

// do {循环体} while (表达式)

      // 需求:在控制台输出1-100的整数
      // var num =1;
      // do {
      //   document.write(num)
      //   num++
      // } while (num<101)

      // 需求:0-100所有偶数的和
      // var num =0;
      // var i =0;
      // do {
      //   i+=2;
      //   num+=i
      // } while (i<100)
      // document.write(num)

      // 或者
      // var num = 0;
      // var i = 0;
      // do {
      //   i++
      //   if (i%2==0) {
      //     num+=i;
      //   }
      // } while (i<=100)
      // document.write(num)

原理图如下:

区别:

执行顺序方面:

do...whlie语句:循环变量初始化->执行循环体(包括循环变量自增)->循环判断

whlie语句: 循环变量初始化->循环判断->执行循环体(包括循环变量自增)

for语句:循环变量初始化->循环判断->执行循环体->循环变量自增

三者在执行顺序方面do...whlie语句和后两者不同

语义方面:

而for语句和whlie语句一般情况下相同,但两者在语义方面有一定区别,for循环强调遍历一个序列中的元素,因为其循环次数一般为已知,而whlie语句强调满足条件输出true结束循环,故其循环次数可能是未知的

应用场景方面:

whlie语句一般用于未知次数循环的情况,且可能出现死循环

for语句一般用于已知次数循环遍历情况,一般不会出现死循环

4.3-跳转语句 

(1)break语句

// 1.break语句
    // for(var i = 1;i<=5;i++) {
    //   if (i==3) {
    //     document.write('吃到了个毒苹果')
    //     break;//跳出了整个循环
    //   }
    //     document.write("第"+i+"个苹果");
    // }

(2)continue语句

// 2.continue语句
    // for (var n = 1;n<=5;n++) {
    //   if (n==3) {
    //     document.write("我吃到了毒苹果")
    //     continue
    //   }
    //   document.write('我吃完了第'+n+'个苹果')
    // }

(3) return语句

// 3.return语句用于返回函数值
    // function fun (a,b) {
    //   var num = a*b;
    //   return num
    // }

break语句会立刻跳出整个循环也就是循环结束

continue语句用来跳出本次循环,循环并不会结束  

return一般用于函数中

第三章 函数

1.0-初识函数

函数的定义

    函数用于封装完成一段特定功能的代码,相当于将一条和多条语句组成的代码块包裹起来,用户在使用时只需要关心参数和返回值,就完成了特定的功能,而不用了解具体的实现

    // [函数格式]
    // fuction name (params) {}
    // fuction指这是一个函数语句
    // name时函数名
    // {}内放函数的具体功能

内置函数

     也叫原生函数,它类似于常量的使用(其内部为固定表达式),即可以不用声明直接调用的函数    

    console.log(isNaN("number"));//true
    console.log(parseInt("15.99"));//15

自定义函数

     提高代码复用性,降低程序维护的难度(人话说就是这串代码如果要多次使用可以先封装起来,下次就可以直接调用)

无参函数

     顾名思义即没有参数的函数

    // 封装函数
    function demo () {
    console.log("我是一个函数")
    }
    // 使用函数
    demo()

有参函数

    function sum (a,b) {
      console.log(a+b);
    }
    sum(1,2)
    sum(88888,99999)

函数的返回值 

    函数的返回值是指函数在调用后获得的一个数据

    在定义函数时,可以为函数指定一个返回值,函数的返回值可以是任意类型的数据

    在JS中使用return语句返回函数值并退出函数

    // {return 表达式}
    function total01 (price,num) {
      all=price*num
      return all
    }
    document.write(total01(9999,12));

 2.0-函数内外的作用域

(1) 全局变量:在函数体外声明的变量或者在函数体内省略var关键字声明的变量

    var a =10
        function demo(){
            console.log(a);
        }
        demo()
        console.log(a);//  a为全局变量,在函数体外也可以被访问

(2) 局部变量:在函数体内利用let关键声明的变量

    function demo1(){
            let b =10
            console.log(b); // 函数内部定义的局部变量b,可以在函数内部被访问

            c = 20; //c是省略var关键字声明的变量,为全局变量
            console.log(c);
        }
    demo1() //10
    // console.log(b);  //b is notdefined 不可以在函数外访问局部变量b    
    console.log(c); //? 可以在函数外访问到全局变量c

(3) 块级变量:在es6标准中,新增的let关键字声明的变量为块级变量,一个花括号{}为一个块级

if(true){
        let sex ='男'  // let声明的变量sex为块级变量
        console.log(sex);//块级变量sex可以在{}内部被访问
}
    // console.log(sex);//块级变量sex不可以在{}外部被访问


    for(let i =0;i<5; i++){
        console.log("循环内部"+1);
}

console.log("循环内部"+1); //i is not defined

总结:

全局作用域:被全局变量所拥有:在{}外声明的变量

局部作用域:被局部变量所拥有:在函数内定义的变量

块级作用域:被块级变量所拥有:在分支语句或者循环大括号中定义的变量

//可以访问到全局变量demo
// 但是demo目前没有赋值,为undefined
    console.log(demo); 
    var demo =7
    let test =10 //全局变量
    function fun(){
        console.log(demo); //7
        console.log(test); //10
    }
    fun()
    console.log(demo); //7
    console.log(test); //10

3.0-函数进阶

// 函数表达式

    // 封装一个函数,在函数内可以求得变量num1与变量num2的和
    var f = function sum (num1,num2) {
      // 在函数内封装了一个打印语句
      // 调用此函数,就会执行打印语句
      document.write(num1+num2)
    }
    // sum(1,2)//3
    f(1,2)//3

    function sum1 (num1,num2) {
      // 在函数内求得一个和
      // 并将求得的和返回出去
      // 让函数外都可以拿到
      return num1+num2
    }
    document.write(sum1(1,2))

    // 匿名函数
    var fun = function (num1,num2) {
      console.log(num1+num2)
    }
    fun(2,4)

    var fun1 = function (num1,num2) {
      return num1+num2
    }
    console.log(fun1(3,5))

    // 箭头函数
    // 删除function关键字
    // 在参数和函数体中间放上"=>"
    var fn = (num1,num2) => {
      console.log(num1+num2);
    }
    fn(1,5)
    // 当函数只有一句话时,可以省略大括号
    var fn2 = (num1,num2) => console.log(num1+num2);
    fn1(1,5)
    // 当函数只有一句代码,并且函数的执行结果就是函数返回值
    // 可以省略函数的大括号和return关键字
    var fn3 = (num1,num2) => num1+num2 
    console.log(fn3(1,5));
    // 当参数只有一个时,可以省略函数外部小括号
    var fn4 = num1 => num1*2
    console.log(fn4(2))

 总结:

当进行函数封装时可以省略function关键字改在"()"后使用"=>";

当函数的执行代码只有一句话时可以省略掉"{}";

当参数只有一个时可以省略"()";

4.0-回调函数 

回调函数:一个函数作为参数传入另外一个函数中,则称该函数为回调函数

// 函数fn作为参数传递给参数cal
    // 然后在函数cal中调用fn
    // 此时fn就是回调函数
    function cal (num1,num2,fn) {
      console.log(fn(num1,num2))
    }

    console.log (cal(90,17,function(a,b) {
      return  a%b
    }))

5.0-定时器函数 

// [setInterval()]
    // Interval:间隔,间隙
    // "时间间隔"一到,代码就会在多少毫秒执行一次(重复执行)

    // setInterval(() => {}, interval);

    setInterval(() => {
    document.write("抽瑞克五代,享受百味人生")
    }, 1000);

    // [setTimeout()]
    // 用来指某个函数或某个代码多少毫秒后执行(执行一次)

    // setTimeout(() => {}, timeout);

    // 定时器函数属于异步代码
    // setTimeout指定的代码,必须等同步代码执行完毕后再执行

    document.write(1)
    setTimeout(() => {
      document.write(2)
    }, 1000);
    document.write(3)

    console.log("A")
    setTimeout(() => {
      console.log("B");
    }, 20);
    console.log("C");
    setTimeout(() => {
      console.log("D");
    }, 0);    
    // 打印结果:ACDB

 这里的setTimeout属于异步代码,console.log()属于同步代码,因为程序执行时会优先执行同步代码再执行异步代码所以顺序如上所示

6.0-函数嵌套和作用链 

// 函数嵌套

    var i=10

    function fn1 () {
      var i=20
      function fn2 () {
       function fn3 () {
        console.log(i)
       }
       fn3 ()
      }
      fn2 ()
    }
    fn1 ()

    // 变量访问规则:就近原则
    // 当在一个作用域中访问变量时,首先看当前作用域有没有声明
    // 如果有则访问,没有则往上级作用域查找
    // 直到顶端作用域没有时,程序报错

 7.0-闭包函数

闭包 [close] :闭包是一种代码形式,内部函数访问外部函数的局部变量



    // 例:js函数A中有一个函数B,函数B访问了函数A里面定义的局部变量,此时就产生了闭包
    //    变量所在函数就是闭包函数,在这里,函数A就是闭包函数

    // 外部函数
    function outer () {
      // 外部函数定义的局部变量
      let n=10
      // 内部函数
      function inner () {
        // 内部函数要访问外部函数定义的局部变量
        console.log(n);
      }
      inner()
    }
    outer()
    let n=10

    // 解决变量污染问题,让变量被函数保护起来
    // let count=0
    // setInterval(() => {
    //   console.log(count++)
    // }, 1000);
    // 在这段代码中,count是一个很常用的变量名
    // 为了避免和其他位置的代码起冲突,可以使用一个函数将上述代码包裹起来

    function fn () {
      let count=0
      setInterval(() => {
        console.log(count++);
      }, 1000);
    }
    // 内部函数setInterval访问外部函数fn定义的局部变量

    function fn () {
      let count=0
      function add () {
        console.log(count++);
      }
      setInterval(add,count)
    }
    // 内部函数add访问外部函数fn定义的局部变量

 8.0-函数的递归

// 递归函数是一个函数间接或直接地调用自身

        function func() {
            console.log(1);
            func()
        }

        // 需求: 设置一个函数getSum()
        // 如果传入进去的是n
        // return sum = n + (n-1) + (n-2) + .. + 1

        // n = 5
        // sum = 5+4+3+2+1 =15
        
        // 循环写法1
        function getSum(n) {
            var sum =0
            for (let i = 0; i <= n; i++) {
                sum +=i
                
            }
            return sum
        }
        console.log(getSum(5));

        // 循环写法2
        function getSum(n) {
           if (n==1) {
            return 1
           }
            return n * getSum(n-1);
        }
        var n = prompt('输入任意n');
        n = parseInt(n);
        if (isNaN(n)) {
            console.log('输入有误');
        } else {
            console.log(n + '的阶层为:' + getSum(n));
        }

        // 需求:设置一个函数求出输入值为n到1的累加和
        // 1.for语句循环
        function fn (n) {
          var mulSun = 1;
          for ( var i=1;i<=n;i++) {
            mulSun +=i;
          }
          return mulSun
        }

        // 2.if语句递归
        
        function fn1 (n) {
        // 设置终点
          if(n===1) {
            return 1
          }
        // 未到终点
          return n+fn1(n-1)
        }
        fn1(4)

        // 斐波那契数列
        // 循环写法:
        function fn2 (n) {
          var arr=[1,1]
          for (var i =2;i<n;i++) {
            arr[i]=arr[i-1]+arr[i-2]
            console.log(arr)
          }
        }
        fn2(10)

        // 递归写法:
        function fn3 (n) {
          if (n===1) {
            return 1
          }
          return fn3(n-1)+fn3(n-2)
        }
        fn3(n) = fn3(n-1) + fn3(n-2)
        fn3(n) = fn3(n-2)+fn3(n-3) + fn3(n-2)
        fn3(n) = fn3(n-3)+fn3(n-4) + fn3(n-2) + fn3(n-3)
        fn3(n) = fn3(n-4)+fn3(n-5) + fn3(n-3) + fn3(n-2) + fn3(n-1)

 总结:递归函数写法就是用if语句判断是否到达递归终止条件,然后决定是否继续调用函数的一种技巧

 实例:简易网页计算器

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 一下是HTML部分 -->
  <p>整数1: <input type="text" id="num1"></p>
  <p>整数2: <input type="text" id="num2"></p>
  <p>
    <!-- onclick按钮点击事件 -->
    <input type="button" value="加" onclick="cal(add)">
    <input type="button" value="减" onclick="cal(sub)">
    <input type="button" value="乘" onclick="cal(mul)">
    <input type="button" value="除" onclick="cal(div)">
  </p>
  <p>结果: <input type="text" id="result"></p>

  <!-- 以下是js代码 -->
  <script>
    function add(num1,num2) {
      return num1+num2
    }
    function sub(num1,num2) {
      return num1-num2
    }
    function mul(num1,num2) {
      return num1*num2
    }
    function div(num1,num2) {
      if (num2===0) {
        document.write("除数不能为零!")
        return""
      }
      return num1/num2
    }
    // 在cal函数中需要传入一个回调函数
    function cal(func) {
      // 通过ID"num1"得到HTML中名字叫"num1"的输入框的值
      // 在js中获取HTML中输入的num1的值
      var num1=parseInt(document.getElementById("num1").value)
      var num2=parseInt(document.getElementById("num2").value)
      var result=document.getElementById("result")
      result.value=func(num1,num2)
    }    
  </script>
</body>
</html>

第四章 数组

1.0-初始数组 

    // 数组是一种复杂的数据类型
    // 用于将一组数据集合在一起
    // 通过一个变量可以访问这一组数据

    // 数组之间用逗号分隔

    // 数组中的'索引/下标',要从零开始计算

    // 声明数组
    let class02 = ['tom','lili','lisa']
    // 打印数组
    document.write(class02)
    // 打印数组长度
    document.write(class02.length)//3
    //打印下表为X的元素
    console.log(class02[0])//"tom"
    console.log(class02[1])//'lily'

    //数组可以是任意类型的元素,例如字符串,数字,数组
    let arr1 = [1,2,3,4,5,6]
    let arr2 = ['string',NaN,null,undefined,arr1]
    console.log(arr2);

 2.0-数组的创建

创建数组方法:

1.var 数组名 = new Array(数组长度) //如果括号内未指定数组长度则打印结果为Array(0)

2.var 数组名 = [元素1,元素2,元素3,...]

// 1.以new Array()方式创建数组
  // var 数组名 = new Array([数组长度])
 var arr = new Array();
 console.log(arr); //Array(0)
 var arr = new Array(5);
 console.log(arr); // [empty*5]
 arr = new Array("tom",'tony','bob')
 console.log(arr); // ["tom",'tony','bob']

 // 2. 使用数组字面量创建数组
 // var 数组名 = [元素1,元素2,元素3,...]
 var mood = ['sad',,,,,,'happy']
 console.log(mood.length); //8
console.log(mood[7]); //happy
console.log(mood[6]); // undefined
 console.log(mood[0]); // 'sad'

3.0-数组的基本操作

 在JS中数组的基本操作除了增、删、改、查还有在特定位置添加元素、遍历数组等

    // 1.获取元素长度
    // 数组名.length

    // 2.修改数组长度
    // 数组名.length = number
    var arr = [0,1,2,3]
    console.log(arr.length); // 4
    arr.length = 5
    console.log(arr); // [0,1,2,3,empty]
    arr.length = 3
    console.log(arr); // [0,1,2]

    // 3.添加数组元素
    arr[4] = 3
    console.log(arr); // [0,1,2,empty,3]


    // 修改数组元素
    arr[0] = 1
    console.log(arr); // [1,1,2,empty,3]

    // 5.删除数组元素
    delete arr[3] 
    console.log(arr); // [1,empty,2,empty,3]

    // 6.遍历数组
    let arr1 = [10,20,30,40,50,60]
    var sum =0;
    for (var i=0; i<arr.length; i++){
        sum += arr[i]
        // arr[0] 10     sum+10=0+10=10
        // arr[1] 20     sum+20=10+20=30
        // arr[2] 30     sum+30=30+30=60
        // arr[3] 40
        // arr[4] 50
        // arr[5] 60
        // arr[6]
    }
    console.log(sum); // 210

    // 7.新增数组元素
    // push在数组后添加元素
    let arr3 = [1,2,3,4]
    arr3.push(5,6)
    console.log(arr3); //[1,2,3,4,5,6]

    // unshift在数组前添加元素
    arr3.unshift(-2,-1,0)
    console.log(arr3); //[-2,-1,0,1,2,3,4,5,6]

下面是数组基本操作的应用实例:


    // 需求:打印当前数组最大值和最小值
    let score = [97,65,43,99,60,58,36,72,85,77]
    let max =0;
    let min =100;
    for(var j=0;j<score.length;j++){
        if(score[j]>max){
            max=score[j]
        }
        if(score[j]<min){
            min =score[j]

        }
    }
    console.log(max);
    console.log(min);


    // 需求:把数组中大于10的元素筛选出来
    var arr4 =[4,5,8,9,11,30,39,20,19]
    var arr5 = []
    for(let i=0;i<arr4.length;i++){
        console.log(arr4[i]);
        if(arr4[i]>10){
          arr5.push(arr4[i])
        } 
    }
    console.log(arr5);
      // 需求:数组去0,形成一个新数组
      var arr6 = []
    for(let i=0;i<arr6.length;i++){
        if(arr4[i]!=0){
            arr6.push(arr4[i])
        }
    }
    console.log(arr6);

    // 需求: 将数组['一','二','三','四','五']反转
    // 反转后的数组为[]
    var arr7=[1,2,3,4,5]
    var arr8 = []
    // for(let i=0;i<arr7.length;i++){
    //    arr8.unshift(arr7[i])
    // }
    // console.log(arr8);

      for(let i=0;i<arr7.length;i++){
        for (let b=4;b>=0;b--){
            arr8.push(arr7[b])
        }
       
    }
        console.log(arr8);

补充:

删除数组元素

arraypop();删除数组最后一个元素

 

arrayshift();删除数组开头元素,并使其他元素索引减一


array.slice(start, [end]); 以数组的形式返回数组的一部分,注意不包括 end 对应的元素,如果省略 end 将复制 start 之后的所有元素

 

array.concat(item1, item2, . . . ,itemN); 将多个数组(也可以是字符串,或者是数组和字符串的混合)连接为一个数组,返回连接好的新的数组


array.slice(0); 返回数组的复制的数组,注意是一个新的数组,不是指向

 

array.concat(); 返回数组的复制数组,注意是一个新的数组,不是指向


array.reverse(); 反转元素(最前的排到最后、最后的排到最前),返回数组地址

 

array.sort(); 对数组元素排序,返回数组地址


array.join(separator); 返回字符串,这个字符串将数组的每一个元素值连接在一起,中间用 separator 隔开

4.0-二维数组(多维数组)

多维数组:当一个数组充当另外一个数组的元素时,这时我们称另外一个数组叫做多维数组

二维数组调用方法:arr[][]

其实可以把下面二维数组看作一个坐标系,数组后两个括号内对应的其实就是元素的坐标(索引)

如下为一个二维数组及遍历方法:

var arr=[
      [80,90,100],
      [78,37,98],
      [76,65,86]
    ];

// 调用方法:arr[][]

    for (var num=0;num<arr.length;num++) {
      for (var num1=0;num1<arr[num].length;num1++) {
        console.log(arr[num][num1]);
      }
    }

5.0-数组的迭代方法 

5.1-map数组遍历方法

注意:

(1).回调函数的执行次数等于数组长度
(2).map函数返回的新数组长度等于原数组长度
(3).回调函数中一定要return,返回的是当前遍历的元素值,如果不return,新数组的每一个元素都是undefined
    let arr =[23,34,45,43,233]
    let num=[]
    // 需求:将arr数组每个元素+1,生成一个新数组
    for(var i=0; i<arr.length; i++){
        num[i] =arr[i]+1       
      }
        console.log(num);

        // map:利用某种规则映射得到一个新数组
        // map()中需要传入一个回调函数作为参数
        // 在回调函数中定义需要map数组遍历方法做什么事情
        // arr.map((value,index) => {return 新元素})
        let res =arr.map(function(value,index){
            // 回调函数中一定要return
            return value + 1 //让每个元素+1
        })
        console.log(res);

        // 需求:数组res2在arr的基础上,每个元素+2
        let res1 =arr.map(function(value,index){
            return value + 2
        })
        console.log(res1);

5.2-filter数组过滤器

注意:

(1).回调函数的执行次数等于数组长度
(2).filter函数返回的新数组长度不等于原数组长度
(3).回调函数一定要return一个布尔值,如果return的值为true,当前遍历的元素就会添加到新数组中,如果return的值为false,则不会添加到新数组中
    let arr = [-10,0,23,42,24]
    // 需求: 找出数组中大于10的所有元素,形成新数组res
    let res =[]
    for(let i=0;i<arr.length;i++){
        if(arr[i]>10){
            res.push(arr[i])
        }
    }
    console.log(res);

    // filter
    // 创建一个新数组,新数组中的元素都是符合指定条件过滤后的元素。

    // 特点:
    // (1)filter会遍历数组中的每一项,找到符合指定条件的元素返回。返回一个新数组。
    // (2)filter对空数组不会进行检测,不会改变原始数组。

    // filter:用于筛选数组中满足条件的元素,返回筛选后的新数组
    // arr.filter(value,index) =>{筛选条件}
    // filter形成的新数组的长度 ! ==  原数组长度
    // 回调函数执行次数 == 数组长度

    let res1 =arr.filter((value,index) => {
       return value > 10          
    })
    console.log(res1);

    // 需求: 数组res2在arr的基础上,每个元素*2
    let rse2 =arr.filter((value,index) => {
        return value*2
    })
    console.log(rse2);

5.3-forEach数组遍历方法

注意:

(1).回调函数的执行次数等于数组长度
(2).forEach函数没有返回值
(3).回调函数不需要return,就算手动return,也不会结束循环
    let arr = [1,2,3,4,5]

    // 需求:数组求和
    // let sum=0;
    // for (var i =0;i<arr.length;i++) {
    //   sum+=arr[i]
    // }
    // document.write(sum)

    let sum1=0
    arr.forEach(value => sum1+=value)
    document.write(sum1)

    // forEach也是用于遍历数组
    // 数组.forEach(function(value,index,arr) {算法})

    // 回调函数的执行次数=原数组长度
    // forEach没有返回值,不需要return

5.4-some方法

注意:

(1).回调函数的执行次数不等于数组长度
(2).some函数的返回值是一个布尔值
(3).回调函数返回布尔类型值用于结束遍历,如果return的值为true,则遍历结束,且some函数的返回值为true,如果return的值为false,则继续遍历,如果最后一个元素返回值为flase,则some函数的返回值为false

    // some用于判断数组元素是否符合条件
    
    //判断数组中有没有负数,有则返回true。
    // 假设这个数组中没有负数,返回false
    // let arr = [1,2,3,4,5]
    // var jg = false
    // arr.map((value,index) => {
    //   if (value<0) {
    //     jg=true
    //   }
    // })
    // document.write(jg)

    // 通过forEach方法遍历并判断
    // let res = arr.some((item,index) => {
    //   return item<0
    // })
    // console.log(res)

    // 回调函数的执行次数!==原数组长度
    // some函数返回一个布尔值

    //只要有一个元素符合函数体的判断条件,就返回true
    // 如果没有一个元素符合函数体的判断条件,则返回false

    // 需求:判断该数组中年份是否存在闰年
    let year =[2001,2002,2003,20051]
    //判断year数组中是否存在闰年,存在则返回true,不存在则返回false
    let res1 = year.some((item,index) => {return item%4==0})
    document.write(res1)

5.5-every方法

 注意:

(1).回调函数的执行次数不等于数组长度
(2).every函数的返回值是一个布尔值
(3).回调函数返回布尔类型值用于结束遍历,如果return的值为true,则遍历继续,且every函数的返回值为true,如果return的值为false,则继续结束,且every函数的返回值为false

    // some和every遍历数组后返回的都是一个布尔类型的值

    // 如果有元素符合条件,some的值为true
    // 当全部元素满足条件,every的值为true

    // 需求:判断某数是否全部为正数,全部为正数则返回true,反之则返回flase
    let arr=[-1,2,3,4,5]

    for (var i=0;i<arr.length;i++) {
      var res = true;
      if (arr[i]<0) {
        res = false;
        break
      }
    }
    document.write(res)

    // let res = arr.every((item) => {item>0})
    // document.write(res)

    // every语句:数组名.every = ((item,index) => {条件表达式})

*:some方法和every方法输出值可以理解为或和与 ,即一真则真和一假全假

5.6-findindex方法

 注意:

(1).如果return的值为true,则遍历结束,findIndex方法返回值为当前的index值;如果return的值为false,则遍历继续,如果数组全部遍历完还是没有返回true,则findIndex方法返回值为-1

    // findindex用于返回第一个符合函数的下标

    var arr = [9,4,0,-1,3,-2,7]

    // 需求:找到第一个非正数的下标
    // for (var i=0;i<arr.length;i++) {
    //   var s=0;
    //   if (arr[i]<0) {
    //     s = i;
    //     break
    //   }
    // }
    // document.write(s)


    let res = arr.findIndex (item => {return item<0})
    document.write(res)

    // findindex语句:数组名.findindex = ((item,index) => {条件表达式})
    // 当函数中有满足条件元素时则返回该元素下标,没有满足条件或者无返回值则输出-1

5.7-reduce方法

 注意:

(1).最好给item一个初始值,避免空数组报错
      var arr = [97,66,48,31,82]

      // 求数组各项的平均值
      // var sum =0
      // for(var i=0;i<arr.length;i++){
      //     sum +=arr[i]
      //     var avg =sum/arr.length
      // }
      // console.log(sum);
      // console.log(avg);

      // let sum = arr.reduce((item,item2)=>{},默认值)如果没有规定默认值则默认为数组第一个元素
      // item为初始值,默认为数组的第一个元素
      // item2为数组的每一个元素,默认为数组第二个元素
      let avg =arr.reduce(function(item,item1){
        // 将return值赋值给item
          return item +=item1
      })
      console.log(avg/arr.length);
      console.log(avg);

第五章 对象

1.0-介绍对象(没错,就是你想得那个对象/dog)

    // 1. 对象{object}是什么:对象是一种复杂数据类型
    // {复杂数据类型的内容存储在堆内存中,地址存储在栈内存中}
    // 2. 对象作用:以键值对的形式存储多个数据

    // 需求:存储一个人的信息(姓名、年龄、性别)
    let name = "张三";
    let age = 38;
    let sex = "男";
    // 好处:阅读性高 弊端:冗余

    // 2. 数组
    // 弊端:阅读性不高 好处:一个变量存储多个数据
    let peopel = ["张三",38,"男"]

    // 3. 对象
    let obj = {
      name : "张三",
      age : 38,
      sex : "男",
      gfs : ["小花","小美","小艾"],
      sayHi : function () {
        console.log("你好,世界")
      }
    } 

    // 3.1 对象查询
    console.log(obj);
    console.log(obj.name);
    console.log(obj.age);
    console.log(obj.sex);
    console.log(obj.gfs);
    console.log(obj.sayHi);

    // 3.2 对象新增
    obj.bf="李四"
    console.log(obj);

    // 3.3 对象修改
    obj.bf="王五"
    console.log(obj);
    // 对于变量修改还是新增,则看原对象里有没有该属性值,如果没有则为新增,有则为修改

    // 3.4 对象删除
    delete obj.bf
    console.log(obj);

 2.0-Math数学对象

    内置对象:由JS作者提前编写好了,里面存储了一些属性和方法,直接使用即可

    如:Math数学对象,Date日期对象

(1).圆周率对象:Math.PI

    console.log(Math.PI)
    const c = 2*Math.PI
    console.log(c);//6.28

(2).绝对值:Math.abs()

    console.log(Math.abs(-3.5));//3.5

(3).最大值/最小值:Math.max()/Math.min()

    console.log(Math.max(1,2,3,4,2,9,0));//9
    console.log(Math.min(1,2,3,4,2,9,0));//0

(4).幂运算Math.pow(x,y),表x的y次方

console.log(Math.pow(2,10));//1024

(5).四舍五入Math.round()

    console.log(Math.round(-4.9))//5
    console.log(Math.round(9.1))//9
    console.log(Math.round(3.2))//3
    console.log(Math.round(5.8))//6

(6).向上取整Math.ceil()

注意:这里的往上取不是绝对值的往上而是数轴的往上,(7同理)

    console.log(Math.ceil(4.2));//5
    console.log(Math.ceil(-8.7));//-8
    console.log(Math.ceil(-1.2));//-1
    console.log(Math.ceil(0.3));//0

(7).向下取整Mth.floor()

    console.log(Math.floor(-6.3));
    console.log(Math.floor(-0.9));
    console.log(Math.floor(3.4));
    console.log(Math.floor(6.7));

(8).生成一个0-1(0<=x<1)的随机小数

console.log(Math.random());

实例如下:

    // 生成一个0-100的随机整数

    console.log(Math.round(100*Math.random()));

    alert("你的幸运数字是"+Math.round(100*Math.random()));

实际上上面写法存在亿点问题,由于Math.random()只能取到(0<=x<100)之间的数字所以扩大一百倍后该语句还是取不到100

故,我们这样写

    // 取0-N之间的随机整数(这里的N为一个10的n次方)
    console.log(Math.floor(Math.random()*(N+1)));
    // 写法二:
    console.log(Math.ceil(Math.random()*10));

3.0-Date对象

时间戳:从1960年1月1日到现在的毫秒数

    //时间戳:从1970年1月1日0时0分0秒到现在的毫秒数
    // 以下三种都会得到时间戳
    console.log(Date.now());
    console.log(+new Date());
    console.log(new Date().getTime());

    // 年份
    console.log(new Date().getFullYear());

    // 月份
    console.log(new Date().getMonth());
    
    // 日期
    console.log(new Date().getDate());

    // 星期
    console.log(new Date().getDay());

    // 小时
    console.log(new Date().getHours());

    // 分钟
    console.log(new Date().getMinutes());

4.0-Array对象

    var course=["java","web"]
    // push()在数组末尾添加一个元素
    course.push("javaScript")
    console.log(course)// ["java","web","javaScript"]

    // unshift()在数组开头添加一个元素
    course.unshift("计算机基础")
    console.log(course);// ["计算机基础","java","web","javScript"]

    // pop()删除数组中最后一个元素
    course.pop()
    console.log(course);// ["计算机基础","java","web"]

    // shift()删除数组中第一个元素
    course.shift()// ["java","web"]
    console.log(course);

    var arr=[1,2,3,4,5,6,7]

    // splice(start,deleCount)从指定位置往后删除指定个元素
    arr.splice(3,2)
    console.log(arr);// [1,2,3,6,7]

    // splice(start,deleCount,item1,item2,...)从指定位置往后添加元素
    arr.splice(3,0,4,5,999,777)
    console.log(arr);

    // reverse()颠倒数组中元素索引
    var arr1=[1,2,3,4,5,6,7,8,9,0]
    arr1.reverse()
    console.log(arr1);// [0,9,8,7,6,5,4,3,2,1]
    
    // sort排序

    // 升序排序
    var arr2=[13,67,23,45,95,23,11]
    arr2.sort(function (a,b) {return a-b})
    console.log(arr2);

    // 降序排序
    arr2.sort(function (a,b) {return b-a})
    console.log(arr2);


    // 获取元素索引方法
    // indexOf(element):返回指定元素在数组中第一次出现的索引(即从开头查找到第一个指定元素的索引)
    // lastIndexOf(element):返回指定元素在数组中最后一次出现的索引(即从末尾开始查找到第一个指定元素的索引)
    var color=["pink","red","green","white","yellow","red"]
    console.log(color.indexOf("red"));//1
    console.log(color.indexOf("pink"));//0
    console.log(color.lastIndexOf("red"));//5

    // 将元素转化为字符串
    // toString()将数组转化为字符串,用逗号分隔开每一个数组元素
    // join()将数组转化为字符串,默认用逗号分隔开,括号内可指定分隔符号
    console.log(color);// ['pink','red','green','white','yellow','red']
    console.log(color.toString());// pink,red,green,white,yellow,red

    
    // 数组类型检测
    var abj={
      name:'张三'
    }
    console.log(Array.isArray(abj));//false
    console.log(Array.isArray(arr));//true

5.0-String对象

        

    // 创建字符串对象
    var str=new String("apple")
    console.log(str);// {'apple'}
    
    // 访问字符串长度
    console.log(str.leng);//5
    // 数据类型检测
    console.log(typeof(str));// object
    var str1="banana"
    console.log(typeof(str1));// string

    // 根据字符串返回索引
    // indexOf() 返回在字符串中指定字符首次出现的索引,没有则返回-1
    // laseIndexOf() 返回在字符串中指定字符最后一次川线的索引,没有则返回-1
    var str="helloworld"
    console.log(str.indexOf('o'));//4
    console.log(str.lastIndexOf('o'));//6

    // 根据索引返回字符串
    // charAt()
    console.log(str.charAt(7));//'r'

    // 字符串的截取
    // slice(start)
    console.log(str.slice(5))//"world"
    // slice(start,end) 从start下标截取到end下标
    console.log(str.slice(1,2));//"el"

    // 字符串连接
    // concat()
    var str1 = "hello"
    var str2 = ",world"
    console.log(str1.concat(str2)); //hello,world

    // 大小写转换
    // toUpperCase() 转化为大写
    // tolowerCase() 转化为小写
    console.log(str1.toUpperCase()); //HELLO
    console.log("HELLO".toLowerCase()); //hello

    // 替换
    // replace(str1,str2) 将str2替换str1
    console.log(str); //helloworld
    console.log(str.replace("world","JS")); //helloJS

    // 字符串分隔
    // split(分隔符)
    console.log(str.split("")); //['h','e','','','o','w','o','r','l','d']
    console.log(str.split());//['helloworld']
    console.log(str.split("o"));//['hell','w','rld']

第六章 DOM

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值