JS的ECMAScript2

161 阅读26分钟

46、数组遍历的常用方法

①. forEach
 * 语法:数组.forEach(function(item, index, origin) {})
 *       * item:数组的每一项
 *       * index:数组的每一项 对应的下标
 *       * origin:原始数组 (了解即可,一般没人使用)
 * 作用:遍历数组
 * 返回值:该方法永远没有返回值(undefined)
 ```js
     var arr = [100, 200, 300, 400, 500, 600]
     console.log('原始的数组',arr)
     
     arr.forEach(function (item, index, origin) {
         console.log(item, index)
         console.log(origin)
     })
 ```
②.map
 * 语法:数组.map(function (item, index, origin) {})  三个参数的意义与forEach 相同
 * 作用:映射数组
 * 返回值:返回一个和原数组长度相同的数组,但是内部数据可以经过我们的映射加工
 * 映射加工:就是在函数内 以return的形式书写
  ```js
     var arr = [100, 200, 300, 400, 500, 600]
     console.log('原始的数组',arr)
     
     var newArr = arr.map(function (item, index, origin) {
         // console.log(item, index, origin)
         return item * 2
     })
     var newArr = arr.map(function (item) {
         return item * 2
     })
     console.log('映射出来的数组:' ,newArr)
 ```
有一道面试题:数组常用的遍历方法中,有一个forEach和一个map,这两个方法有什么区别?
 * 1.forEach的作用是用来遍历数组,而map的作用是用来映射数组
 * 2.forEach 没有返回值,而 map 是可以有返回值的
!③.filter
 * 语法:数组.filter(function (item, index, origin) {})
 * 作用:过滤数组
 * 返回值:返回一个新数组,内部存储的是原始数组过滤出来的部分内容
 * 过滤条件:过滤条件以return 的形式书写
  ```js
     var arr = [100, 200, 300, 400, 500, 600]
     console.log('原始的数组',arr)
     
     var newArr = arr.filter(function (item, index, origin) {
         return item > 350 //过滤数组的内容,只留下item>350的成员
     })
     console.log(newArr) //[400, 500, 600]
 ```
!④.find
 * 语法:数组.find(function (item, index, origin) {})
 * 作用:在数组内查找满足条件的第一项
 * 返回值:找到的数据, 如果没找到返回的是undefined
 * 查找条件以return的形式书写
  ```js
     var arr = [100, 200, 300, 400, 500, 600]
     console.log('原始的数组',arr)
     
     var newArr = arr.find(function (item, index, origin) {
         return item > 350 //在数组中查找第一个符合条件的成员
     })
     console.log(newArr) //400
     
     var newArr = arr.find(function (item, index, origin) {
         return item > 3500 //在数组中查找第一个符合条件的成员
     })
     console.log(newArr) //undefined
 ```
⑤.findIndex
 * 语法:数组.findIndex(function (item, index, origin) {})
 * 作用:在数组内查找满足条件的第一项的下标
 * 返回值:找到的数据的下标,如果没找到返回的是-1
 * 查找条件以return的形式书写
  ```js
     var arr = [100, 200, 300, 400, 500, 600]
     console.log('原始的数组',arr)
     
     var newArr = arr.findIndex(function(item, index, origin) {
         return item > 350 //找到符合条件的第一项的下标
     })
     console.log(newArr) // 3
     
     var newArr = arr.findIndex(function(item, index, origin) {
         return item > 3500 //找到符合条件的第一项的下标
     })
     console.log(newArr) // -1
 ```
⑥.some
 * 语法:数组.some(function (item, index, origin) {})
 * 作用:判断数组内是否有一个满足条件
 * 返回值:一个布尔值 true/false
 * 判断条件以return的形式书写
  ```js
     var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
     console.log('原始数组:', arr)
     
     var bol = arr.some(function (item, index, origin) {
         return item % 2 === 0 //判断数组内是否有一 个满足条 件的
     })
     console.log(bol) //true
     
     var bol = arr.some(function (item, index, origin) {
         return item > 500 //判断数组内是否有一 个满足条 件的
     })
     console.log(bol) //false
 ```
⑦.every
 * 语法:数组.every(function (item, index, origin) {})
 * 作用:判断数组内是否全部满足条件
 * 返回值:一个布尔值 true/false
 * 判断条件以return的形式书写
  ```js
     var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
     console.log('原始数组:', arr)
     
     var bol = arr.every(function (item, index, origin) {
         return item % 2 === 0 //判断数组内是否全都 满足条件
     })
     console.log(bol) //false
     
     var bol = arr.every(function (item, index, origin) {
         return item > 0 //判断数组内是否全都 满足条件
     })
     console.log(bol) //true
 ```
