Skip to content

3 内置对象与正则

约 1130 个字 125 行代码 预计阅读时间 5 分钟

1 Array

不同于普通对象使用 String 作为属性名,数组使用 Number 作为索引对元素进行操作

  • Index 从 0 开始
  • 数组中的元素可以是任意数据类型( String / Object),且允许同时存在多种数据类型
    arr = ["hello", 1, {}, null, undefined, function(){}, [1,2,3]];
    
  • 数组的存储性能比普通对象好,所以一般用来存数据

1.1 基本操作

  • 创建数组

    var arr1 = new Array(10, 20, 30); // typeof arr 将返回 Object(顺便初始化)
    var arr2 = [1,2,3,4];             // 使用字面量形式创建(顺便初始化)
    
    // 小小的区别
    var arr3 = [10];          // 只有一个元素 10 的数组
    var arr4 = new Array(10); // 长度为 10 的空数组
    

  • 向数组中添加元素

    arr[0] = 10;             // 将首位置为 10
    arr[arr.length] = value; // 始终向末尾插入元素
    

  • 读取数组中的元素

    console.log(arr[1]);
    // 读取不存在的索引会返回 undefined(不报错)
    

  • 获取数组长度

    console.log(arr.length); // 适用于「连续数组」
    // 跳着插入会返回 max(index) + 1
    

  • 修改数组长度

    arr.length = newLength;
    // newLen > oldLen 多出来的部分会插入空值(打印一堆 ,)
    // newLen < oldLen 多余部分被截断
    

1.2 基本方法

  1. push

    向数组「末尾」添加 >= 1 个元素,返回新的数组长度

     arr.push("hello", 1, null); // 多个元素之间使用 , 进行分隔
    
  2. pop

    删除数组的「最后一个元素」,返回「被删除的元素」

    arr.pop();
    
  3. unshift

    向数组「开头」添加 >= 1 个元素(其余元素依次后移),返回新的数组长度

     arr.unshift("hello", 1, null); // 多个元素之间使用 , 进行分隔
    
  4. shift

    删除数组的「首个元素」,返回「被删除的元素」

    arr.shift();
    
  5. slice

    从已有数组截取子串,返回截取结果形成的数组(不改变原数组)

    • arrObj.slice(start, [end]) 实际截取 [start, end)区间
    • 省略 end 时,截取从 start 开始的所有元素
    • start / end 可以传递负值(自后向前以 -1 ~ -len 进行编号)
    var arr = [0, 1, 2, 3, 4, 5];
    arr.slice(1,3);    // => [1,2]
    arr.slice(4);      // => [4,5]
    arr.slice(3, -1);  // => [3,4]
    arr.slice(-3, -1); // => [3,4]
    // 但 slice(-1, -3) 会返回空数组 []
    
  6. splice

    删除并添加新元素,返回删除元素构成的数组(会影响原数组)

    • arrObj.splice(start, len, [newVal1, new Val2, ...]) ,删除从 start 位置开始的 len 个元素
    • 可以认为是用 [newVal1, new Val2, ...] 替换了 arr[start, start+len] 的数组元素
    var arr = [0, 1, 2, 3, 4, 5];
    arr.splice(1, 2); // => [1,2] 
    arr.splice(1, 1, "hello", "world"); 
    // => arr = [0, 'hello', 'world', 2, 3, 4, 5]
    
  7. concat

    连接 >= 2 个数组,并返回合并结果(不修改原数组)

    var arr1 = [1,2];
    var arr2 = [3,4];
    var arr3 = [5,6];
    var arr = arr1.concat(arr2, arr3); // => arr1 本身不发变换
    // arr = [1,2,3,4,5,6]
    
    arr1.concat(arr2, "hello", "world"); // 这样也行
    
  8. join

    返回数组转换为 String 的结果(不修改原数组)

    var arr = [1,2,3,4,5,6];
    console.log(arr.join()); // => 1,2,3,4,5,6 (type = String)
    
    // 我们可以指定 String 作为元素间的连接符(默认是 ,)
    arr.join("--"); // => 1--2--3--4--5--6
    
  9. reverse

    返回反转数组(影响原数组)

    var arr = [1,2,3];
    arr.reverse(); // 现在 arr = [3,2,1]
    
  10. sort

    对数组元素进行排序(影响原数组)

    • 默认按照 Unicode 升序排序(对 Number 的支持有问题:11 < 2)
    • 希望获得降序数组可以先 arr.sort() ,再 arr.reverse()
    • 支持自定义规则(下面是一个对 Number 排序规则覆写的例子)
    var arr = ["a", "d", "e", "b", "c"];
    arr.sort(); // arr = ["a", "b", "c", "d", "e"]
    
    var arrNum = [5, 11, 2, 34, 24];
    arrNum.sort(function(a, b) {
        // 返回 >0 的值,则交换 (a,b) 的位置
        // 返回 <=0 的值,保持元素位置不变
        return a-b; // 升序
        return b-a; // 降序
    })
    

