严格模式、错误类型、解构赋值、正则

一、严格模式

js 的默认执行模式是松散模式,为了规范 js 这门语言,所以引入了严格模式;目的是为了消除 js 的一些怪异行为;

  • 使用严格模式:在 js 脚本中第一行增加 字符串 “use strict”

严格模式下和普通模式下的常见区别

  1. 在严格模式下形参 和 arguments 没有映射关系

在松散模式中,形参和 arguments 有映射关系,如果在函数中修改形参,那么 arguments 中的对应的值也会跟着修改

  1. function sum(a, b) {
  2. b = 100; // 普通松散模式中
  3. console.log(arguments); // 1 100
  4. }
  5. sum(1, 3);

严格模式中,形参和 arguments 不存在映射关系

  1. 'use strict';
  2. function sum2(a, b) {
  3. b = 100;
  4. console.log(arguments); // 1 2
  5. }
  6. sum2(1, 2);

项目中使用 webpack 工具打包编译时,会在 js 脚本头部指定严格模式

  1. 严格模式下的 this 问题
  • 非严格模式下的 call:
  1. function f0() {
  2. console.log(this);
  3. }
  4. var obj = {
  5. id: 1
  6. };
  7. f0.call(obj); // this -> obj
  8. f0.call(); // this -> window
  9. f0.call(undefined); // -> window
  10. f0.call(null); // window
  • 严格模式下,call 方法不指定 this 时函数中的 this 就是 undefined
  • 严格模式下 call 指定谁,谁就是 this
  1. 'use strict';
  2. function f1() {
  3. console.log(this);
  4. }
  5. f.call(); // this -> undefined
  6. f1.call(undefined); // this -> undefined
  7. f1.call(null); // this -> null
  1. 严格模式下,不能直接给未声明的变量赋值
  1. 'use strict';
  2. aa = 123; // 非严格模式下给 window 增加属性
  3. aa = 123; // 严格模式下报错: Uncaught Reference:aa is not defined

二、手动抛出错误

  • throw 关键字 用于手动抛出错误
  1. throw 'hello world';
  2. console.log(123); // 不会输出,因为 throw 关键字抛出的是错误,js 一旦抛出错误后就会停止后面的代码执行;
  1. 常见的错误类型
  • 2.1. ReferenceError 引用错误 引用了不存在的变量
  1. throw new ReferenceError('某个变量未找到');
  • 2.2 TypeError 类型错误 错误使用类型
  1. throw new TypeError('你搞错类型了');
  • 2.3 SyntaxError 语法错误
  1. throw new SyntaxError('你的语法错误');
  • 2.4 Error 普通错误
  1. throw new Error('这是一个普通错误');

三、解构赋值

利用数据结构的对应关系快速对数组和对象进行取值;

1. 数组解构赋值:

等号左边的变量的位置和等号右边的数组中值位置相同时,变量可以取得数组中该位置的值;

  • 1.1 顺序解构:
  1. let ary = [10, 50, 100, 200];
  • 没有解构赋值时
  1. let a = ary[0];
  2. let b = ary[1];
  3. let c = ary[2];
  4. console.log(a, b, c);
  • 使用解构赋值
  1. let [a, b, c] = ary; // 等号左边是变量等号右边是数组,要求变量在等号边的位置和想取出的值的索引位置相同
  2. console.log(a, b, c);
  • 1.2 取数组中的某一个:
  1. let [,, d] = ary; // 如果只想得到第三个,前面两个空着,但是需要写两个 ,
  2. console.log(d);
  • 1.3 取出第一项和第二项,剩余的统一放到一个数组中;
  1. let [e, f, ...arr] = ary;
  2. console.log(e); // 10
  3. console.log(f); // 50
  4. console.log(arr); // [100, 200]
  • 1.4 进一步解构:
  1. let ary2 = [10, ['a', 'b']];
  2. let [g, [h, i]] = ary2;
  3. console.log(g); // 10
  4. console.log(h); // 'a'
  5. console.log(i); // 'b'
  • 1.5 数组解构默认值:只有解构出来的值是 undefined 时默认值才会生效
  1. let ary3 = [1, 3];
  2. let [j = 2, k = 3, l = 100] = ary3; // j 的默认值是2,k 的默认值是3,l 的默认值是100
  3. console.log(j); // 1
  4. console.log(k); // 3
  5. console.log(l); // 100
  6. // 把a当做b的默认值
  7. let [a, b = a] = [1];
  8. console.log(a); // 1
  9. console.log(b); // 1