!⑧.reduce
 * 语法:数组.reduce(function (prev, item, index, origin) {}, init)
 *     * prev: 表示初始值或者上一次的运算结果
 *     * item:数组的每一项 的值
 *     * index:表示数组的每一项 对应的下标(索引)
 *     * origin:原始数组
 * 作用:用来实现叠加效果
 * 返回值:最终叠加效果
 * 注意:
 *     + 叠加条件以return的形式书写
 *     + prev 第一次的值 如果你传递了init, 就是init 的值,如果没有传递init, 那么就是数组[0]的值;(init不写,  prev从下标0开始  item直接从下标1 开始)(只要传递了init,不管init是几,item都是从下标0开始)
 *     + 如果传递了init, 循环执行 数组.length 次,如果没有传递init,循环执行 数组.length - 1 次
  ```js
     var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
     console.log('原始数组:', arr)
     
     var str = arr.reduce(function (prev, item, index, origin) {
         return prev + item
     }, 0)
     console.log(str) //45
  ```
     /**
     * 在第 1 轮执行的时候
     *        prev === 0 ((因为我使用reduce 方法的时候传递了第二个参数,默认给的值为0)
     *        item === 1 它的值就是数组第一项的值
     *          在第一轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第二轮循环开始的时候的prev
     * 
     * 在第 2 轮执行的时候
     *        prev === 1 (因为上一轮执行了prev + item 得到的值为1)
     *        item === 2 因为是第2轮循环, 所以他的值就是 数组第2个元素的值
     *          在第2轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第3轮循环开始的时候的prev
     * 
     * 在第 3 轮执行的时候
     *        prev === 3 (因为上一轮执行了prev + item 得到的值为3)
     *        item === 3 因为是第3轮循环, 所以他的值就是 数组第3个元素的值
     *          在第3轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第4轮循环开始的时候的prev
     * 
     * 在第 4 轮执行的时候
     *        prev === 6 (因为上一轮执行了prev + item 得到的值为6)
     *        item === 4 因为是第轮循环, 所以他的值就是 数组第个元素的值
     *          在第4轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第5轮循环开始的时候的prev
     * ...
     * 
     * 因为后续数组没有元素了,所以循环到此结束,然后将 最后一轮 prev 的值return 出去,外部可以使用一个变量 去接收
     * 
     * */ 
     ```js
         var str = arr.reduce(function (prev, item, index, origin) {
             return prev + item
         }, '')
         console.log(str) //字符串123456789
     ```
    /**
     * 在第 1 轮执行的时候
     *        prev === '' ((因为我使用reduce 方法的时候传递了第二个参数,默认给的值为0)
     *        item === 1 它的值就是数组第一项的值
     *          在第一轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第二轮循环开始的时候的prev
     * 
     * 在第 2 轮执行的时候
     *        prev === '1' (因为上一轮执行了prev + item 得到的值为1)
     *        item === 2 因为是第2轮循环, 所以他的值就是 数组第2个元素的值
     *          在第2轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第3轮循环开始的时候的prev
     * 
     * 在第 3 轮执行的时候
     *        prev === '12' (因为上一轮执行了prev + item 得到的值为3)
     *        item === 3 因为是第3轮循环, 所以他的值就是 数组第3个元素的值
     *          在第3轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第4轮循环开始的时候的prev
     * 
     * 在第 4 轮执行的时候
     *        prev === '123' (因为上一轮执行了prev + item 得到的值为6)
     *        item === 4 因为是第轮循环, 所以他的值就是 数组第个元素的值
     *          在第4轮代码执行的时候, 运行了return prev + item, 这个结果 会传递给第5轮循环开始的时候的prev
     * ...
     * 
     * 因为后续数组没有元素了,所以循环到此结束,然后将 最后一轮 prev 的值return 出去,外部可以使用一个变量 去接收
     * 
     * */
     ```js
         var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
         console.log('原始数组:', arr)
         
         var str = arr.reduce(function (prev, item, index, origin) {
             return prev + item
         })
         console.log(str) //45
     ```
     /**
     * 第1轮
     *    prev === 1 (因为没传递init,所以prev第一次的值是数组下标0位置上的值)
     *    item === 2 (因为没传递init,所以prev是下标[0] 的值,然后item就拿到了下标[1] 的值)
     *          第1轮运行代码return prev + item 这个结果会传递给下轮循环开始时的prev 
     * 
     * 第2轮
     *    prev === 3 (因为上一轮执行了prev + item 得到的值3)
     *    item === 3 (因为上一轮item的值是[1],所以本轮的值是[2])
     *          第1轮运行代码return prev + item 这个结果会传递给下轮循环开始时的prev 
     * 
     * 第3轮
     *    prev === 6 (因为上一轮执行了prev + item 得到的值3)
     *    item === 4 (因为上一轮item的值是[2],所以本轮的值是[3])
     *          第1轮运行代码return prev + item 这个结果会传递给下轮循环开始时的prev 
     * ...
     * 因为后续数组没有元素了,所以循环到此结束,然后将最后一轮prev的值return出去,外部可以使用一个变量去接收
     * */ 

47、课后练习

```js
     // 1.计算数组的和 var arr = [1, 2, 3, 4, 5]
     var arr = [1, 2, 3, 4, 5]
     
     // 方法1 reduce 用来实现叠加效果
     var sum = arr.reduce(function (prev, item) {
         return prev + item
     },0)
     console.log(sum)
     
     // 方法2 for循环
     function fn(arr){
         var sum = 0;
         for(var i = 0; i < arr.length; i++){
             sum += arr[i]; 
         }
         return sum;
     }
     console.log(sum);
     
     // 方法3 forEach 遍历数组
     var sum = 0
     arr.forEach(function (item) {
         sum += item
     })
     console.log(sum)
     
     // 方法4 map 映射数组,一般不会使用
     var sum = 0
     arr.map(function (item) {
         return sum += item
     })
     console.log(sum)
```
```js
    // 3. 将数组的值 放大 10 倍 并返回一个新数组
    var newArr = arr.map(function (item, index, origin) {
        return item * 10
    })
    console.log('放大十倍的数组', newArr)
    
    // forEach 有点麻烦
    var newArr = []
    arr.forEach(function (item, index, origin) {
        newArr[newArr.length] = item * 10
    })
    console.log('放大十倍的数组', newArr)
```
```js
     // 4. 过滤数组, 让数组内的值只有偶数 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -> 新数组: [2, 4, 6, 8, 10]
     var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     var newArr = arr.filter(function (item, index, origin) {
         return item % 2 === 0
     })
     console.log(newArr)
     
     var newArr = []
     var newArr = arr.forEach(function (item, index, origin) {
         if(item % 2 === 0) {
             newArr.push(item)
         }
     })
     console.log(newArr)
```

48、数组塌陷

    var arr = [0, 1, 2, 3, 4, 5]
    //          0  1  2  3  4  5
    console.log('原始数组', arr)

    // 利用数组的方法,将数组的每一项 删除

    // 利用数组的方法,将数组的每一项删除pop shift splice
    // 1.拿到数组的每一项,暂时先不用数组的方法,使用for循环
    // for (var i = 0; i < arr.length; i++) {
    //   arr.pop()
    //   /**
    //    * 第一轮循环
    //    *    i === 0   arr.length === 6   条件成立,开始执行内部代码
    //    *      arr.pop()   将数组的最后一项删除,删除完毕 arr.length = 5
    //    * 第二轮循环
    //    *     i === 1   arr.length === 5   条件成立,开始执行内部代码
    //    *      arr.pop()   将数组的最后一项删除,删除完毕 arr.length = 4
    //    * 第二轮循环
    //    *     i === 2   arr.length === 4   条件成立,开始执行内部代码
    //    *      arr.pop()   将数组的最后一项删除,删除完毕 arr.length = 3
    //    * 第二轮循环
    //    *     i === 3   arr.length === 3   条件不成立,循环到此结束
    //    * */ 
    // }
    for(var i = arr.length; i >= 0; i--) {
      arr.pop()
      // arr.unshift()
    }
    console.log('删除后的数组', arr)

    for(var i = arr.length - 1; i >= 0; i--) {
      arr.splice(i, 1)
    }
    console.log('删除后的数组', arr)

    var arr = [0, 1, 2, 3, 4, 5]
    //         0  1  2  3  4  5
    console.log('原始数组', arr)
    // 数组塌陷情况1
    for(var i = 0; i < arr.length; i++) {
      arr.splice(i, 1)
      /**
       * 第1轮
       *    i === 0   arr.Length === 6  符合条件
       *        arr.splice(i, 1)    (0,1)把[0]的值截取掉了
       *          现在的数组: arr === [1,2,3, 4, 5]
       *          对应的下标           0  1  2  3  4
       *          数组的Length === 5
       * 第2轮
       *    i === 1    arr.Length === 5  符合条件
       *        arr.splice(i, 1)    (1,1)把[1]的值截取掉了
       *          现在的数组:arr === [1,3,4,5] 
       *          对应的下标          0  1  2  3
       *          数组的Length === 4
       * 第3轮
       *    i === 2    arr.Length === 4  符合条件
       *        arr.splice(i, 1)    (2,1)把[2]的值截取掉了
       *          现在的数组: arr === [1, 3, 5]
       *          对应的下标           0  1  2
       *          数组的Length === 3
       * 第4轮
       *    i === 3    arr.Length === 3  条件不成立,循环到此结束
       * */ 
      i-- //可以解决塌陷
      // var arr = [0, 1, 2, 3, 4, 5]
      //            0  1  2  3  4  5
      /**
       * 第1轮
       *    i === 0   length === 6  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是0
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第2轮
       *    i === 0   length === 5  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是1
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第3轮
       *    i === 0   length === 4  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是2
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第4轮
       *    i === 0   length === 3  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是3
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第5轮
       *    i === 0   length === 2  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是4
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第6轮
       *    i === 0   length === 1  符合条件,执行内部代码
       *        arr.splice(i, 1)此时相当于 把[0]的值截取掉了也就是5
       *        i--   此时相当于把i的值更改为-1
       *        循环内部代码执行完毕之后,会执行一个 i++,所以下一轮循环开始的时候i的值===0
       * 
       * 第5轮
       *    i === 0   length === 0  不符合条件,循环到此结束
       * */ 
    }
    console.log('删除后的数组', arr)

