第一篇 JS语言基础之Math方法 数组方法 字符串方法

210 阅读14分钟

1 . Math

Math(数学函数) : 但它不是一个函数 , 它是一个对象 ,对象中存储了很多操作数字的属性方法 , 因此被称为数学函数 .

console.log(typeof Math); // => 'object'

Math的数据类型是对象,里面有很多属性方法 :

            Math = {
                PI : 3.141592653589793,
                abs: function(){[native code]},
                ceil: function(){[native code]},
                ...
            }
            对于属性
            Math.PI
            对于方法: 属性值是函数的属性
            Math.abs()

2 . Math常用的属性和方法

1. Math . abs ( )

写法 : Math.abs([ number value ])

获取绝对值 ( 绝对值永远非负 )

传递的不是数字类型的值 : 先基于Number() 转换为数字再处理

        console.log(Math.abs(-12.5)); // => 12.5
        console.log(Math.abs(12)); // => 12
        console.log(Math.abs(0)); // => 0
     // 传递的不是数字类型会输出什么?  先基于Number()转换为数字再处理
        console.log(Math.abs('-1')); // => 1
        console.log(Math.abs('-1px')); // => NaN
        console.log(Math.abs(true)); // => 1

2. Math . ceil / floor ( )

写法: Math . ceil / floor ([ number value ])

把一个数字向上 / 向下取整

向上取整 , 除整数外 , 一定会取一个比原来数字大的数

向下取整 , 除整数外 , 一定会取一个比原来数字小的数

        console.log(Math.ceil(12)); // => 12
        console.log(Math.ceil(12.1)); // => 13
        console.log(Math.ceil(12.9)); // => 13
        console.log(Math.ceil(-12.1)); // => -12
        console.log(Math.ceil(-12.9)); // => -12
       ===========================================
        console.log(Math.floor(12)); // => 12
        console.log(Math.floor(12.1)); // => 12
        console.log(Math.floor(12.9)); // => 12
        console.log(Math.floor(-12.1)); // => -13
        console.log(Math.floor(-12.9)); // => -13
        

3 . Math . round ( )

数字四舍五入

        console.log(Math.round(12)); // => 12
        console.log(Math.round(12.1)); // => 12
        console.log(Math.round(12.5)); // => 13  正数中 .5入
        console.log(Math.round(12.9));  // => 13
        // 满 5 进 1 不考虑正负大小
        console.log(Math.round(-12.1)); // => - 12
        console.log(Math.round(-12.5)); // => - 12 负数中 .5舍
        console.log(Math.round(-12.51)); // => - 13
        console.log(Math.round(-12.9)); // => - 13

4 . Math . max / min ( [ val1 ] , [ val2 ] , ... )

获取一堆数中的最大值和最小值

       console.log(Math.max(12,5,46,7,3)); // => 46
       console.log(Math.min(12,5,46,7,3)); // => 3

思考 : 如何基于Math.max / min 获取数组中的最大值最小值?

Math.max([12,5,68,3,7]); // => NaN

此处只传递了一个值,是个数组,和内置的语法要求不符

答:

  1. 展开运算符 ...

  2. 待补充

5 . Math . sqrt / pow ( )

sqrt : 给一个数开平方

pow : 计算一个数的多少次幂 ; 第一个参数是底数 , 第二个参数是幂

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

6. Math . random ( )

获取 0 ~ 1 之间的随机小数

         for (let i = 0; i < 10; i++) {
             console.log(Math.random);
         }

扩展: 获取[ n ~ m ] 之间的随机整数

包含 n 不包含 m 且 n < m

Math.round ( Math.random ( ) * ( m - n) + n )

应用 : 获取十个 25-96 之间的随机整数

      for (let i = 0; i < 10; i++) {
      let ran = Math.round(Math.random() * (96 - 25) + 26);
         console.log(ran);
      } 

3. 数组及数组中常用的方法

数组是对象数据类型的,它属于特殊的对象

ary = [1,2,3,4]

等同于

ary = { 0 : 1, 1 : 2, 2 : 3, 3 : 4, length : 4 }

  • 属性名包括

    • 以0开始的数字 , 也称之为索引

    • length : 数组长度 (元素的个数)

  • 属性值可以为任意类型的值

    • ary[索引] 根据索引获取指定项的内容

    • ary.length 获取数组的长度

    • ary.length-1 最后一项的索引 ,获取最后一项

方法的四个方面 :

  • 方法的作用和含义

  • 方法的实参(类型和含义)

  • 方法的返回值

  • 原来的数组是否会发生变化