2. 对象的结构赋值

通常情况下获取一个对象的属性值是通过对象.属性名 或者 对象[‘属性名’]
而对象的解构赋值就是通过变量和对象的属性对应时,就可以取得对象的改属性名的值

  1. let obj = {
  2. name: '珠峰',
  3. age: 10
  4. }
  • 2.1解构赋值:
  1. let { name, age } = obj;
  2. console.log(name);
  3. console.log(age);
  • 2.2 如果只想要对象的某一个属性值:
  1. let obj2 = {
  2. name: '珠峰',
  3. age: 10,
  4. courses: ['js前端', '珠峰架构', 'UI设计师']
  5. };
  6. let {courses} = obj2;
  • 2.3 进一步解构:
  1. let obj3 = {
  2. name: 'zhufeng',
  3. teacher: {
  4. js: ['马宾', '牛晓鑫', '....'],
  5. architect: ['']
  6. }
  7. };
  8. let { teacher: { js } } = obj3;
  9. console.log(js); // 获取 obj3.teacher.js 的值
  • 2.4 重命名:为了避免重复声明
  1. let obj4 = {
  2. title: '高级前端工程师'
  3. };
  4. let title = 100;
  5. // let { title } = obj4; // 如果直接这样解构,相当于重复声明了 title 变量
  6. let { title: title2 } = obj4; // 从 obj4 中解构 title 属性,并且重命名为 title2
  7. console.log(title2);
  • 2.5 解构赋值的默认值:只有解构出来的值是 undefined 时默认值是才会生效
  1. let obj5 = {
  2. name: '马宾',
  3. age: 18,
  4. job: 'FE',
  5. // address: undefined
  6. };
  7. let { address = '河北' } = obj5; // 设置 address 解构赋值的默认值是 '河北';
  8. console.log(address);
  9. // 3. 字符串解构赋值
  10. let [x, y, z] = 'hello';
  11. console.log(x, y, z);

4. 函数参数的解构赋值

  1. function fe({ name: nike, id, num = '18332567506'}) {
  2. // 把 fe 执行时传递过来的实参进行解构
  3. console.log(nike, id, num);
  4. }
  5. fe({
  6. name: 'zhangsna',
  7. id: 10
  8. });

5. 对象的简洁语法

  1. let config = '110.156.23.24';
  2. let pwd = '4323445';
  3. let obj6 = {
  4. config: config,
  5. pwd: pwd
  6. };
  7. // 当你的属性名和变量名一样时,就可以简写为一个变量名
  8. let obj7 = {
  9. config,
  10. pwd,
  11. };

练习:

  1. let response = {
  2. code: 0,
  3. data: {
  4. list: [
  5. {
  6. name: 'a',
  7. age: 1
  8. },
  9. {
  10. name: 'b',
  11. age: 2
  12. }
  13. ],
  14. page: 1,
  15. total: 100
  16. }
  17. };
  18. // 使用解构赋值取出 response.list, response.page, response.total
  19. let { data: { list, page, total } } = response;
  20. console.log(list);
  21. console.log(page);
  22. console.log(total);

正则

正则:(RegExp:Regular Expression)

专门用来处理字符串的规则,这个处理包含两方面的:

  1. 正则匹配,判断某一个字符串是否符合规则
  2. 正则捕获,把符合规则的字符串捕获到;
  • 学习正则学习编写一个正则:
  1. let reg = /\d/img; // 字面量方式创建
  2. let reg0 = new RegExp('\\d+', 'img'); // 实例的方式创建

正则的构成:元字符和修饰符