49、数组的数学方法

数学的方法
 * 
 * 在JS中Math对象给我们提供J操作数据的些方法( 教学的方法)
 * 
* !1.random
 * 语法:Math.random()
 * 作用:得到一个随机数,每次生成的数 字都不一样,但一定是0~1之间的,
                     包含0,不包含1, 也就是 说最大值可能是0. 99999...
 ```js
     var num = Math.random()
     console.log(num)
 ```
* 2.round
 *    * 语法:Math.round(数字)
 *    * 作用:将这个数字(小数),按照四舍五入的形式变成整数
 ```js
     var num1 = Math.round(4.499999)
     var num2 = Math.round(4.5)
     console.log(num1) //4
     console.log(num2) //5
 ```
* !3.ceil
 *    * 语法:Math.cei- l(数字)
 *    * 作用:将这个数字(小数)向上取整
 ```js
     var num1 = Math.ceil(1.00001)
     var num2 = Math.ceil(1.99999)
     console.log(num1) //2
     console.log(num2) //2
 ```
* !4.floor
 * 语法:Math.floor(数字)
 * 作用:将这个数字(小数)向下取整
 ```js
     var num1 = Math.floor(1.00001)
     var num2 = Math.floor(1.99999)
     console.log(num1) //1
     console.log(num2) //1
 ```
* 5.abs
 * 语法:Math.abs(数字)
 * 作用:返回这个数字的绝对值
 ```js
     var num1 = Math.abs(1.23)
     var num2 = Math.abs(-1.23)
     console.log(num1) //1.23
     console.log(num2) //1.23
 ```
* 6.sqrt
 * 语法:Math.sqrt(数字)
 * 作用:求平方根
 ```js
     var num = Math.sqrt(16)
     console.log(num) //4
 ```
* 7.pow
 * 语法:Math.pow(基数, 幂)
 * 作用:返回基数的几次幂
  ```js
     var num = Math.pow(2, 3)
     console.log(num) //8
 ```
* 8.max
 * 语法:Math.max(数字1,数字2...)
 * 作用:返回传入的数字中最大的那一个
 ```js
     var num = Math.max(100, 500, 123, 87, 9)
     console.log(num) //500
 ```
* 9.min
 * 语法:Math.min(数字1,数字2...)
 * 作用:返回传入的数字中最小的哪一个
 ```js
     var num = Math.min(100, 500, 123, 87, 9)
     console.log(num) //9
 ```

* 10.PI

 * 语法:Math.PI
 * 作用:返回π
 ```js
     var num = Math.PI
     console.log(num) //3.141592653589793
 ```

50、数组的数学方法课堂案例

```js
/**
 * 1.数组去重
 *      var arr  = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]
 * 处理完毕后的arr === [1, 2, 3, 4, 5]
 * 
 * 2.封装一个函数,函数返回一个0~10之间的随机整数 0 1 2 3 4 5 6 7 8 9 10
 * */ 

// 1.数组去重 var arr  = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5] 
//处理完毕后的arr === [1, 2, 3, 4, 5]
var arr  = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]

// 1.遍历数组,拿到数组的每一项
for (var i = 0; i < arr.length; i++) {
  // console.log(arr[i])
  // 2.判断数组内,除了当前项之外,后续有没有和当前项相同的项
  if(arr.indexOf(arr[i], i + 1) !== -1) { //如果当前分支语句成立,那么代表数组后续一定有与当前重复的值
    arr.splice(i, 1) //分支成立时,将当前项删掉,达到去重的目的
    i-- //直接使用splice会出现 数组塌陷的情况,会导致去重无法清除干净,加上i--,解决数组塌陷
  }
}
console.log(arr)

// 2.封装一个函数,函数返回一个0~10之间的随机整数 0 1 2 3 4 5 6 7 8 9 10
function fn() {
  // var fnNum1 = Math.random() //得到了一个0-1的随机数
  // var fnNum2 = fnNum1 * 10 //得到了一个0-10的随机数
  // var fnNum3 = Math.ceil(fnNum2)// 通过向上取整,将这个随机数改变为随机整数
  // var fnNum3 = Math.round(fnNum2) //通过四舍五入,将这个随机数改变为随机整数
  // console.log(fnNum3)

  /**
 * 目前 随机数取整的方式为 四舍五入 ,会出现概率问题
 * */ 
  // var fnNum3 = Math.round(Math.random() * 10)

  // 当前四舍五入的形式有问题,我们现在要么改为向上取整,要么改为向下取整
  //      如果说使用向上取整,数字应该计算为: -0.999~9.999向上取整后为0~10
  //      如果说使用向下取整,数字应该计算为: 0~10.999 向下取整后为0~10
  //       通过分析认为向下取整比较好计算,所以我们的取整方式更改为向下取整
  //       计算公式       Math.floor(随机数 * (10 + 1))   
  /**
   * 目前的随机数取整方式为向下取整
   * 0~0.999      0
   * ...
   * 9~9.999      9
   * 10~10.999    10
   * */ 
  var fnNum3 = Math.floor(Math.random() * (10 + 1))
  return fnNum3
}
var num = fn()
console.log('num是一个随机数:' , num)

var obj = {}
for(var i = 0; i <= 10000; i++) {
  var sum = fn() //1.循环开始 先拿到的随机数的值
  if(obj[sum] === undefined) {
    obj[sum] = 1 //代表 当前这个随机数 第一次出现
  } else {
    obj[sum]++ 
    //如果执行的else分支,表明sum不是第一次出现具体出现的次数我们不知道,所以直接让他的属性
  }
}
console.log(obj) //得出概率问题的结论
```