3.1 关于数组增删改查的方法 原数组都会改变

这些方法都会修改原有的数组

1. push ( )

作用 : 向数组末尾增加内容
params : 多个任意类型值
return : 新增后数组的长度
原数组: 会发生变化

应用:

        let ary = [10,20];
        let res = ary.push(30,"AA",{name:'Ark'});
        console.log(res,ary); // => 5 [10,20,30,"AA",{...}]

基于原生JS操作键值对的方法向数组末尾增加一项

    ary[ary.length] = 40 ;
    console.log(ary); // => [10,20,30,"AA",{...},40]

2. unshift ( )

作用 : 向数组开头增加内容
params : 多个任意类型值
return : 新增后数组的长度
原数组: 会发生变化

应用:

        let ary = [10,20];
        let res = ary.unshift(30,"AA",{name:'Ark'});
        console.log(res,ary); // => 5 [30,"AA",{...},10,20]

基于原生JS向数组末尾增加一项 : 无法做到.

ary[0] = XXX; => 只是把第一项顶替了

ary[-1] = XXX; => 只是在数组里增添了一项属性名为-1的属性, 且不会改变length属性的属性值

因为添加的不是正常索引, 所以length长度不会变

基于原生ES6展开运算符, 把原有的ARY克隆一份,在心底数组中创建第一项,其余的内容使用原始ARY中的信息即可, 也算实现了向开始追加的效果 (并不是改变原来的数组, 是创造了一个新的数组)

       ary = [100,...ary]
       console.log(ary); // => [100,10,20,30,"AA",{...},40]

3. shift ( )

作用 : 删除数组第一项
params :
return : 删除的那一项
原数组: 会发生变化

应用:

        let ary = [10,20,30,40];
        let res = ary.shift();
        console.log(res,ary); // => 10 [20,30,40]

基于原生JS中的DELETE

delete ary[0]

console.log(ary); // => [empty ,30,40]

image.png

结论: 基于原生JS中的DELETE , 把数组当做普通的对象,确实可以删除掉某一项内容,但是不会影响数组本身的结构特点 (length长度不会跟着修改),真实项目中不好用.

4. pop ( )

作用 : 删除数组末尾一项
params :
return : 删除的那一项
原数组: 会发生变化

应用:

        let ary = [10,20,30,40];
        let res = ary.pop();
        console.log(res,ary); // => 40  [10,20,30]

基于原生JS让数组长度减少一位,默认减少的就是最后一项

        ary.length -- ; // ary.length = ary.length - 1     
        console.log(ary); // => [10,20]

5. splice ( )

作用 : 增 删 改 数组任意几项
params : 三部分参数

  • 前两部分: n , m 都是数字 => 从索引n开始(包含n)删除m个元素 ; m不写, 从n开始删除到末尾
  • 第三部分: 要添加进去的具体项 return : 把删除的部分用新数组存储起来返回
    原数组: 会发生变化

删:

params
n , m 都是数字 => 从索引n开始(包含n)删除m个元素 ; m不写, 从n开始删除到末尾

应用:

        let ary = [10,20,30,40,50,60,70,80,90];
        let res = ary.splice(2,4)
        console.log(res,ary); // => [30, 40, 50, 60]  [10, 20, 70, 80, 90]
  1. 清空一个数组, 把原始数组中的内容以新数组存储起来(有点类似于数组的克隆: 把原来数组克隆一份一模一样的给新数组)
   res = ary.splice(0)
   console.log(res,ary); // =>  [10, 20, 70, 80, 90] []
  1. 删除最后一项 ary.splice(ary.length - 1)

  2. 删除第一项 ary.splice(0,1)

总结:

删除数组最后一项的方法 :

  • pop

  • length--

  • splice(ary.length - 1)

删除数组第一项:

  • shift( )

  • ary.splice(0,1)

增与改:

params
n , m , x => 从索引n开始(包含n)删除m个元素,用x占用删除的部分
n , m , 0 => 从索引n开始(包含n)一个都不删,把x放到索引n的前面

应用:

    改
        let ary = [10,20,30,40,50];
        let res = ary.splice(1,2,'占位')
        console.log(res,ary); // =>  [20, 30] [10,'占位',40,50]

    增
        let res2 = ary.splice(1,0,'看看我在哪里')
        console.log(res,ary); // => (2) [20, 30] (5) [10, '看看我在哪里', '占位', 40, 50]

向数组末尾追加 :

ary.splice(ary.length-1) 这个不行, 会把最后一位往后挤

