第八课之提高开发效率的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 日期处理类库,用于解析、检验、操作、以及显示日期的功能
posted @ 2020-12-06 18:35  福小松  阅读(170)  评论(0编辑  收藏  举报