51、JS的严格模式

 * JS的严格模式
 * JS是一个相对不是很严谨的语言,在开发的时候 写代码也不是很严格
 * 换句话说严格模式就是对开发的时候 ,你写的代码做了一些要求
 * 严格模式的规则
 *    1.声明变量必须要 var 关键字
 *    2.函数的形参不可以重复
 * JS中默认是没有开启严格模式, 如果想要开启严格模式,需要手动在代码最开始的位置(script标签内第一行), 写一个字符串'use strict'
 * 
 * 现在的公司的项目中,基本都是按照严格模式开发的
 ```js
     'use strict'//开启严格模式
     var a = 100
     console.log(a)
     // b = 200 //b is not defined
     // console.log(b) 
     
     for (var i = 0; i < 3; i++) {
         console.log('for循环1开始执行')
     }
     
     function fn(a, b) {
         console.log(a, b)
     }
     fn(100, 200)
 ```

52、字符集(了解)

 * 字符集
 * 计算机只能存储二进制数据0101010
 * 我们的大写字母小写字母符号之类的内容都是由 二进制数字组成
 * 或者说我们在敲一个字符的时候,都有个对应的编号,计算机存储的时候存储的是这些编号,
 * 只不过我们看到的时候,是通过这些编号解析成我们看到的内容
 * 前身:ASCII  as key (128) 只够 美国人用英语的使用
 * 国内推出了一个属于中国的GBK国标码 前128位ASCII码,后边从129 位开始就是汉字
 * unicode(万国码)   前128 位还是ASCII码, 后边开始是各个国家的文字码
 * 八位十六进制编码         容量小,但是占用内存也小     UTF-8
 * 十六位的十六进制编码     容量大,但是占用内存也大

53、创建字符串

 * 创建字符串的方式
 *    1.字面量的形式创建字符串
 *        var str = 'abc'
 *    2.内置构造函数的形式创建字符串
 ```js
      var str = new String() 
      //创建了一个字符串,但是是空字符
      console.log(str)
      
      var str = new String('abc') //创建了一个字符串
      console.log(str)
 ```

54、字符串的索引与下标

 * 字符串的length与下标
 * 
 *    length与下标的含义与数组中的一样
 *    length: 长度
 *    索引(下标):获取到字符串中指定位置的值
 *    注意:字符串中通过索引能够获取到指定位置的值,只不过获取到的值是只读的  
             换句话说 获取到的值,能看不能改
 ```js
     var str = 'abc'
     console.log(str.length) //3
     console.log(str[1]) //b
     
     str[1] = 'Q' 
     //因为字符串通过索引获取到的值是只读的,我们修改是没用的,所以这一行代码没意义
     console.log(str) //还是abc,无法修改
 ```

55、字符串的方法

(1).charAt
 * 语法:字符串.charAt(索引)
 * 作用:查询指定下标的值
 * 返回值:查询到的值,如果没有查询到就是一个空字符串
 ```js
     var str = 'abcd'
     var str1 = str.charAt(0)
     console.log(str1) //a
     var str2 = str.charAt(50)
     console.log(str2) //因为没有查询到,返回的是空字符串
 ```
(2).charCodeAt
 * 语法:字符串.charCodeAt(索引)
 * 作用:查询指定下标的值 对应的 十进制码
 * 返回值:查询到的值对应的十进制码 如果没有查询到会返回一个NaN
 ```js
     var str = 'abcd'
     var str1 = str.charCodeAt(0)
     console.log(str1) //字符串a的十进制码   97
     var str2 = str.charCodeAt(50)
     console.log(str2) //因为没有查询到 返回一个NaN
 ```
(3).toLowerCase
 * 语法:字符串.toLowerCase()
 * 作用:将这个字符串转换为小写
 * 返回值:转换后的字符串
 ```js
     var str1 = 'abcDEF'
     var str2 = 'QWER'
     var str3 = 'asdf'
     // var str4 = str1.toLowerCase()
     // console.log(str4)
     console.log(str1.toLowerCase()) //abcDEF  ->  abcdef
     console.log(str2.toLowerCase()) //QWER    ->  qwer
     console.log(str3.toLowerCase()) //asdf    ->  asdf
 ```
(4).toUpperCase
 * 语法:字符串.toUpperCase
 * 作用:将这个字符串转换为大写
 * 返回值:转换后的字符串
 ```js
     var str1 = 'abcDEF'
     var str2 = 'QWER'
     var str3 = 'asdf'
     // var str4 = str1.toUpperCase()
     // console.log(str4)
     console.log(str1.toUpperCase()) //abcDEF  ->  ABCDEF
     console.log(str2.toUpperCase()) //QWER    ->  QWER
     console.log(str3.toUpperCase()) //asdf    ->  ASDF
 ```
 * 
(5).substr
 * 语法:字符串.substr(开始索引, 多少个)
 * 作用:截取指定的字符串
 * 返回值:截取到的字符串
 * 注意:mnd说明这个方法将来某一天可能会删除,所以建议我们使用substring
 ```js
     var str = 'qwertyuiop'
     var str1 = str.substr(0, 3) 
     //从下标0开始,截取3个,其实应该 就是下标0,1,2的值
     console.log(str1) //qwe
     var str1 = str.substr(3, 2) 
     //从下标3开始,截取2个,其实应该 就是下标3,4的值
     console.log(str1) //rt
 ```
(6).substring
 * 语法:字符串.substring(开始索引, 结束下标)
 * 作用:截取指定的字符串
 * 返回值:截取到的字符串
 * 注意:
 *    1.参数包前不包后
 *    2.结束索引可以不写,相当于写了length(字符串的总长度)
 ```js
     var str = 'qwertyuiop'
     var str1 = str.substring(0, 3) //从下标0开始,到下标3结束
     console.log(str1) //qwe
     var str2 = str.substring(0) //从下标0开始,结束索引因为没有传递,所以默认是length,也就是从下标0开始,一直到字符串最后
     console.log(str2) //qwertyuiop
 ```
(7).slice
 * 语法:字符串.slice(开始索引, 结束索引)
 * 作用:截取指定字符串
 * 返回值:截取到的字符串
 * 注意:
 *    1.参数包前不包后
 *    2.结束索引可以不写,相当于写了length(字符串的总长度)
 *    3.开始索引可以不写,相当于写了0
 *    4.结束索引支持写负数,相当于length +负数
 ```js
     var str = 'qwertyuiop'
     var str1 = str.slice(0, 3) //从下标0开始,到下标3结束
     console.log(str1) //qwe
     var str2 = str.slice(0) 
     //从下标0开始,因为没写结束索引,所以默认为length
     console.log(str2) //qwertyuiop
     var str3 = arr.slice() 
     //开始索引不写,默认为0,结束索引不写,默认为length
     console.log(str3) //qwertyuiop
     var str4 = str.slice(0, -3) 
     //从下标0开始,到下标length-3结束
     console.log(str4) //qwertyu
 ```