ary.splice(ary.length,0,'AA')

向数组开始追加 :

ary.splice(0,0,'AA')

总结:

向数组末尾追加

  • push( )

  • ary.[ary.length] = xxx

  • ary.splice(ary.length,0,xxx)

向数组开始追加:

  • unshift( )

  • ary.splice(0,0,xxx)

3.2 数组的查询和拼接 不改变原数组

此组方法,原来的数组不会变 因为只是查询和拼接

1. slice( )

作用 : 实现数组的查询
params : n,m都是数字, 从索引n开始,找到索引为m的地方(不包含m这一项)
return : 把找到的内容以新数组的形式返回
原数组: 不会发生变化

应用:

        let ary = [10,20,30,40,50];
        let res = ary.slice(1,3);
        console.log(res,ary); // => [20,30] [10,20,30,40,50]

m不写是找到末尾

      res = ary.slice(1);
      console.log(res,ary); // => [20,30,40,50] [10,20,30,40,50]

数组的克隆: 参数0, 不写也可以.

      res = ary.slice(0);
      console.log(res,ary); // => [10,20,30,40,50] [10,20,30,40,50]

这种克隆方式叫做浅克隆?.两个一模一样的数组,原数组不变, 且 新数组===原数组 为 false

思考:

  1. 如果n/m为负数会怎样?小数呢?非有效数字呢?

  2. 如果n>m会怎样?

  3. 如果m或者n的值比最大索引都大会怎样?

2. concat( )

作用 : 实现数组的拼接 params : 多个任意类型值
return : 拼接后的新数组 原数组: 不会发生变化

应用:

        let ary1 = [10,20,30];
        let ary2 = [40,50,60];
        let res = ary.concat('Ark',ary2);
        console.log(res,ary); // => [10,20,30,'Ark',40,50,60] [10,20,30]

当concat(),实现了数组的克隆

        let ary1 = [10,20,30];
        let res = ary.concat();
        console.log(res,ary); // => [10,20,30] [10,20,30]
 
        res === ary1 false

3.3 数组转换为字符串 不改变原数组

此组方法,原来的数组不会变

1. toString( )

作用 : 数组转换为字符串 params : 无
return : 转换后的字符串 ,每一项用逗号分隔
原数组: 不会发生变化

应用:

        let ary = [10,20,30];
        let res = ary.toString();
        console.log(res,ary); // => "10,20,30"
        console.log([]); // => ""
        console.log([12]); // =>  "12"

2. join( )

作用 : 数组转换为字符串且能指定分隔符
params : 指定的分隔符,且为字符串格式 ; 空着不填,则默认用逗号作为分隔符
return : 转换后的字符串 ,每一项用指定分隔符分隔
原数组: 不会发生变化

应用:

        let ary = [10,20,30];
        let res1 = ary.join();
        console.log(res1); // => "10,20,30"
        let res2 = ary.join('');
        console.log(res2); // => "102030"
        let res3 = ary.join(' ');
        console.log(res3); // => "10 20 30"
        let res4 = ary.join('|');
        console.log(res3); // => "10|20|30"
        let res5 = ary.join('+');
        console.log(res3); // => "10+20+30"
        eval 把字符串变为JS表达式执行

3.4 检测数组中是否包含某一项

1. indexOf / lastIndexOf / includes ( )

作用 : 检测当前项在数组中第一次或者最后一次出现位置的索引值 (IE6~8中不兼容) params : 要检索的这一项内容
return : 这一项出现的位置索引值(数字) ,如果数组中没有这一项,返回的结果是 -1 (因为0及0以上都代表这项存在) 原数组: 不会发生变化

应用:

        let ary = [10,20,30,10,20,30];
        console.log(ary.indexOf(20)); // => 1
        console.log(ary.lastIndexOf(20)); // => 4
        
        想验证ARY中是否包含"XXX"
        if(ary.indexOf('xxx') === -1){
            // 不包含
        }
        
        // 也可以直接使用ES6新提供的includes方法判断
        if(ary.includes('xxx')){
            // 包含: 如果存在返回的是TRUE
        }

3.5 数组的排序或者排列

1. reverse ( )

作用 : 把数组倒过来排列 params : 无
return : 排列后的新数组 原数组: 会发生变化

应用:

        let ary = [12,15,9,28,10,22];
        let res = ary.reverse();
        console.log(res); // => [22, 10, 28, 9, 15, 12]

2. sort ( )

作用 : 把数组排序
params : 可以没有(有缺陷),也可以是个函数
return : 排列后的新数组 原数组: 会发生变化