1.3 遍历数组

  • 使用 For 循环

    for(let i=0; i<arr.length; i++) {
        console.log(arr[i]);
    }
    

  • 使用 forEach 方法

    arr.forEach(item => { // 仅支持 IE8 以上的浏览器,item 是当次遍历得到的元素
        console.log(item);// 回调函数体(有几个元素就执行几次)
    })
    // 完整情况下会传递三个参数
    arr.forEach(function(item, index, arrObj) {
        // 当前元素,当前下标,正在遍历的数组
    })
    

1.4 练习 - 数组去重

var arr = [1,2,3,2,1,4,5,4];
// 获取数组中的每一个元素
for(let i=0; i<arr.length; i++) {
    // 检查 i 以后是否存在与当前元素重复的内容
    for(let j=i+1; j<arr.length; j++) {
        if(arr[i]==arr[j]) { // 删后面的
            arr.splice(j,1);
            // (连续两个重复会漏删 -> 前移了)
            j--; // 重复 check 当前位置
        }
    }
}

2 Date

  • 创建一个 Date 对象

    • 允许以 mm/dd/yyyy / mm/dd/yyyy hh:mm:ss 进行初始化
    var d1 = new Date();            // 直接调用 -> 封装代码执行时间(当前时间)
    var d2 = new Date("12/03/2010");// 传入字符串,指定时间
    
  • 获取基本信息

    d.getDate();     // 返回日期   1-31
    d.getDay();      // 返回星期几 0-6
    d.getMonth();    // 返回月份   0-11
    d.getFullYear(); // 返回 YYYY
    ---
    d.getHours();       // 小时 0-23
    d.getMinutes();     // 分钟 0-59
    d.getSeconds();     // 秒   0-59
    d.getMiliseconds(); // 毫秒 0-999
    ---
    d.getTime(); // 获取时间戳:从1970/01/01 00:00:00 经过的「毫秒」数(有负数)
    time = Date.now(); // 获取「改行代码执行时」的时间戳
    

3 Math

不同于其他对象,Math 不是一个构造函数(不能 new),而是一个「工具类」

3.1 属性 - 一些常量

属性 描述
E 常量 \(e = 2.718\)
LN2 \(ln(2) = 0.693\)
LN10 \(ln(10)=2.302\)
LOG2E \(log_2(e) = 1.414\)
LOG10E \(log_{10}(e) = 0.434\)
PI \(3.14159\)
SQRT1_2 \(\frac{1}{\sqrt{2}} =0.707\)
SQRT2 \(\sqrt{2}=1.414\)

3.2 方法

  • Math.abs(x) 绝对值
  • Math.exp(x) 返回 \(e^x\)
  • Math.pow(x, y) 返回 \(x^y\)
  • Math.floor() / Math.ceil() 向下/向上 取整
  • Math.max(x,y, ...) / Math.min(x,y, ...) 多个数中的 最大 /最小 值
  • Math.random() 0-1 的随机数
    // 生成 [n-m] 的整数
    function rand(n, m) {
        return Math.random() * (m-n) + n;
    }
    
  • Math.round() 四舍五入
  • Math.sqrt() 开方

4 正则表达式

检查 String 是否符合特定规则 / 提取符合规则的子串