(8).concat
 * 语法:字符串.concat(数据1, 数据2, 数据3...)
 * 作用:将字符串和参数传递的数据 进行拼接
 * 返回值:拼接后的字符串
 ```js
     var str = 'qwer'
     var str1 = str.concat('@', '+', '!')
     console.log(str1) //qwer@+!
 ```
 * 
(9).indexOf
 * 语法:字符串.indexOf(数据, 开始下标)
 * 作用:寻找数据在字符串中的位置
 * 返回值:找到的时候返回下标,找不到返回-1
 * 注意:第二个参数可以不传递,默认为0
 ```js
     var str = 'qwer'
     var str1 = str.indexOf('q', 1) 
     //在字符串str中,下标1的位置,开始查找字符串'q'
     console.log(str1) //-1
     var str1 = str.indexOf('q', 0) 
     //在字符串str中,下标0的位置,开始查找字符串'q'
     console.log(str1) //0
     var str1 = str.indexOf('q') 
     //在字符串str中,下标0的位置,开始查找字符串'q'
     console.log(str1) //0
 ```
 * 
(10).lastIndexOf
 * 语法:字符串.lastIndexOf(数据, 开始索引)
 * 作用:寻找数据在字符串中的位置(从后往前/从右向左)
 * 返回值:找到的时候返回下标,找不到返回-1
 * 注意:第二个参数可以不传递,默认为length - 1
 ```js
     var str = 'qwer'
     var str1 = str.lastIndexOf('e', 1) 
     //在字符串str中,下标1的位置,开始查找字符串'e'
     console.log(str1)//-1
     var str1 = str.lastIndexOf('e') 
     //在字符串str中,下标1的位置,开始查找字符串'e'
     console.log(str1)//2
 ```
 * 
(11).split
 * 语法:字符串.split('符号')
 * 作用:在字符串中找到'符号' 然后将这个字符串分隔,并放在一个数组内
 * 返回值:一个数组
 * 注意:参数如果传递的是 空字符串('') 会将字符串全部分隔开
 ```js
     var str = 'qwer, tyui, asdf, ghjk'
     console.log('原始字符:', str)
     
     var str1 = str.split(',')
     // 通过, 将字符串str分隔到一个数组中
     console.log(str1) //['qwer', ' tyui', ' asdf', ' ghjk']
     
     var str2 = str.split('i')
     // 通过i 将字符串str分隔到一个数组中
     console.log(str2) //['qwer, tyu', ', asdf, ghjk']
     
     var str3 = str.split(' ')
     // 通过一个空格 将字符串str分隔到一个数组中
     console.log(str3) //['qwer,', 'tyui,', 'asdf,', 'ghjk']
     
     var str4 = str.split('')// 通过一个空字符串 将字符串str分隔到一个数组中
     console.log(str4) 
     // ['q', 'w', 'e', 'r', ',', ' ', 't', 'y', 'u', 'i', ',', ' ', 'a', 's', 'd', 'f', ',', ' ', 'g', 'h', 'j', 'k']
     
     var str5 = str.split('@')// 通过一个@ 将字符串str分隔到一个数组中
     console.log(str5) //['qwer, tyui, asdf, ghjk']
 ```
!(12).trim
 * 语法:字符串.trim()
 * 作用:去掉字符串两侧的空格
 * 返回值:去掉空格后的字符串
 ```js
     var str = ' a b c '
     console.log('原始的字符串:', str)
     var str1 = str.trim()
     console.log(str1) //a b c
 ```
(13).trimStart / trimLeft
 * 语法:字符串.trimStart() / 字符串.trimLeft()
 * 作用:去掉字符串开始(左侧)的空格
 * 返回值:去掉空格后的字符串
 ```js
     var str = ' a b c '
     console.log('原始的字符串:', str)
     
     var str1 = str.trimStart()
     var str2 = str.trimLeft()
     console.log(str1) //a b c 
     console.log(str2) //a b c 
 ```
 * 
(14).trimEnd / trimRight
 * 语法:字符串.trimEnd() / 字符串.trimRight()
 * 作用:去掉字符串结束(右侧)的空格
 * 返回值:去掉空格后的字符串
 ```js
     var str = ' a b c '
     console.log('原始的字符串:', str)
     
     var str1 = str.trimEnd()
     var str2 = str.trimRight()
     console.log(str1) // a b c
     console.log(str2) // a b c
 ```
!(15).includes
 * 语法:字符串.includes(字符串片段)
 * 作用:判断 当前字符串中,是否拥有指定字符串片段
 * 返回值:一个布尔值
 *        true -> 拥有
 *        false -> 没有
 ```js
     var str = 'qwertyuiop'
     var str1 = str.includes('tyui')
     console.log(str1) //true
     var str2 = str.includes('tyuip')
     console.log(str2) //false
 ```
(16).startsWith
 * 语法:字符串.startsWith(字符串片段)
 * 作用:判断 字符串开头 是不是指定的字符串片段
 * 返回值:一个布尔值
 *        true -> 是开头
 *        false -> 不是开头
 ```js
     var str = 'qwertyuiop'
     var str1 = str.startsWith('qwer')
     console.log(str1) //true
     var str2 = str.startsWith('wer')
     console.log(str2) //false
 ```
(17).endsWith
 * 语法:字符串.endsWith(字符串片段)
 * 作用:判断 字符串结尾 是不是指定的字符串片段
 * 返回值:一个布尔值
 *        true -> 是结尾
 *        false -> 不是结尾
 ```js
     var str1 = str.endsWith('op')
     console.log(str1) //true
     var str2 = str.endsWith('qwer')
     console.log(str2) //false
 ```
(18).replace
 * 语法:字符串.replace('要被替换的字符', '替换的字符')
 * 作用:找到当前字符串中第一个参数对应的值,然后将其替换为第二个参数
 * 返回值:替换完成的字符串
 ```js
     var str = 'abcdefg'
     var str1 = str.replace('abc', '@@!!##')
     console.log(str1) //@@!!##defg
     var str2 = str.replace('qwer', '@@!!##')
     console.log(str2) //abcdefg
 ```

56、课堂案例(面试题)

