文章目录
第一章 基本语法
1.什么是ES6
ECMAScript是Javascript的标准,js是ES的实现;主流实现只有js
ES6的正式名称是ES2015,是ECMA标准的第6版
2.变量(常量)
var声明的缺点
用var声明的变量可以重复声明。
var a=1;
var a=2;
用var声明的变量难以控制修改
var GIT_HOST = 'github.com'
// 看似声明了一个常量,但实际是一个变量,可以被重新赋值
块级作用域
ES5 var 的作用域——函数级
ES6 let 的作用域——块级(const也是块级)
新的声明方式:let和const
(1)禁止重复声明
(2)用const声明禁止修改
(3)用let和const声明块级变量、常量,具有块级作用域特性
(4)使用let声明变量可以防止循环变量变成全局变量
for(var i=0;i<2;i++){
}
console.log(i);// 2
(5)使用let声明变量不存在变量提升
(6)使用let声明变量存在暂时性死区
var num = 3;
if(true){
console.log(num);// 3
}
var num = 3;
if(true){
console.log(num);
let num = 2;
}
// ReferenceError: Cannot access 'num' before initialization
补充:暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead
zone,简称TDZ)。
(7)声明常量时必须初始化
(8)声明常量,常量的值(内存地址)不能变化。也就是说,如果常量保存的是基本数据类型,不能重新赋值,但如果保存的是引用类型,则可以给引用类型所引用的内存地址的保存量重新赋值,但不能改变内存地址的值。
const arr = [1,2];
arr[0] = 100;
console.log(arr);//[100,2]
arr = [100,200];
//TypeError: Assignment to constant variable.
3.解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
格式:[模式名:变量名,模式名:变量名] = [值1,值2];
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
json = {a:12.b:5}
let {a,b} = json;
arr = [12,5,8];
let [a,b,c] = arr;
用途:从请求获取的数据中提取有用信息
$.ajax('xxx') => {
code:xx,
data:xx,
msg:"xxx"
}
let {code,data} = $.ajax('xxx');
注意
(1)解构赋值两边的结构必须一样
(2)右边必须是一个正常数据结构
(3)赋值和解构同时完成
let {a,b};
{a,b} = {a:12,b:5}
// 报错
ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
// 例子1
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
// 例子2
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined
4.函数
箭头函数
作用1:简化代码
()=>{}
例:排序函数
[12,2,4,23].sort((n1,n2) => {return n1-n2});
注意事项
(1)如果有且仅有一个参数,圆括号()也可以不写。
(2)如果有有且仅有一个语句,并且是return语句,花括号{}也可以不写。
作用2:修正this
this在箭头函数中会被固定为当前的环境(对象的环境或者语句执行时this的指向)。
class Json(){
constructor(){
this.a = 2;
this.fn()=>{
console.log(this.a);
}
}
}
let json = new Json();
json.fn();//2
let date = new Date();
date.fn = json.fn;
date.fn();//2
箭头函数有几个使用注意点。
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。
5.参数展开、数组展开、json展开
剩余参数
function show(a,b,...c){
}
show(1,2,3,4,5,6);
// a = 1.b = 2,c = [3,4,5,6];
注意:剩余参数之后不能出现其他参数
数组展开
// 将数组的内容作为整体出现
let arr = [1,2,3];
function add(a,b,c){
alert(a+b+c);
}
add(...arr);
// 合并数组
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = [...arr1,...arr2];// arr3 = [1,2,3,4,5,6]
json展开
类似于数组
let json1 = {a:1,b:2};
let json2 = {
...json1,
c:3;
}
// json2 = {a:1,b:2,c:3}
5.原生对象扩展
Array对象的扩展
map
:映射,一一对应(n个数据项出来还是n个)
let array = [68,12,53,74,95];
let resultArray = array.map(item => {
return item>=60 ? '及格' : '不及格';
})
console.log(array);
console.log(resultArray);
//[ 68, 12, 53, 74, 95 ]
//[ '及格', '不及格', '不及格', '及格', '及格' ]
reduce
:缩减,(n个数据项出来只有1个)
例:求平均值
let array = [68,12,53,74,95];
// 参数函数的4个参数(前一个值,当前值,项的索引,数组对象)
let result = array.reduce((tmp,item,index) => {
if(index == array.length-1){
return (tmp+item)/array.length;
}
return tmp+item;
})
console.log(array);
console.log(result);
filter
:过滤
例:过滤偶数
let array = [68,12,53,74,95];
let result = array.filter((item) => {
if(item%2==0){
return true;
}else{
return false;
}
})
console.log(array);
console.log(result);
foreach
:遍历,没有返回值
let array = [68,12,53,74,95];
array.forEach((item,index) => {
console.log(`第${index+1}个项是${item}`);
})
第1个项是68
第2个项是12
第3个项是53
第4个项是74
第5个项是95
JSON
JSON.stringfy();
JSON.parse();
let json = {a:12,b:15};
// 把json转化成字符串
console.log(JSON.stringify(json));
let strJson = '{"name":"zijeak","age":20}';
// 把字符串转化成json
console.log(JSON.parse(strJson));
{"a":12,"b":15}
{ name: 'zijeak', age: 20 }
第二章 babel编译
Babel是一个js编译器,可以将ES6编译为低版本可识别的代码。
方式一:引入js文件
不能兼容IE7
方式二:编译
安装babel
@babel/core
:babel核心库
@babel/cli
:babel命令库
@babel/preset-env
: babel的环境预设,用于指导babel的编译
@babel/polyfill
:(可选)babel编译过程中检测目标平台,如果是特别低版本的平台,会把自带的一些库函数编译进去,已向后兼容。
cnpm i @babel/core @babel/cli @babel/preset-env -D
在package.json
中新增一行
{
"name": "es6",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
// 新增下面一行
"build":"babel src -d dest"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.10.5",
"@babel/core": "^7.11.1",
"@babel/preset-env": "^7.11.0"
}
}
之后我们就可以使用npm run build
命令快速编译。
$ npm run build
> es6@1.0.0 build C:\Users\Zijeak\Desktop\前端学习\es6
> babel src -d dest
Successfully compiled 0 files with Babel (8ms).
可以看到,运行build脚本,实际上运行的就是babel src -d dest
命令。
这时我们来编译以下文件:
let a = 1;
let b = 2;
let sum = (n1,n2)=>{n1+n2};
console.log(sum(a,b));
编译后:
let a = 1;
let b = 2;
let sum = (n1, n2) => {
n1 + n2;
};
console.log(sum(a, b));
可以看到,除了格式上发生变化之外,并没有将let。箭头函数进行翻译。
这是因为我们还缺少预设配置。
在项目根目录创建.babelrc
文件如下:
{
"presets": [
"@babel/preset-env"
]
}
该文件指定了babel采用环境预设。
编译后:
"use strict";
var a = 1;
var b = 2;
var sum = function sum(n1, n2) {
n1 + n2;
};
console.log(sum(a, b));
第三章 异步操作
异步操作:例如ajax请求,异步操作可以同时进行多个操作,用户体验好;代码混乱。
同步操作:一次只能进行一个操作,用户体验差;代码清晰。
能不能有异步操作的体验,同时又同步操作的清晰代码?
1.Promise
Promise的作用是对异步操作做统一地封装
<script>
// Promise的作用是对异步操作做统一地封装
let p = new Promise(function(resolve,reject){
// 异步操作
// resolve 成功
// reject 失败
$.ajax({
url:'data/1.txt',
dataType:'json',
success(arr){
resolve(arr);
},
error(res){
reject(res);
}
});
});
p.then(function(arr){
alert('成功');
console.log(arr);
},function(res){
alert('失败');
console.log(res);
});
</script>
Promise.all()
Promise.all([
p1,
p2,
p3
]).then()
Promise.all(
[
$.ajax({url:'data/1.txt',dataType:'json'}),
$.ajax({url:'data/2.txt',dataType:'json'}),
$.ajax({url:'data/3.txt',dataType:'json'}),
]
).then(arr=>{
alert("成功");
console.log(arr);
},res=>{
alert("失败");
});
Promise.all(),需要全部成功才会执行then,只要有一个失败就会不执行。
也可以改用解构赋值:
Promise.all(
[
$.ajax({url:'data/1.txt',dataType:'json'}),
$.ajax({url:'data/2.txt',dataType:'json'}),
$.ajax({url:'data/3.txt',dataType:'json'}),
]
).then(([data1,data2,data3])=>{
console.log(data1,data2,data3);
},res=>{
alert("失败");
});
Promise.race()
Promise.race()同时读,谁先读完用哪个
2.像写同步代码那样写异步:async/await
普通函数——一直执行,直到结束
async函数——能够“暂停”,可以暂停的位置用await标识
async function show(){
let a = 1;
let b = 2;
let data = await $.ajax({
url:"data/1.txt",
dataType:'json'
});
console.log(a+b+data[0]);
}
show();
上面的写法相当于把函数拆分成小函数:
function show1(){
let a = 1;
let b = 2;
}
$.ajax({
url:"data/1.txt",
dataType:'json'
}).then(show2());
function show2(){
console.log(a+b+data[0]);
}
可以用try…catch捕获可能在Promise内部发生的错误
async function show(){
let a = 1;
let b = 2;
try{
let data = await $.ajax({
url:"data/1.txt",
dataType:'json'
});
}catch(e){
alert("读取出错!");
}
console.log(a+b+data[0]);
}
show();
第四章 ES6面向对象
参考文章:
https://blog.csdn.net/qq_18404993/article/details/107535615
第五章 ES6模块系统
参考文章:
https://blog.csdn.net/qq_18404993/article/details/107540524