应用:

参数为空:

        let ary = [7,8,5,2,4,6,9];
        let res = ary.sort();
        console.log(res); // => [2, 4, 5, 6, 7, 8, 9]
        
        let ary1 = [12,15,9,28,10,22];
        let res1 = ary1.sort();
        console.log(res1); // => [10, 12, 15, 22, 28, 9]

SORT方法中如果不传参数, 是无法处理10以上数字的排序: 因为它默认按照每一项第一个字符来排, 不是我们想要的效果.

参数为函数:

        let ary1 = [12,15,9,28,10,22];
        let res1 = ary1.sort((a,b)=>{
            console.log(ary1) // 见下图
            console.log(a,b); // => a和b是相邻的两项
        });

image.png

        let ary1 = [12,15,9,28,10,22];
        let res1 = ary1.sort((a,b)=>{
            // a和b是相邻的两项
            return a - b;
        });
        console.log(res1); // => [9, 10, 12, 15, 22, 28]
=============================================================
         let ary2 = [12,15,9,28,10,22];
        let res2 = ary2.sort((a,b)=>{
            return b - a;
        });
        console.log(res2); // => [28, 22, 15, 12, 10, 9]

结论 : 想要实现多位数正常排序,需要给SORT传递一个函数,函数中返回 a-b 实现升序( 由小到大 ) ,返回 b-a 实现降序( 由大到小 )

为什么?因为ab是相邻两项是进行比较 需要先了解冒泡排序机制 (待补充)

3.6 遍历数组中每一项的方法

  • forEach
  • map
  • filter
  • find
  • reduce
  • some
  • every
  • ...

1. forEach ( )

作用 : 遍历数组中的每一项内容
params : 回调函数(callback)
return : 无 原数组: 不会发生变化

基于原生JS中的循环可以实现遍历数组中的每一项内容

        let ary2 = [12, 15, 9, 28, 10, 22];
        for (let i = 0; i < ary.length; i++) {
            // i:当前循环这一项的索引
            // ary[i] 根据索引获取循环的这一项
            console.log('索引:' + i + '内容:' + ary[i]);
        }

forEach应用:

  1. 数组当中有多少项 , 函数就会被默认执行多少次
    • 每一次执行函数: item 是数组中当前要操作的这一项 , index 是当前项的索引.
下列代码与上个代码块的输出结果完全一致

       let ary2 = [12, 15, 9, 28, 10, 22];
       ary.forEach((item,index)=>{
        console.log('索引:' + index + '内容:' + item);
       })
  1. 类数组不可以使用数组方法.

Array.prototype 在控制台中查看数组中所有提供的方法,结合MDN

数组方法未完待续 ...

4. 字符串中常用的方法

所有用 单引号 双引号 反引号 包起来的都是字符串
每一个字符串都是有零到多个字符组成

基本操作 长度与索引 类似于数组

    let str = 'zheshiyigezifuchuan'
    str.length; //=> 字符串的长度
    str[0];   // => 获取索引为零(第一个)字符
    str[str.length-1];   // => 获取最后一个字符 
    str[10000]; // => undefined 不存在这个索引

    //循环输出字符串中的每一个字符
    for (let i = 0; i < str.length; i++) {
        let char = str[i];
        console.log(char); // => 循环输出单个字符
    }

1. charAt / charCodeAt

作用 : 根据做引获取指定位置的字符/字符的Unicode 编码值
params : n [ number ] 获取字符指定的索引
return :返回查找到的字符 ( 找不到返回的是空字符串 不是undefined ) 或 对应的编码值
原字符串: 值类型,直接按值操作, 不会对原值产生影响

    let str = 'zheshiyigezifuchuan';
    console.log(str.charAt(0)); // => 'z'
    console.log(str[0]); // => 'z'
    // 一般情况下 输出结果是一样的; charAt的好处就是返回空串 不返回undefined
    console.log(str.charAt(1000)); // => ''
    console.log(str[1000]); // => undefined
    console.log(str.charCodeAt(0)); // => 122 十进制的值 (二进制 0111 1010 八进制 0172 十六进制 0x7A)
    console.log(String.fromCharCode(122)); // => 'z' 通过编码值找到字符

2. substr / substring / slice