* 一道面试题
 *  统计字符串中每个字符串出现的次数(以对象的形式存储)
    // 半成品
    var str = 'aaabbbccddeeeea'
    var obj = {}
   //  通过循环拿到字符串中每个位置的值
   for(var i = 0; i <= str.length; i++) {
     // console.log(str[i])
     var key = str[i]
     if(obj[key] === undefined) {
       /**
        * obj -> 全局声明的空对象
        * key -> 在循环内部创建的一个变量,内部的值 就是 str[i]
        * str[i] -> 字符串对应下标的值
        * 
        * 第一轮循环  i === 0   str[i] === a   key === a
        *    obj[key] -> obj['a'] -> 此时得到的值应该是undefined
        * */ 
       obj[key] = 1
     }
   }
   /**
    * 第1轮
    *    i === 0    str[i] === 'a'   key === 'a'   obj = {}
    * 
    *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  undefined
    *        if 条件成立,obj[key] = 1 -> obj['a'] = 1
    *        第1轮结束后的 obj === {a: 1}
    * 第2轮
    *    i === 1    str[i] === 'a'   key === 'a'   obj = {a: 1}
    * 
    *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  1
    *        if 条件不成立,开始下一轮循环
    *        第2轮结束后的 obj === {a: 1}
    * 第3轮
    *    i === 2    str[i] === 'a'   key === 'a'   obj = {a: 1}
    * 
    *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  1
    *        if 条件不成立,开始下一轮循环
    *        第3轮结束后的 obj === {a: 1}
    * 第4轮
    *    i === 3    str[i] === 'b'   key === 'b'   obj = {a: 1}
    * 
    *        obj[key] === undefined  obj[key]  ->  obj['b']  ->  undefined
    *        if 条件成立,obj[key] = 1 -> obj['b'] = 1
    *        第4轮结束后的 obj === {a: 1, b: 1}
    * */  
    console.log(obj)
    //  基础版
    var str = 'aaabbbccddeeeea'
    var obj = {}
    for(var i = 0; i <= str.length; i++) {
      // console.log(str[i])
      var key = str[i]
      if(obj[key] === undefined) {
        obj[key] = 1
      } else {
        obj[key]++
      }
    }
    console.log(obj)
    /**
     * 第1轮
     *     i === 0    str[i] === 'a'   key === 'a'   obj = {}
     *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  undefined
     *        if 条件成立,执行if分支,else分支不再执行 
     *        obj[key] = 1 -> obj['a'] = 1
     *        第1轮 循环结束后 obj === {a: 1}
     * 第2轮
     *     i === 1    str[i] === 'a'   key === 'a'   obj = {a: 1}
     *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  1
     *        if 条件不成立,不执行if分支,else分支执行 
     *        obj[key]++ -> obj['a']++
     *        第2轮 循环结束后 obj === {a: 2}
     * 第3轮
     *     i === 2    str[i] === 'a'   key === 'a'   obj = {a: 2}
     *        obj[key] === undefined  obj[key]  ->  obj['a']  ->  2
     *        if 条件不成立,不执行if分支,else分支执行 
     *        obj[key]++ -> obj['a']++
     *        第3轮 循环结束后 obj === {a: 3}
     * 第4轮
     *     i === 3    str[i] === 'b'   key === 'b'   obj = {a: 3}
     *        obj[key] === undefined  obj[key]  ->  obj['b']  ->  undefined
     *        if 条件成立,执行if分支,else分支不再执行 
     *        obj[key] = 1 -> obj['b'] = 1
     *        第4轮 循环结束后 obj === {a: 3, b: 1}
     * */ 
    // 优化版
    var str = 'aaabbbccddeeeea'
    var obj = {}
    for(var i = 0; i <= str.length; i++) { 
      // var key = str[i]
      // if(obj[str[i]] === undefined) {//obj[str[i]] =-= undefined 的时候做某些事
      if(!obj[str[i]]) {
        /**
         * 因为undefined 转换为布尔值是false,
         * 
         * 所以如果obj[str[i]]的值就是undefined的时候
         *    那么布尔值就是false,加一个!代表取反,所以实际得到的布尔值 是true
         * 
         * obj[str[i】]要么是undefined要么是从1开始的数字
         *    所以除了是undefined之外的其他情况他的布尔值都是true
         *    加一个!代表取反,所以实际的到的布尔值为false
         * */ 
        obj[str[i]] = 1
      } else {
        obj[str[i]]++
      }
    }
    console.log(obj)
    // 最终版本
    var str = 'aaabbbccddeeeea'
    var obj = {}
    for(var i = 0; i <= str.length; i++) { 
      if(!obj[str[i]]) {
        obj[str[i]] = 1
      } else {
        obj[str[i]]++
      }
    }
    console.log(obj)

57、课后练习

* ①. 反转字符串
 * var str = 'abcdef'
 * 代码处理后的 str === fedcba
 ```js
     // 方法1
     var str = 'abcdef'
     // var newStr = str.split('')
     // var newStr2 = newStr.reverse()
     // var newStr3 = newStr2.join('')
     var newStr = str.split('').reverse().join('')
     console.log(newStr3)
     
     // 方法2
     var newStr = '';
     for(var i = 0; i <= str.length; i++) {
         var s = str.charAt(str.length-i-1)
         newStr += s
     }
     console.log(newStr)
 ```
* ②.查询字符串
JS 中内把字符串分为几种类型(约定)
1. 普通字符串: '123asd阿松大'
2. 数字字符串: '123123123123123'
3. html格式字符串: '<p></p>'
4. 查询字符串: 'key=value&key2=value2&key3=value3'
    * 一条数据: key=value
    * 多条数据: & 符间隔
假设 str 存储的是后端反馈给我们的一个信息
var str = 'username=靓仔&age=18&qq=88888888'
需求1:
将'username=靓仔&age=18&qq=88888888'
更改为
{
    username: '靓仔',
    age: 18,
    qq: 88888888
}
需求2:
将
{
    username: '靓仔',
    age: 18,
    qq: 88888888
}
更改为
'username=靓仔&age=18&qq=88888888'
```js
    // 需求1 字符串转对象
    var str = 'username=靓仔&age=18&qq=88888888'
    var obj = {}
    /**
    * 分析:
    *    1.拿到字符串中所有的key
    *    2.拿到字符串中所有的key对应的value
    * 
    * 逻辑:
    *    1.将字符串分割为key=value (分割完应该会有3个)
    *    2.拿到每一个key 添加到对象中,并且给值赋值为对应的vaLue
    * */ 
    //  1.将字符串分割为key=value (分割完应该会有3个)
    var arr = str.split('&')
    //  console.log(arr)
    //  2.拿到每一个key添加到对象中,并且给值赋值为_对应的value
    // 2.1遍历数组拿到数组的每一项,也就是每一个 key=value
    arr.forEach(function(item) {
        var itemInfo = item.split('=')
        /**
        * console.log(itemInfo)
        * ['username', '靓仔']
        * ['age', '18']
        * ['qq', '88888888']
        * var key = itemInfo[0]
        * var value = itemInfo[1]
        * obj[key] = value
        * */ 
        obj[itemInfo[0]] = itemInfo[1] //向对象内存储
    })
    
    // 需求2 将对象转换为 字符串
    console.log(obj)
    var newStr = ''
    /**
    * obj === {
        username: '靓仔',
        age: 18,
        qq: 88888888
    }
    * 需要将他转换为一个字符串'username=视仔&age=18&qq=88888888'
    * 核心:拿到对象的所有key 与value,然后拼接到一个字符串中
    * */ 
    for (var k in obj) {
        newStr += k + '=' + obj[k] + '&'
    }
    console.log(newStr)// 此时结尾多一个 &
    newStr = newStr.slice(0, -1)
    console.log(newStr)
```

