学习视频:尚硅谷Web前端ES6教程,涵盖ES6-ES11_哔哩哔哩_bilibili
一、介绍
ES:全称为EcmaScript,是脚本语言的规范
ECMAScript: 由Ecma国际通过ECMA-262标准化的脚本程序设计语言。
es6兼容性:ECMAScript 6 compatibility table
二、ES6 - 声明变量
(一)let
1.不能重复声明;(var可以重复声明)
2.块级作用域;
3.不存在变量提升;(变量提升解释:代码执行之前收集变量名称,最初为undefined)
console.log(abc); var abc = 'aaa'; ==》 输出undefined
console.log(abc); let abc = 'aaa'; ==》 报错
4.不影响作用域链;
举例:
<script>
let items = document.getElementsByClassName('item');
for (var i = 0; i < items.length; i++) {
items[i].onclick = function() {
this.style.background = 'pink'; //必须用this,因为i此时为3,
//items[i]会报错
}
}
</script>
<script>
let items = document.getElementsByClassName('item');
for (let i = 0; i < items.length; i++) {
items[i].onclick = function() {
items[i].style.background = 'pink'; //可以用items[i]或this
}
}
</script>
(二) const 声明常量
1. 一定要赋初始值
2.一般常量使用大写
3.常量的值不能修改
const SCHOOL = '测试';
SCHOOL = 'ABC';
//报错:Uncaught SyntaxError: Missing initializer in const declaration
4.块儿级作用域
{
const SCHOOL1 = '测试';
}
console.log(SCHOOL1);
//报错:Uncaught ReferenceError: SCHOOL1 is not defined at 2-const.html:23
5.对于数组和对象的元素修改,不算做对常量的修改,不会报错
const TEAM = ['ABC','MING','ADF'];
TEAM.push('AD'); //地址不变,所以不报错
TEAM = 100; //会报错
三、ES6 - 变量的解构赋值
允许按照一定模式从数组和对象中提取值,对变量进行赋值,被称为解构赋值。
<script>
//1.数组的解构
const F4 = ["言承旭","周渝民","没组","西门"];
let [yan,zhou,mei,xi] = F4;
console.log(mei,zhou,yan,xi);
//2.对象的解构
const zhao={
name:'赵本山',
age:55,
xiaopin:function(){
console.log("我可以演小品");
}
};
let {name,age,xiaopin}=zhao;
console.log(age,name,xiaopin);
xiaopin();
</script>
四、ES6 - 模板字符串
<script>
//ES6引入新的声明字符串的方式[``] '' ""
//1.声明
let str = '我也是一个字符串';
console.log(str, typeof str); //输出:我也是一个字符串 string
//2.内容中可以直接出现换行符
str = `<ul>
<li>aa</li>
<li>bb</li>
</ul>`;
//3.变量拼接
let lovest = '天才樱木';
let out = `${lovest}不是傻瓜`;
console.log(out); //输出:天才樱木不是傻瓜
</script>
五、ES6 - 对象的简化写法
ES6允许在大括号里,直接写入变量和函数,作为对象的属性和方法。
<script>
//ES6允许在大括号里,直接写入变量和函数,作为对象的属性和方法。
let name = '加油';
let change = function(){
console.log('我们可以改变');
}
const school1 = { // 完整写法
name:name,
change:change,
inporove: function(){
console.log('我们要努力学习');
}
};
const school = { //简略写法,只写变量
name,
change,
improve(){
console.log('我们要努力学习');
}
};
console.log(school); //输出:{name: '加油', change: ƒ, improve: ƒ}
</script>
输出:
六、ES6 - 箭头函数以及声明特点
(一)、允许使用箭头 (=>) 定义函数
<script>
//允许使用箭头 (=>) 定义函数
//声明函数
let fn = function(){ //旧写法
}
let fn1 = (a,b)=>{
return a+b;
}
//调用函数
let result = fn1(1,2);
console.log(result);
//1.this是静态的,this始终指向函数声明时所在作用域下的this的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置window的name属性
window.name='test';
const school = {
name:"TEST"
}
//直接调用
getName(); //out:test //this指向window
getName2(); //out:test //this指向window
//call方法调用
getName.call(school); //TEST
getName2.call(school); //test
//2.不能作为构造函数实例化对象
// let Person = (name, age) => {
// this.name = name;
// this.age = age;
// }
// let me = new Person('xiao',30);
// console.log(me); //error : Uncaught TypeError: Person is not a constructor
//3.不能使用arguments变量
// let fn2 = ()=>{
// console.log(arguments); //error:Uncaught ReferenceError: arguments is not defined
// }
// fn2(1,2);
//4.箭头函数的简写
// a.省略小括号:当形参有且只有一个
// let add1 = (n) => {
// return n+n;
// }
let add = n => {
return n+n;
}
console.log(add(9));
// b.省略花括号:当代码体只有一条语句: return必须省略
// 而且语句的执行结果时函数的返回值
// let pow = (n) => {
// return n*n;
// }
let pow = n => n*n;
console.log(pow(8));
</script>
call方法扩展说明:call()
方法是预定义的 JavaScript 方法,它可以用来调用所有者对象作为参数的方法。通过 call()
,您能够使用属于另一个对象的方法。
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates",
}
var person2 = {
firstName:"Steve",
lastName: "Jobs",
}
person.fullName.call(person1); // 将返回 "Bill Gates"
call() 方法可接受参数:
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates"
}
person.fullName.call(person1, "Seattle", "USA"); //out:Bill Gates,Seatle,USA
arguments扩展说明:arguments 是一个对应于传递给函数的参数的类数组对象。arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。
arguments展示形式是一个伪数组:具有 length 属性,按索引方式储存数据,不具有数组的 push , pop 等方法。
函数参数(argument)指的是传递到函数或由函数接收到的真实值。
如果调用参数时省略了参数(少于被声明的数量),则丢失的值被设置为:undefined。
function sumAll() {
var i;
var sum = 0;
for(i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(sumAll(1,2,4)); // out:7
(二)、箭头函数举例
1. 点击div 2s后变色
<script>
//需求:1-点击div 2s 后颜色变了
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
// a.this报错
// setTimeout(function(){
// console.log(this); //out: window
// this.style.background = 'pink'; //error:Uncaught TypeError: Cannot set properties of undefined (setting 'background')
// },2000);
// b.老的正确写法: 保存this的值
// let _this = this;
// setTimeout(function(){
// console.log(this);
// _this.style.background = 'pink';
// },2000);
//c. 箭头函数写法:this是静态的,指向声明的函数的作用域的值
setTimeout(()=>{
this.style.background = 'pink';
},2000);
})
</script>
2. 从数组中返回偶数元素
// 2.需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
//a. 老方法
const result = arr.filter(function(item){
if(item % 2 === 0) {
return true;
}else {
return false;
}
});
console.log(result); //out:(3) [6, 10, 100]
//b. 箭头函数
const result1 = arr.filter(item => item % 2 === 0);
console.log(result1); //out:(3) [6, 10, 100]
总结:箭头函数适合于this无关的回调,如定时器,数组的方法回调
不适合与this有关的回调,如事件回调,对象的方法
let a={
name:'abc',
getName : function(){
return this.name; //this 指向本对象
}
};
var name = 'cccc'; //或window.name可以输出 //当let name='xx'时无法输出,为什么?
let b ={
name:'abc',
getName : ()=> {
console.log(this); //window
return this.name;
} //指向外层this
};
console.log(a.getName()); // out: abc
console.log(b.getName()); // out: cccc
七、ES6 - 函数参数的默认值
es6允许给函数参数赋初始值
<script>
//es6允许给函数参数赋初始值
//1.形参初始值
//具有默认值的参数,一般位置要靠后
function add(a,b,c=10) {
return a+b+c;
}
console.log(add(1,2),add(1,2,3)); //out: 13 6
//2. 与解构赋值结合
function connect(options) { //传统写法
let host = options.host;
let username = options.username;
console.log(host,username);//out:localhost root
}
function connect({host,username,password,port}){ //解构写法
console.log(host,username,password,port);
}
connect({
host:'localhost',
username:'root',
password:'root',
port:3306
}) //out:localhost root root 3306
//解构写法+赋初始值
function connect1({host='127.0.0.1',username,password,port}){
console.log(host,username,password,port);//out:localhost root root 3306
}
connect1({
username:'root',
password:'root',
port:3306
}) //out:127.0.0.1 root root 3306
</script>
八、ES6 - rest参数
<script>
//es6 引入 rest参数,用于获取函数的实参,用来代替arguments
//es5 获取实参的方式
function date(){
console.log(arguments);
}
date('abc','23','adf'); //out:Arguments(3)对象 0: "abc" 1: "23" 2: "adf"
//es6 rest参数
function date1(...args){
console.log(args);
}
date1('abc','23','adf'); //out: (3) ['abc', '23', 'adf'] //是数组
//rest参数必须放到参数最后
function fn(a,b,...args){
console.log(a,b,args);
}
fn(1,2,3,4,5); //out:1 2 (3) [3, 4, 5] //3,4,5属于一个数组,给了args
</script>
九、ES6 - 扩展运算符
(一)、扩展运算符介绍
<script>
// ... 扩展运算符能将 数组 转换为逗号分隔的 参数序列
//声明一个数组
const boys = ['ab','cd','ef']; //=>'ab','cd','ef'
//声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(boys); //out:Arguments(1) // 0: (3) ['ab', 'cd', 'ef'] //只有一个数组参数
chunwan(...boys);// out:Arguments(3) // 0: "ab" 1: "cd" 2: "ef" //变成三个参数
// 等同于chunwan('ab','cd','ef')
</script>
(二)、扩展运算符的应用
<html>
<head>
<meta charset="UTF-8">
<title>let</title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<script>
//应用:1. s数组的合并
const str1 = ['a1','a2'];
const str2 = ['b1','b2'];
const unit = str1.concat(str2);
console.log(unit); //out:(4) ['a1', 'a2', 'b1', 'b2'] //数组
//扩展运算符
const unit2 = [...str1, ...str2];
console.log(unit2);//out:(4) ['a1', 'a2', 'b1', 'b2'] //数组
//2. 数组的克隆
const sanzhihua = ['e','g','m'];
const sanyecao = [...sanzhihua];
console.log(sanyecao);//out : (3) ['e', 'g', 'm'] //如果元素包含引用类型,则是浅拷贝
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
console.log(divs); //out : NodeList(3) [div, div, div] //对象
const divArr = [...divs];
console.log(divArr);//out:(3) [div, div, div]
</script>
</body>
</html>
十、 ES6 - Symbol
(一)、介绍和创建
Symbol是新引入的数据类型,表示独一无二的值,类似于字符串的数据类型。
特点:1.Symbol值是唯一的,解决命名冲突的问题。2.Symbol值不能与其他数据进行运。 3.Symbol定义的对象属性不能使用for...in循环遍历,可以用Reflect.ownKeys来获取对象的所有键名
//创建Symbol
let s = Symbol();
console.log(s,typeof s); //out: Symbol() 'symbol'
let s2 = Symbol('abc');//传入描述字符串
let s3 = Symbol('abc');
console.log(s2 === s3); // out : false
let s4 = Symbol.for('abc');
console.log(s4,typeof s4); // out: Symbol(abc) 'symbol'
let s5 = Symbol.for('abc');
console.log(s4 === s5); // out: true
//不能与其他数据进行运算
// let result = s + 100; //error: Uncaught TypeError: Cannot convert a Symbol value to a number
// let result = s + s; //error: Uncaught TypeError: Cannot convert a Symbol value to a number
七种数据类型口诀: USONB you are so niubility
//u undefined
//s string symbol
//o object
//n null number
//b boolean
(二)symbol使用场景
//2 - 使用场景: 向对象中添加方法 up down
let game = {
name:'abc',
up:function(){},
down:function(){}
}
// game.up = function(){}
//声明一个对象
let methods = {
up:Symbol(),
down:Symbol()
};
game[methods.up] = function(){
console.log('我可以改变形状');
}
game[methods.down] = function(){
console.log('我可以快速下降');
}
console.log(game);//out : {name: 'abc', up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}
let youxi = {
name:'狼人杀',
[Symbol('say')]:function(){
console.log('abc');
},
[Symbol('zibao')]:function(){
console.log('efg');
},
}
console.log(youxi);//out:{name: '狼人杀', Symbol(say): ƒ, Symbol(zibao): ƒ}
输出:
- {name: '狼人杀', Symbol(say): ƒ, Symbol(zibao): ƒ}
- name: "狼人杀"
- Symbol(say): ƒ ()
- arguments: null
- caller: null
- length: 0
- name: "[say]"
- prototype: {constructor: ƒ}
- [[FunctionLocation]]: 10-symbol.html:63
- [[Prototype]]: ƒ ()
- [[Scopes]]: Scopes[2]
- Symbol(zibao): ƒ ()
- [[Prototype]]: Object
(三)Symbol-内置值
除了定义自己使用的Symbol值以外,es6还提供了11个内置的Symbol值,指向语言内部使用的方法
Symbol其他扩展介绍可以参考:
2.3 ES6 Symbol | 菜鸟教程
Symbol - JavaScript | MDN
//当其他对象使用instanseof运算符,判断是否为该对象的实例时,会调用这个方法
class Person{
static [Symbol.hasInstance](param){
console.log(param); // out: {}
console.log('检测类型');
}
}
let o = {};
console.log(o instanceof Person);//out:false
//对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,
//是否可以展开。
const arr = [1,2,3];
const arr2 = [4,5,6];
console.log(arr.concat(arr2));//out: (6) [1, 2, 3, 4, 5, 6]
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));//out:(4) [1, 2, 3, Array(3)]
十一、迭代器
(一)迭代器介绍
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,九可以完成遍历操作。
1)es6创造了一种新的遍历命令for..of循环,iterator接口主要供for..of消费
2)原生具备iterator接口 数据(可用for of遍历)
Array, Arguments, Set, Map, String, TypedArray, NodeList
3) 工作原理
a)创建一个指针对象,指向当前数据结构的起始位置
b)第一次调用对象的 next方法,指针自动指向数据结构的第一个成员
c)接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
d)每调用next方法返回一个包含value和done属性对象
//声明一个数组
const arr = ['a','b','c','d'];
for (let v in arr) {
console.log(v+"-"+arr[v]); // out: 0-a 1-b 2-c 3-d
}
//使用for...of遍历数组
for (let v of arr) {
console.log(v); // out: a b c d
}
console.log(arr);
let iterator = arr[Symbol.iterator]();
console.log(iterator);//out:Array Iterator {}
//调用对象的next方法
console.log(iterator.next());//out:{value: 'a', done: false}
console.log(iterator.next());//out:{value: 'b', done: false}
console.log(iterator.next());//out:{value: 'c', done: false}
console.log(iterator.next());//out:{value: 'c', done: false}
console.log(iterator.next());//out:{value: undefined, done: true}
(二)迭代器应用
注意:需要自定义遍历数据的时候,需要想到迭代器。
//2 -应用
//注意:需要自定义遍历数据的时候,需要想到迭代器。
const banji = {
name:"终极一班",
stus:[
'marry',
'summer',
'rukawa',
'sakuragi',
'lucy'
],
[Symbol.iterator](){
let index = 0;
let _this = this;
return {
next:function(){
if(index < _this.stus.length) {
const result = {value:_this.stus[index],done:false};
//下标自增
index++;
return result;
}else {
return {value:undefined, done:true};
}
}
};
}
}
//遍历对象,每一次返回的结果是数组里的成员
for (let v of banji) {
console.log(v);//marry summer rukawa sakuragi lucy
}
十二、生成器
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数不同
(一)声明和调用
//异步编程 纯回调函数:node fs ajax mongodb
//加一个星号
function * gen(){
console.log('hello');
}
let iterator = gen();
console.log(iterator);
/**
* out:
* gen
[[GeneratorLocation]]: 12-生成器.html:13
[[Prototype]]: Generator
[[Prototype]]: Generator
constructor: GeneratorFunction {prototype: Generator, Symbol(Symbol.toStringTag): 'GeneratorFunction', constructor: ƒ}
next: ƒ next()
return: ƒ return()
throw: ƒ throw()
Symbol(Symbol.toStringTag): "Generator"
[[Prototype]]: Object
[[GeneratorState]]: "suspended"
[[GeneratorFunction]]: ƒ * gen()
[[GeneratorReceiver]]: Window
[[Scopes]]: Scopes[3]
*
*/
iterator.next(); //out: hello
//yidld函数代码的分隔符
function * gen1(){
console.log(111);
yield '一个';
console.log(222);
yield '二个';
console.log(333);
yield '好的吧';
console.log(444);
}
let it = gen1();
console.log(it.next());//out:111 {value: '一个', done: false}
console.log(it.next());//out:222 {value: '二个', done: false}
console.log(it.next());//out:333 {value: '好的吧', done: false}
console.log(it.next());//out:444 {value: undefined, done: true}
//遍历
for(let v of gen1()){
console.log(v);
}
/**
* out:
111
一个
222
二个
333
好的吧
444
*
*/
(二)生成器的参数传递
//2-生成器的参数传递
function * abc(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator1 = abc('aaa');
console.log(iterator1.next()); // aaa {value: 111, done: false}
//next 方法可以传入实参
console.log(iterator1.next('bbb'));//bbb {value: 222, done: false}
console.log(iterator1.next('ccc'));//ccc {value: 333, done: false}
console.log(iterator1.next('ddd'));//ddd {value: undefined, done: true}
(三)生成器函数实例
//3-实例1
//异步编程:文件操作 网络操作(ajax,request) 数据库操作
//1s 后控制台输出 111 2s后输出222 3s后输出333
//老代码:回调地狱
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 1000);
}, 1000);
}, 1000);
console.log("---------------------------");
//改进
function one(){
setTimeout(()=>{
console.log(111);
it1.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
it1.next();
},1000)
}
function three(){
setTimeout(()=>{
console.log(333);
it1.next();
},1000)
}
function * create1(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let it1 = create1();
it1.next();
//3-实例2
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(() => {
let data1 = '用户数据';
//调用next方法,并且将数据传入
it2.next(data1);
}, 1000);
}
function getOrders(){
setTimeout(() => {
let data = '订单数据';
it2.next(data);
}, 1000);
}
function getGoods(){
setTimeout(() => {
let data = '商品数据';
it2.next(data);
}, 1000);
}
function * create2(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
//调用生成器函数
let it2 = create2();
it2.next();
十三、Promise
(一)介绍
Promise是es6引入的异步编程的新解决方案,语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
构造函数:Promise(excutor){}
Promise.prototype.then方法
Promise.prototype.catch方法
//实例化promise对象
//初始化 成功 失败
const p = new Promise(function(resolve,reject){
setTimeout(function(){
// let data = '数据库中的用户数据';
// //resolve
// resolve(data); //成功时调用
let err = '数据读取失败';
reject(err); //失败时调用
},
1000);
});
//调用promise 对象的 then方法
p.then(function(value){ //成功
console.log(value); // out: 数据库中的用户数据
},function(reason){//失败
console.log(reason); // out: 数据读取失败
})
(二) 封装读取文件
// //1.引入fs模块
const fs = require('fs');
// //2. 调用方法读取文件
// fs.readFile('../resources/1.txt',(err,data)=>{
// //如果失败,抛出错误
// if(err) throw err;
// //如果正确,则输出
// console.log(data.toString());
// });
//3.使用promise封装
const p = new Promise(function(resolve, reject){
fs.readFile('../resources/1.txt',(err,data)=>{
//如果失败
if(err) reject(err);//改变状态为失败
//如果正确,改变状态为成功,并传值
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
},function(reason){
console.log('读取失败');
});
控制台输入:node .\13-promise读取文件.js
打印出文件内容