作用 : 字符串截取 (在原字符串中查找到自己想要的)
params :
substr ( n , m ) : 从索引 n 开始截取 m 个字符, m 不写截取到末尾 ( 其他两个方法也是 ) substring ( n , m ) : 从索引 n 开始找到索引为 m 处 ( 不含m )
slice ( n , m ) : 和 substring 一样,都是找到索引为 m 处,但是 slice 可以支持负数为索引,其余两个方法是不可以的
return : 返回查找到的字符 ( 找不到返回的是空字符串 不是 undefined ) 或 对应的编码值
原字符串: 值类型,直接按值操作, 不会对原值产生影响

  1. substr和substring
    let str = 'zheshiyigezifuchuan';
    // 参数一致 返回结果完全不同
    console.log(str.substr(3,7)); //=> shiyige
    console.log(str.substring(3,7)); //=> shiy
    // m不写
    console.log(str.substr(3)); //=> zheshiyigezifuchuan 截取到末尾
    // m远大于原字符串长度
    console.log(str.substring(3,10000)); //=> zheshiyigezifuchuan 截取到末尾
    // 超过索引,也只截取到末尾
  1. subtring和slice
// 参数一致时,返回结果一致
console.log(str.substring(3,7)); //=> shiy
console.log(str.slice(3,7)); //=> shiy
// slice支持负数索引 
console.log(str.substring(-7,-3)); //=> 
console.log(str.slice(-7,-3)); //=> fuch
  1. 负数索引 可以按照str.length + 负数索引的方式找

    本质是倒着找,从字符串末尾开始找

3. indexOf / lastIndexOf / include

作用 : 验证字符是否存在
params :
indexOf ( x , y ) : 验证x第一次出现位置的索引 , y是控制查找的起始位置索引 lastIndexOf ( x , y ) : 验证x第一次出现位置的索引 , y是控制查找的起始位置索引
return : 返回字符出现位置的索引 ,没有这个字符, 返回的结果是 -1
原字符串: 值类型,直接按值操作, 不会对原值产生影响

字符串的indexOf / lastIndexOf 兼容全部浏览器 数组的不兼容 IE6-8

  1. 应用:
    let str = 'zheshiyigezifuchuan';
    console.log(str.indexOf('h')); // => 1
    console.log(str.lastIndexOf('h')); // => 15
    // 不存在 返回 -1
    console.log(str.indexOf('@')); // => -1
    console.log(str.lastIndexOf('@')); // => -1
    if(!str.includes("@")){
    console.log('当前字符不包含@'); //=> '当前字符不包含@'
    }
  1. 验证一串字符整体第一次出现, 返回的索引是这个字符串整体中第一个字符所在位置的索引值

    如果不存在, 也返回 -1

    console.log(str.indexOf('shi')); // => 3
    console.log(str.indexOf('sshi')); // => -1
  1. 第二个参数的应用

    查找字符串索引m及之后的字符串中,n第一次出现的位置

    console.log(str.indexOf('h',7)); // => 15
    查找字符串索引7及之后的字符串中,n第一次出现的位置

4. toUpperCase / toLowerCase

作用 : 字符串中字母大写转换 / 小写转换
params : 无 return : 转换后的字符串

应用:

    let str = 'zheshiyigezifuchuan'
    str = str.toUpperCase();
    console.log(str); //=> ZHESHIYIGEZIFUCHUAN
    str = str.toLowerCase();
    console.log(str); // => zheshiyigezifuchuan

需求: 首字母大写

str.substr(0,1).toUpperCase()+str.substr(1)

5. split ([ 分隔符 ] )

作用 : 把字符串按照指定的分隔符拆分成数组 (和数组中的join相对应)
params : 分隔符
return : 新数组
split支持传递正则表达式

应用: 竖线分隔符变为逗号分隔符 数据类型不变

    let str = 'music|movie|eat|sport';
    let ary = str.split('|');
    console.log(ary); //=>  ['music', 'movie', 'eat', 'sport']
    // 然后变成用逗号相连的字符串
    str = ary.join(',');
    console.log(str); // => 'music,movie,eat,sport'

6. replace ( )

作用 : 实现字符串的替换 (经常伴随正则应用)
params : replace ( 老字符 , 新字符 ) return : 新字符串 在不适用正则表达式的情况下,执行一次REPLACE只能替换一次字符

无正则:

    let str = '我@喜欢@可乐@';
    str = str.replace('@','~')
    console.log(str); // => 我~喜欢@可乐@

搭配正则:

    let str = '我@喜欢@可乐@';
    str = str.replace(/@/g,'~')
    console.log(str); // => 我~喜欢~可乐~

后续: match localCompare trim/trimLeft/trimRight ...

控制台输出String.prototype输出所有字符串方法

实现一些常用的需求 项目7 字符串方法项目