58、进制转换与保留小数

1.进制转换(了解)
1.1十进制转换为其他进制
  语法:十进制数字.toSting(几进制)
    var num = 100 //10进制的数字100
    var num1 = num.toString(2) //讲10进制的100转换为2进制的数字
    console.log(num1) //1100100
1.2其他进制转换为十进制
语法:parseInt(数字,将数字视为几进制的数字转换为10进制的数字)
    var num = parseInt(100, 2) 
    //将100视为2进制的数字,然后转换为10进制的数字,得到数字4
    console.log(num) //4
!2.保留小数(掌握)
语法:toFixed(保留几位小数), 保留小数的时候四舍五入,并且返回的是字符串
    var num = 100.123456789
    var num1 = num.toFixed(2) //通过四舍五入保留两位小数
    console.log(num1) //100.12
    var num2 = num.toFixed(4) //通过四舍五入保留四位小数
    console.log(num2) //100.1235

59、定时器

 * 两种定时器的介绍
①.setInterval 计时器,每间隔固定的时间执行一次
 * 语法:setInterval(函数, 数字/时间)
 *      函数:每间隔固定的时间要执行的代码
 *      数字:问隔的时问,注意单位是毫秒 ,最小值为4~20
 ```js
    setInterval(function() {
        console.log('我是一个定时器~~~')
    }, 1000)
```
②.setTimeout 倒计时器,在指定时间到达后,执行一次
 * 语法:setTimeout(函数, 数字)
 *      函数:在指定时间到达后要执行的代码
 *      数字:间隔时间,单位也是毫秒
 ```js
     setTimeout(function() {
         console.log('我是一个倒定时器~~~')
     }, 3000)
 ```
* 两个定时器的返回值与意义
 * + 返回值不区分定时器种类,用于表示你这个定时器是页面中第几个定时器
 * + 作用:用来关闭定时器
 ```js
     //  1.计时器 setInterval
     var timeId1 = setInterval(function() {
         console.log('我是一个定时器~~~')
     }, 1000)
     
     // 2.倒计时器 setTimeout
     var timeId2 = setTimeout(function() {
     console.log('我是一个倒定时器~~~')
     }, 3000)
     console.log('计时器ID', timeId1) //1
     console.log('倒计时器ID', timeId2) //2
 ```
* 关闭定时器
 * + 不区分定时器种类,只要给出正确的定时器返回值就可以关闭
 * + 语法:
 *    clearTimeout(定时器返回值) 
 *      注意:能够关闭计时器也能关闭倒计时器
 *           开发人员的约定:这个定时器只用来关闭倒计时器
 *           目的就是为了让其他开发人员看到这个行代码之后,知道你关闭了一个倒计时器
 *    clearInterval(定时器返回值)
 *      注意:能够关闭计时器也能关闭倒计时器,
 *           开发人员的约定:这个定时器只用来关闭计时器
 *           目的就是为了让其他开发人员看到这个行代码之后,知道你关闭了一个计时器
 * */ 
 ```js
      //  1.计时器 setInterval
      var timeId1 = setInterval(function() {
          console.log('我是一个定时器~~~')
      }, 1000)
      clearInterval(timeId1)
      
      // 2.倒计时器 setTimeout
      var timeId2 = setTimeout(function() {
          console.log('我是一个倒定时器~~~')
      }, 3000)
      clearTimeout(timeId2)
 ```

60、异步代码

 * 简单的代码异步执行机制(并不是详细的,详细的内容后期还会讲)
 * 
 *  这是一道面试题,请熟读并背诵全文
 * 
 * 什么是非异步代码
 *    按照从上往下的顺序,从左到右的顺序,依次执行每一行代码
 *    如果上一行代码没有执行完毕,不会执行下一行代码
 * 
 * 什么是异步代码
 *    当代码遇到异步任务的时候,会把这个代码放在'异步队列'内等待
 *    所有的同步代码全都执行完毕之后,在开始执行“异步队列”内的代码
 * 简单来说:代码在执行的时候如果遇到异步任务,会先放在‘异步队列’内等着,然后继续往下执行,直到把所有的同步代码执行完毕后,在开始执行异步任务
 * 
 * 什么是异步任务
 *    两种定时器都是异步任务
 * 可以理解:先执行定时器外面的代码然后执行定时器里边的代码
 ```js
     console.log('开始')
     setTimeout(function() {
         console.log('倒计时器执行了~~~')
     }, 3000)
     console.log('结束')

/**
 * 运行顺序
 *  1.开始
 *  2.结束
 *  3.倒计时器执行了~~~
 * */ 
 ```
 ```js
     console.log('1')
     setTimeout(function() {
         console.log('2')
     }, 3000)
     console.log('3')
     setTimeout(function() {
     console.log('4')
     }, 4000)
     console.log('5')
     setTimeout(function() {
     console.log('6')
     }, 2000)
     console.log('7')
     //  执行顺序 1 3 5 7 6 2 4
 ```
 #### **61、创建时间对象**
在Js中 Date 给我们提供了操作时间的一些方法,是JS内置的一个对象    
    var timer = new Date() 
    //new Date()  会给我们返回一个时间对象
    console.log(timer)
    //Wed Jan 04 2023 14:12:56 GMT+0800 (中国标准时间)

62、时间对象的参数

* 创建时间对象的时候,可以选择传递参数,也可以不传递参数
 *    如果需要传递参数,分为两种方式
①.数字
 * 最少要传递两个值,年 和 月(JS中0-11代表了1-12月)
 ```js
     //                    年   月  日  时   分  秒
     var timer = new Date(2020, 00, 31, 23, 59, 59)
     console.log(timer)
 ```
②.字符串
 * 最少只需要传递一个参数年份即可(字符串的形式传递时月份从1开始)
 ```js
     //                    年   月 日  时 分 秒
     var timer = new Date('2019-02-13 13:14:15')
     console.log(timer)
 ```

63、获取时间对象

    var timer = new Date()
    // console.log(timer)
①.得到时间对象中的年份
    var year = timer.getFullYear()
    console.log(year) //2023
②.得到时间对象中的月份
    var month = timer.getMonth()
    console.log(month) //0 -> 1月
③.得到时间对象中的那一天/日
    var day = timer.getDate()
    console.log(day) //4
④.得到时间对象中的小时
    var hours = timer.getHours()
    console.log(hours) //14
⑤.得到时间对象中的分钟
    var minutes = timer.getMinutes()
    console.log(minutes) //43
⑥.得到时间对象中的秒
    var seconds  = timer.getSeconds()
    console.log(seconds) //44