学完编译原理回来感觉神清气爽 🤡

  • 创建正则表达式对象

    • 匹配模式选项
      • i - 忽略大小写
      • g - 全局匹配
    var reg1 = new RegExp("Regular Expression", "匹配模式");// 可以传入变量
    var reg2 = /RegularExpression/匹配模式;                 // 使用字面量形式创建
    
  • 检测 String 是否符合正则表达式规则(返回 Boolean)

    // 使用 test() 方法
    console.log(reg.test("Str to be tested"))
    

正则语法

  • OR

    • str1 | str2 包含 str1 或 str2
    • [ab] 包含 'a' 或 'b'
    • [a-z] 包含小写字母
    • [A-z] 包含任意字母(注意大小写和顺序)

    例子:是否包含 'abc' / 'adc' / 'aec', / abc | adc | aec / 不够优雅 => / a[bde]c /

  • NOT

    [^ab] 表示除 'a', 'b' 以外的所有字符

  • 量词:指定内容重复出现次数

    语法 描述 示例
    x{n} 字符 x 正好出现 n 次 /a{3}/ === /aaa/
    x{m,n} 字符 x 出现 [m,n] /a[1-3]/ === / a | aa | aaa /
    x{m,} 字符 x 出现 >= m
    (str){n} 字串 str 正好出现 n 次 /(ab){2}/ === abab
    x+ 出现 >=1
    x* 出现 >=0
    x? 出现 0 / 1
  • 以指定串开头:/^a/ === a****...;

  • 以指定串结束:/a$/ === ****...a;
  • 同时使用两者进行全等匹配 /^a$/ === "a"

  • 匹配以 a 开头或结尾的字符串 /^a | a$/

  • 转义字符

    特殊字符 描述
    \w 任意字母、数字、下划线
    \W \w 以外的所有字符
    \s 空格
    \S 除空格以外的内容
    \b 单词边界: /\bchildern\b/ 匹配 child,不匹配 children
    \B 除单词边界以外的部分
    \d [0-9]
    \D [^0-9]

String 中的相关方法

  • split() - 根据“任意字母”拆分字符串

    // 传递 String 只能根据固定内容进行拆分,此处我们传递正则表达式
    var str = "1j2d3k456j7";
    var res = str.split(/[A-z]/); // 不指定全局也会全拆开
    // res = [1,2,3,456,7]
    
  • search() - 搜索字符串中是否包含指定内容,返回首次出现的起始下标(不存在时返回-1)

    var str = "helloabctype";
    console.log(str.search("abc")); // 返回 5
    // 也可以接受一个正则表达式作为参数(无论是否设置全局匹配)
    str.search(/a[bef]c/); // 是否存在 abc/aec/afc
    
  • match() - 返回所有符合正则表达式的子串构成的数组

    var str = "1j2d3k456j7";
    var res = str.match(/[A-z]/); // 默认情况下只找第一个,此时 res = ["j"]
    // 可以通过设置“全局匹配”模式查找所有内容
    var res = str.match(/[A-z]/g); // res = ["j","d","k","j"]
    // 可以同时设置 全局+不区分大小写(顺序无所谓)
    var res = str.match(/[a-z]/gi); // 也是匹配所有大小写字母(单个)
    
  • replace(old, new) - 返回将符合规则的子串替换为新的内容的结果(不影响原串)

    var ini = "aba";
    var res = ini.replace("a", "@_@"); // => @_@ba(只替换第一个)
    
    // 使用正则进行全局替换
    var res = ini.replace(/a/g, "@_@"); // => @_@b@_@(替换所有)
    

练习

检验合法手机号

1 开头,第二位不为 0,1,2 的 11 位纯数字

var phoneReg = /^1[^012][0-9]{9}$/; // 用[3-9]校验第二位也行

检验是否包含 .

因为 . 本身匹配任意「单个」字符(除 \n),所以需要转义

var reg = /\./; // 转义为普通字符 '.'
var reg = new RegExp("\\."); // 使用构造函数时,需要用 \\ 进行转义
// 下面尝试匹配单个 \
var reg = /\\/;
var reg = new RegExp("\\\\"); // 两个转成一个*2次

去除用户输入中的「首尾」连续空格

就使用空串去替换

str = str.replace(/^\s* | \s*$/g, "");

电子邮件

字母/数字/下划线.字母/数字/下划线@字母数字.2-5个字母.2-5个字母

var EmailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;