• 第八课之提高开发效率的es6以及函数


    es6的介绍

    2011 年,ECMAScript 5.1 版发布后(es5),就开始制定 6.0 版了,ECMAScript 2015(简称 ES2015),ES6 的第一个版本,在 2015 年 6 月发布了。因此,ES6 这个词的原意,就是指 JavaScript 语言的下一个版本,涵盖了 ES2015、ES2016、ES2017 等等

    ES6中包含了许多新的语言特性,它们将使JS变得更加强大,更富表现力。对于很多开发者来说,ES6带来的新功能涵盖面很广,还有很多很便利的功能等(如:箭头的功能和简单的字符串插值),确实令人兴奋。

    es6常用语法

    let

    ES6新增了let命令,用来生命变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

    变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。
    每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),
    里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,
    指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10
    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 10  
    
    闭包
    
    如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。
    
    var a = [];
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 6
    

    const

    const声明一个只读的常量,一旦声明,常量的值就不能改变。

    const a = 1;
    a = 2; // 报错
    
    const b = {};
    a = {a:1}; // 报错
    
    const c = {c:1};
    c.c = 2; // 不报错
    
    // 简单理解,改变对象值,改变数组索引的值都不会报错,但是如果直接修改自身数值就会报错
    

    let与const

    1.都不能重复声明

    2.都存在块级作用域问题

    3.只在声明所在的块级作用域内有效

    开发使用

    所有的变量都用let进行定义,所有的常量都是用const进行定义

    解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构

    • 对象解构赋值
    // 1.获取键值
    let obj ={ name:"abc",age:18 };
    
    // 以前的写法
    let name = obj.name;
    let age = obj.age;
    
    //用解构赋值的方式获取name、age
    let { name, age } = obj; //创建了一个变量name,值=obj.name
    console.log(name,age);  //"abc" 18
    
    // 2.重命名(比如想要获取数据的变量和我们已有的变量重名,就需要进行重命名)
    let { name: n, age: a } = obj;
    console.log(n,a);  //"abc" 18
    
    // 3.解构再解构
    let jsonData = {
      id: 42,
      status: "OK",
      data: {list:[],total:1000}
    };
    
    let { id, status, data: {list,total} } = jsonData;
    
    console.log(id, status, list,total);
    // 42 "OK" [] 1000 不过这个时候就不能访问到data了
    
    • 数组解构赋值
    // 获取对应索引下的值
    let data= [1,2,3];
    
    // 以前的写法
    let a = data[0];
    let b = data[1];
    let c = data[2];
    
    // 现在的写法,如果对不上,值就是undefined
    let [a, b, c] = [1, 2, 3];
    console.log(a,b,c);
    
    • 字符串解构赋值
    const [a, b, c, d, e] = 'hello';
    console.log(a) // "h"
    console.log(b) // "e"
    
    • 函数参数解构赋值
    function f1(obj){
        console.log(obj.age);
        console.log(obj.height)
    }
    //等价于
    function f1({ age,height }){
        console.log(age);
        console.log(height)
    }
    
    f1({age:5,height:180})
    
    // 数组解构
    function f2([ a,b ]){
        console.log(a);
        console.log(b)
    }
    f2([1,2])
    
    • 默认值
    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    let [x, y = 'b'] = ['a', null]; // x='a', y=null
    
    // 注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效,null和0均不生效
    
    

    模板字符串

    // 用法:使用``包裹字符串,变量使用${}
    let s1 = 3, s2 = 4;
    let s4 = ` a ${s1 === 1 ? '1' : '2'} b ${s2}`;
    console.log(s4);
    const basket = { count: 111, onSale: 2222 };
    // 以前的js拼接写法
    // document.getElementById('content').innerHTML =
    //   'There are <b>' + basket.count + '</b> ' +
    //   'items in your basket, ' +
    //   '<em>' + basket.onSale +
    //   '</em> are on sale!';
    
    // 现在js拼接写法(所有模板字符串的空格和换行,都是被保留的)
    document.getElementById('content').innerHTML = `
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!`;
    

    替换

    // 只能替换第一个
    'aabbcc'.replace('b', '_')
    // 使用正则进行替换所有
    'aabbcc'.replace(/b/g, '_')
    
    // 现在可以使用replaceAll来替换所有
    'aabbcc'.replaceAll('b', '_')
    

    箭头函数

    ES6 允许使用“箭头”(=>)定义函数。

    使用注意点

    箭头函数有几个使用注意点。

    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

    (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

    //匿名函数
    // div.onclick = function () {
    //   console.log("你好")
    // }
    // //箭头函数
    // div.onclick = () => {
    //   console.log("你好")
    // }
    
    var f = () => 5;
    // 等同于
    var f = function () { return 5 };
    f();
    
    // 报错
    // let getTempItem = id => { id: id, name: "Temp" };
    // 不报错,直接对象、数组返回需要用()包裹
    let getTempItem = id => ({ id: id, name: "Temp" });
    console.log(getTempItem(123));
    // 正常函数写法
    let arr = [{ id: 1 }, { id: 2 }, { id: 3 },];
    // arr.map(function (x) {
    //   x.id = x.id * x.id;
    // });
    
    // 箭头函数写法
    arr.map(x => (x.id = x.id * x.id));
    console.log(arr);
    
    

    扩展运算符

    扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

    // 1.修改对象数据
    let obj = { pageIndex: 1, pageSize: 10 }
    let values = { pageSize: 20 };
    // 以前的写法
    obj.pageSize = values.pageSize;
    // let payLoad = obj;
    // 现在的写法
    let payLoad = { ...obj, ...values };
    console.log(payLoad);
    
    // 2.合并数组
    // ES5的 写法
    // var arr1 = [0, 1, 2];
    // var arr2 = [3, 4, 5];
    // Array.prototype.push.apply(arr1, arr2);
    // console.log(arr1);
    
    // ES6 的写法
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    // arr1.push(...arr2);
    arr1 = [...arr1, ...arr2];
    console.log(arr1);
    
    // 3.与解构结合,并且扩展运算符只能放在最后
    const [first, ...rest] = [1, 2, 3, 4, 5];
    console.log(first) // 1
    console.log(rest)  // [2, 3, 4, 5]
    
    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    console.log(x) // 1
    console.log(y) // 2
    console.log(z) // { a: 3, b: 4 }
    
    // 4. 克隆合并对象
    let a = { name: '123', age: 456 };
    let aClone = { ...a };
    console.log(aClone);
    // 等同于
    // let aClone = Object.assign({}, a);
    // console.log(aClone);
    
    let b = { name: '1233', age: 4567 };
    // let ab = { ...a, ...b };
    // 等同于
    let ab = Object.assign({}, a, b);
    console.log(ab);
    
    

    数组的扩展

    // 1,find:用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
    
    let arr = [1, 4, -5, 10].find((n) => n < 0)
    console.log(arr);
    
    // 2.findIndex:用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
    let arr = [1, 5, 10, 15].findIndex(function (value, index, arr) {
      return value > 9;
    })
    console.log(arr);
    
    // 3.includes:判断元素是否存在 返回true/false
    let arr = [1, 5, 10, 15].includes(5);
    console.log(arr);// true
    
    // 4.filter:按条件进行数组过滤
    var arr = [20, 30, 50, 96, 50]
    var newArr = arr.filter(item => item > 40)
    console.log(newArr)
    
    // 5.every:判断数组中是否每个age都大于22
    let arr = [{name: 'Tom',age: 22},{name: 'Sun',age: 23},{name: 'Mack',age: 25,sex: '男'}];
    let newArr = arr.every(item => item.age > 22)
    console.log(newArr)
    
    
    // 6.some:判断数组中是否某个age都大于22
    let newArr = arr.some(item => item.age > 22);
    console.log(newArr);
    
    // 7.reduce:处理数组,适用于求和、求乘积
    var  arr = [1, 2, 3, 4];
    var sum = arr.reduce((x,y)=>x+y)
    var mul = arr.reduce((x,y)=>x*y)
    console.log( sum ); //求和,10
    console.log( mul ); //求乘积,24
    
    // 8.map:方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
    let data = [1, 2, 3, 4, 5]
    let nowData = data.map(item => (item = 2));
    console.log(nowData, data);
    

    对象的扩展

    // 1.对象赋值
    const foo = 'bar';
    const baz = {foo}; // {foo: "bar"}
    
    // 2.数组key值使用变量
    let lastWord = 'last word';
    
    const a = {
      'first word': 'hello',
      [lastWord]: 'world'
    };
    
    a['first word'] // "hello"
    a[lastWord] // "world"
    a['last word'] // "world"
    
    

    Promise

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大

    Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)

    // 输出:1 2 3(Promise 新建后立即执行,所以首先输出的是1。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以输出2,resolved3最后输出。)
    const promise = new Promise(function (resolve, reject) {
      console.log(1);
      if (true) {
        setTimeout(() => {
          resolve(3);
        }, 1000);
      } else {
        reject(error);
      }
    });
    console.log(2);
    promise.then(function (value) {
      console.log(value);
      return value;
    }, function (error) {
    });
    
    // Promise.all:3秒后输出promise1 promise2
    const promise1 = new Promise(function (resolve, reject) {
      setTimeout(() => {
        resolve('promise1');
      }, 1000);
    });;
    const promise2 = new Promise(function (resolve, reject) {
      setTimeout(() => {
        resolve('promise2');
      }, 3000);
    });
    
    // 所有异步方法成功之后才会执行,如果有一个返回rejected则会返回rejected
    Promise.all([
      promise1,
      promise2
    ]).then(([res1, res2]) => {
      console.log(res1, res2);
    });
    

    Async

    async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

    // 正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
    async function f() {
      return 'hello world';
    }
    
    f().then(v => console.log(v))
    // "hello world"
    
    
    function timeout(value) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(value);
        }, 3000);
      });
    }
    
    async function asyncPrint(value) {
      console.log(1111);
      let nowValue = await timeout(value);
      console.log(nowValue);
      console.log(222);
    }
    
    asyncPrint('3333',);
    

    import export

    ES6模块功能主要有两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

    • export
    // 1. 直接输出变量(方法、类)
    export var m = 1;
    export function multiply(x, y) {
      return x * y;
    };
    
    // 2. 使用大括号指定所要输出的一组变量(方法、类)
    var m = 1;
    export { m };
    
    // 3. as关键字重命名
    // 重命名后,v2可以用不同的名字输出两次
    function v1() { ... }
    function v2() { ... }
    export {
      v1 as streamV1,
      v2 as streamV2,
      v2 as streamLatestVersion
    };
    
    • import
      使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同。
    // 1. 引入变量(方法、类)-(逐一加载),引入的名字要和导出的名字相同
    import { firstName, lastName, year } from './profile.js';
    
    // 2. as关键字重命名
    import { lastName as surname } from './profile.js';
    
    // 3. 整体加载
    import * as circle from './circle';
    
    • export default

    export default就是输出一个叫做default的变量或方法,系统允许自定义命名

    // 默认输出一个函数
    function getName() {
      console.log('foo');
    }
    export default getName;
    // 引用并指定名字(可以按别的名字命名)
    import customName from './export-default';
    

    前端调试

    前端js调试是前端开发学习最为关键的一个环节,熟练地代码调试可以大大减少问题查找时间

    方式一

    使用console.log()

    方式二

    使用alert()

    方式三

    可在任意想要调试的地方加上debugger(就是我们常说的打断点)

    方式四

    谷歌浏览器的source里面打断点,ctrl+p 查找对应的js,找到想要调试的代码打断点

    F8 相当于后端的 F5
    F10 F11和后端调试功能类似(F11很少用)
    

    前端js常用功能

    操作数组

    /* 操作数组的常用方法: */
    var arr = [10, 20];
    /* [1] 在数组的后面添加元素  arr.push(ele1,ele2...) */
    arr.push(30);
    arr.push(40, 50, 60);
    console.log(arr);
    
    /* [2] 在数组的前面添加元素  arr.unshift(ele1,ele2...)*/
    var arr = [10, 20];
    arr.unshift(3);
    arr.unshift(88, 888);
    console.log(arr);
    
    /* [3] 删除数组中最后一个元素 */
    var arr = [10, 20];
    arr.pop();
    console.log(arr);
    
    /* [4] 删除数组中第一个元素 */
    var arr = [10, 20];
    arr.shift();
    console.log(arr);
    
    /* [5] 合并数组的方法 */
    /* 语法:arr.concat(ele1|arr,ele2...) */
    var arr1 = ["熊大", "熊二"];
    var arr2 = ["佩琪", "乔治"];
    var arr3 = arr1.concat(arr2);
    console.log(arr3);
    
    /* [6] 截取数组的方法(不会改变原来的数据) */
    /* 语法:arr.slice(startIndex,endIndex) */
    /* 注意: */
    /* (1) 该方法可以只传递一个参数,表示从这个位置开始截取直到数组的末尾 */
    /* (2) 如果没有传递任何参数,那么表示截取整个数组 */
    var data = ["熊大", "熊二", "佩琪", "乔治", 100, 200, "毛毛", "吉吉"];
    var res1 = data.slice(1, 4);
    console.log(res1);// ["熊二", "佩琪", "乔治"]
    var res2 = data.slice(1);
    console.log(res2);// ["熊二", "佩琪", "乔治", 100, 200, "毛毛", "吉吉"]
    var res3 = data.slice();
    console.log(res3);// ["熊大", "熊二", "佩琪", "乔治", 100, 200, "毛毛", "吉吉"]
    
    /* [7] 删除并插入数组的方法(会改变原来的数据) */
    /* 语法:arr.splice(start,deleteCount.val1,val2,...):从start开始删除deleteCount项 */
    /* 注意: */
    /* (1) 该方法可以只传递一个参数,表示从这个位置开始截取直到数组的末尾 */
    /* (2) 如果没有传递任何参数,那么表示截取整个数组 */
    var data = ["熊大", "熊二", "佩琪", "乔治", 100, 200, "毛毛", "吉吉"];
    data.splice(1, 1, '张三'); // ["熊二", "佩琪", "乔治"]
    console.log(data);
    
    /* [8] 将数组反序 */
    /* 语法:arr.reverse(): */
    var a = [1, 2, 3, 4, 5]
    var b = a.reverse();
    console.log(a, b);//a:[5,4,3,2,1] b:[5,4,3,2,1]
    
    /* [9] 添加分割符并变成字符串 */
    /* 语法:arr.join('|'): */
    var a = [1, 2, 3, 4, 5]
    var b = a.join("|");
    console.log(a, b);//a:[1,2,3,4,5] b:"1|2|3|4|5"
    
    /* [10] 字符串按照字符切割成数组 */
    // 2.数组key值使用变量
    let lastWord = 'last,word,hello';
    let arr = lastWord.split(',');
    console.log(arr);
    
    /* [11] 数组元素索引并返回元素索引,不存在返回-1,索引从0开始 */
    /* 语法:arr.indexOf('a'): */
    var a = ['a', 'b', 'c', 'd', 'e'];
    console.log(a.indexOf('a'));//0
    console.log(a.indexOf('h'));//-1
    
    /* [12] 数组元素排序 */
    /* 语法:arr.sort(): */
    var arr = [{ age: 1 }, { age: 5 }, { age: 3 }, { age: 2 },];
    arr.sort((num1, num2) => num1.age - num2.age);
    console.log(arr);
    
    • 实用的代码
    
    // 1.判断值是否存在(a为null、undefined、0都隐性转换为false),常用在判断值存不存在,数组长度是不是0
    var a = null, b = 1;
    if (a) {
      console.log('有a');
    }
    if (b) {
      console.log('有b');
    }
    
    // 2.获取变量给默认值(0 null undefined false '')
    var a = '';
    let b = a || '默认值';
    console.log(b)
    
    let param = { prop: 1 };
    //let param=null;
    let variable = param && param.prop;
    console.log(variable)
    
    // 3.if判断简写
    let a = 1, b = 3, c = 5, d = 7;
    // a === 1 && (b = 2);
    // console.log(b);
    // // 相当于
    // if (a === 1) {
    //   b = 2;
    // }
    
    // if (a) {
    //   b = c;
    // } else {
    //   b = d;
    // }
    // 相当于
    b = a ? c : d
    console.log(b);
    
    // 4.获取状态,针对没有规律的键值对,可以用对象进行保存
    // 代替if判断或者switch case
    // let a = 'success';
    // let b = '';
    // switch (a) {
    //   case 'success':
    //     b = '成功';
    //     break;
    //   case 'fail':
    //     b = '失败';
    //     break
    //   case 'wait':
    //     b = '待充值'
    //     break
    // }
    // console.log(b);
    // const obj = { 'success': '成功', 'fail': '失败', 'wait': '待充值' };
    // console.log(obj.success);
    
    // 针对按照索引来的键值对,可以用数组进行保存
    let obj = ['', '成功', '失败', '代充值'];
    console.log(obj[1]);
    
    // 5.获取浏览器缓存
    localStorage.setItem('item', 1);
    console.log(localStorage.getItem('item') === localStorage.item);
    
    localStorage.setItem('aaa', JSON.stringify({ a: 1 }));
    console.log(JSON.parse(localStorage.aaa));
    
    // 6.移动端调试利器
    <script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
    <script>
      // 初始化
      var vConsole = new VConsole();
      console.log('Hello world');
    </script>
    

    实用库

    • lodash:是一个 JavaScript 实用工具库,提供一致性,及模块化、性能和配件等功能
    • moment:是一个 JavaScript 日期处理类库,用于解析、检验、操作、以及显示日期的功能
  • 相关阅读:
    没用完的手机流量是否清零?讨论+吐槽
    南方周末:《系统》
    如何将Excel表批量赋值到ArcGIS属性表
    解决4K屏电脑显示问题
    坐标或测量值超出范围
    快速手工实现软件著作权源码60页制作
    SVN版本更新自动通知提醒
    1130不允许连接到MySql server
    Win10中SVN图标不显示的解决
    注意地理坐标系下的距离和面积计算
  • 原文地址:https://www.cnblogs.com/Hsong/p/14093649.html
Copyright © 2020-2023  润新知