⑦.得到时间对象中的一周的第几天(用0-6表示周一到周日,但是周日为0)
    var days = timer.getDay()
    console.log(days)
⑧.getTime 按照格林威治时间计算 从1970年1月1日0时0分0秒 到 现在(或指定日期)的毫秒数
    var getTime = timer.getTime()
    console.log(getTime)

64、设置时间对象

    var timer = new Date() 
    //Wed Jan 04 2023 15:04:17 GMT+0800 (中国标准时间)
①设置 年
    timer.setFullYear(2008)
    console.log(timer.getFullYear()) //2008
②设置 月
    timer.setMonth(11)
    console.log(timer.getMonth()) //11
③设置 当月的第几天
    timer.setDate(20)
    console.log(timer.getDate()) //20
⑤注意:没有设置 本周的第几天
⑥设置 时
    timer.setHours(16)
    console.log(timer.getHours()) //16
⑦设置分
    timer.setMinutes(30)
    console.log(timer.getMinutes()) //30
⑧设置秒
    timer.setSeconds(40)
    console.log(timer.getSeconds()) //40
⑨设置毫秒(0-999)
    timer.setMilliseconds(888)
    console.log(timer.getMilliseconds()) //888
⑩直接设置到1970 的总毫秒
    timer.setTime(123456789)
    console.log(timer.getTime()) //123456789

65、认识BOM

 * BOM
 *    浏览器对象模型,其实就是操作浏览器的一些能力
 * 
 * 我们可以操作那些内容?
 *    +获取浏览器的相关信息(窗口大小)
 *    + 操作浏览器进行页面的跳转
 *    + 获取浏览器地址栏的信息
 *    + 操作浏览器的滚动条
 *    + 获取浏览器的版本
 *    + 让浏览器出现一个弹出框
 *    + ...
 * 
 * BOM 的核心就是 window 对象
 *    window 是JS内置的一个对象,里面包含着操作浏览器的方法

66、体验BOM

* ①.获取浏览器窗口的尺寸
 * innerHeight / innerWidth
 *   + 作用:获取浏览器窗口的高度和宽度(包含滚动条)
 *   + 语法:window.innerHeight / window.innerWidth
    console.log('浏览器窗口的高度', window.innerHeight)
    console.log('浏览器窗口的宽度', window.innerWidth)
* ②.浏览器的弹出框 (学习的时候会用,实际工作中不会使用)
 * alert
 * prompt
 * confirm
 *   * 有一个询问信息和两个按钮
 *   * 点击确定按钮 返回 true
 *   * 点击取消按钮 返回 false    
    var boo = confirm('请问您确定进入页面吗?')
    console.log(boo)
* ③.浏览器的地址信息
 * + 在 window 中,有一个 对象 叫做 location,他是专门用来存储浏览器地址栏内的信息
* 3.1 location 这个对象中,有一个属性叫做href
 * 这个属性是专门存储浏览器地址栏内的 url 地址的信息
 * 我们也可以给这个属性赋值,这样就会跳转到我们赋值的地址了
 <body><button>点击跳转到百度</button></body>
    setTimeout(function() {
        window.location.href = 'https://www.baidu.com/'
    }, 3000)
* 3.2 reload 这个对象中,有一个方法叫做reload
 * 这个方法调用时会重新加载页面,相当于刷新
 * 注意!!!不要直接写在代码中,否则浏览器会一直刷新
    var count = 0
    setInterval(function() {
        count++
        console.log(count)
        if(count === 5) {
            window.location.reload() //不能直接写在代码中
        }
    }, 1000)
* ④.浏览器的历史记录
 * + window对象中有一个叫做history他专门用来存储历史记录信息
* 4.1 history.back
 * 专门用来回退历史记录,就是回到前一个页面,相当于浏览器左上角的←按钮
 * 注意:我们需要有上一条记录,否则不能使用这个方法
 * 语法:window.history.back()
* 4.2 history.forward
 * 是去到下一个历史记录里面,也就是去到下一个也买你,相当于浏览器左上角的→按钮
 * 注意:我们需要之前有过回退操作,不然无法使用这个方法
 * 语法:window.history.forward()

67、BOM的事件

* ①.浏览器的版本信息(了解)
 *      window 中的 navigator 可以获取到浏览器的信息
 * 
* ②.浏览器的onload事件
 *      这个事件会在页面所有资源加载完毕后执行
 *      window.onload = function() {
 *        我们的 Js 代码全部书写在这个函数内部
 *      }
 * 
 * 在浏览器中,把JS 写在 head 中,在S加载时,下边的body标签还没来得及加载
 *     可能会导致我们获取body内部的标签,比如说div或者img,出现问题获取不到
 *      如果把代码放在onload 中,则不会出现这个问题
 * 如果把Js写在body底部,写不写onload都无所谓
* ③.浏览器的onscroll 事件
 *    当浏览器的滚动条滚动时会触发该事件,或者鼠标滚轮滚动时触发(前提是有滚动条)
 * 
* ④.浏览器的滚动距离
 *    + 浏览器的内容可以滚动,那么我们就能获取到浏览器的滚动距离
 * 
 *    思考:
 *        浏览器真的滚动了吗?
 *            其实浏览器并没有滚动,而是浏览器内部的页面在滚动
 *            换句话说:湖览器没动,页面向上或者向下走了
 *        所以这个不能单纯的说是湖览器的内容了,而是页面的内容
 *        那么我们这里就不能再使用window对象,而是使用document对象
 * 
 *    scrollTop
 *      获取的是向上滚动的距离
 *          语法1:document.body.scrollTop
 *          语法2:document.documentElement.scrollTop
 ```js
     window.onscroll = function() {
        //console.log('浏览器滚动了~~~')
        console.log('body:', document.body.scrollTop) //没有DOCTYPE声明的时候
        console.log('documentElement:', document.documentElement.scrollTop) //有DOCTYPE声明的时候
    }
 ```
 *        两种语法的区别:
 *            IE浏览器(了解)
 *                没有DOCTYPE声明的时候,两种语法没有差别用哪个都无所谓
 *                有DOCTYPE 声明的时候,只能使用语法2 documentELement
 * 
 *            Chorme 和 FireFox
 *                没有DOCTYPE声明的时候, 用语法1 body
 *                有DOCTYPE声明的时候,用语法2 documentELement
 *            Safari
 *                这两个语法都不用,使用一个单独的方法window.pageYoffset
 * 
 *    scrollLeft
 *      获取的是向左滚动的距离
 *        语法1:document.body.scrollLeft
 *        语法2:document.documentELement.scrollLeft
 *      区别参考 scrollTop
 ```js
     window.onscroll = function() {
         // console.log('浏览器滚动了~~~')
         console.log('body:', document.body.scrollLeft) //没有DOCTYPE声明的时候
         console.log('documentElement:', document.documentElement.scrollLeft) //有DOCTYPE声明的时候
     }
 ```