元字符
  • 特殊元字符
    • \d 匹配0-9中的任意一位数字
    • \D 匹配除了0-9数字以外的任意字符
    • \w 匹配数字、字母、_ 中的任意一个字符串
    • \s 匹配一个空白符(空格、\t制表符)
    • \b 匹配单词的边界 ‘zhu-feng’ z的左侧,u的右侧,f左侧,g的右侧都是边界
    • \n 匹配一个换行符
    • . 不是小数点,是匹配除 \n 以外的任意字符串
    • \ 转义符,将普通的字符串转义成特殊的元字符,例如\d 就表示 0 -9 之间的字符串;还可以将特殊的元字符转义成普通元字符。如 . 不再表示除 \n 以外的任意字符,而是表示普通小数点
    • ^ (读作caret符)表示以某个元字符开头
    • $ 表示以某个元字符结尾
    • x | y 表示x或者y中的任意一个
    • [xyz] 表示x/y/z 中的任意一个
    • [a-z] a-z 中的任意一个字母
    • [0-9] 0-9中的任意一个数字
    • [^a-z] 除了a-z以外的任意字符
    • () 正则分组
    • (?:) 当前分组值匹配不捕获
    • (?=) 正向预查
    • (?!) 负向预查
  • 量词元字符:表示出现次数的元字符
      • 出现 0次到多次
    • ? 出现0次到1次
    • {n} 出现n次
    • {n, m} 出现n次到m次
    • {n,} 至少出现n次
  • 普通元字符:只要在正则中出现,(基于字面量的方式创建),除了有特殊元字符和量词元字符以外,其余的都是普通元字符。
  • 修饰符:
    • i: ignorecase 忽略大小写
    • m: multiline 多行匹配
    • g: global 全局匹配

示例:

  1. let reg2 = /\D/;
  2. console.log(reg2.test('2')); // false
  3. console.log(reg2.test('a')); // true
  4. console.log(reg2.test('_')); // true
  5. let reg3 = /\w/;
  6. console.log(reg3.test('1')); // true
  7. console.log(reg3.test('a')); // true
  8. console.log(reg3.test('_')); // true
  9. console.log(reg3.test('A')); // true
  10. let reg4 = /\n/;
  11. console.log(reg4.test(`
  12. `)); // true 模板字符串中输入了一个回车
  13. let reg5 = /\s/;
  14. console.log(reg5.test(' ')); //true
  15. console.log(reg5.test(' ')); // true
  16. let reg6 = /\b/;
  17. console.log(reg6.test('zhu-feng'));
  18. let reg7 = /./;
  19. console.log(reg7.test('我')); // true
  20. console.log(reg7.test('x')); // true
  21. console.log(reg7.test('12')); // true
  22. console.log(reg7.test('\n')); // false
  23. let reg8 = /^\d/;
  24. console.log(reg8.test('1abc')); // true
  25. console.log(reg8.test('x23c')); // false
  26. let reg9 = /\d$/;
  27. console.log(reg9.test('hell9')); // true
  28. console.log(reg9.test('123hello')); // false
  29. let reg10 = /^\d$/; // 匹配一个数字,这个数字既是开头也是结尾;就是说这个字符串中只能有一个数字
  30. console.log(reg10.test('9')); // true
  31. console.log(reg10.test('99')); // false
  32. console.log(reg10.test('abc1')); // false
  33. console.log(reg10.test('1xyz')); // false
  34. let reg11 = /a|b/;
  35. console.log(reg11.test('a')); // true
  36. console.log(reg11.test('b')); // true
  37. console.log(reg11.test('ab')); // true
  38. let reg12 = /[a-z]/;
  39. console.log(reg12.test('a')); // true
  40. console.log(reg12.test('z')); // true
  41. console.log(reg12.test('xyz')); // true
  42. console.log(reg12.test('A')); // false
  43. let reg13 = /[^0-9]/;
  44. console.log(reg13.test('8')); // false
  45. console.log(reg13.test('ABC')); // true
  46. console.log(reg13.test('\n')); // true
  47. console.log(reg13.test('_')); // true
  48. let reg14 = /\d*/;
  49. console.log(reg14.test('abc')); // true
  50. console.log(reg.test('12133bade')); // true
  51. let reg15 = /\d?/;
  52. console.log(reg15.test('dsjf8lkk')); // true
  53. let reg16 = /\d{3}/;
  54. console.log(reg16.test('666')); // true
  55. console.log(reg16.test('22')); // false
  56. console.log(reg16.test('111')); // true