现在的Chrome浏览器已经支持ES6了,但是有些低版本的浏览器还是不支持ES6的语法,这就需要我们把ES6的语法自动的转变成ES5的语法。Webpack是有自动编译转换能力的,除了Webpack自动编译,我们还可以用Babel来完成。这节课我们就使用Babel把ES6编译成ES5
建工程目录之后创建两个文件夹:src和dist
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--注意这里js路径是dist编译成ES5的js文件路径-->
<script src="../dist/index.js"></script>
</head>
<body>
Hello Es6
</body>
</html>
在src目录下,新建index.js用ES6声明方式
let a=1;
console.log(a);
在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。
npm init -y
npm install babel-cli -g
npm install babel-preset-es2015 babel-cli --save-dev
在根目录下新建.babelrc文件,并打开录入下面的代码
{
"presets":[
"es2015"
],
"plugins":[]
}
现在可以在终端输入转换命令可以发现dist目录下已经生成了ES5语法的js文件
babel src/index.js -o dist/index.js
可以使用npm run build 直接利用webpack进行打包,在这里也希望利用这种方式完成转换。打开package.json文件,把文件修改成下面的样子。
{
"name": "es6test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "babel src/index.js -o dist/index.js"
}
修改好后,以后我们就可以使用 npm run build 来进行转换了。
var 在ES6里是全局变量
var a=2;
{
var a=3;
}
console.log(a); //打印出来是3
var a=2;
{
let a=3;
}
console.log(a);//打印出来是2
var 声明的循环
for(var i=0;i<10;i++){
console.log('循环体中:'+i);
}
console.log('循环体外:'+i);
你会发现循环体外的i变量被污染了,如果在外部再使用i时就会出现问题,这是开发者不想看到的。我们再利用let声明,就可以解决这个问题。
用let声明的循环
for(let i=0;i<10;i++){
console.log('循环体中:'+i);
}
console.log('循环体外:'+i);
你执行时会发现控制台报错了,找不到循环体外的i变量。通过两种声明的比较,可以明白let在防止程序数据污染上还是很有用处的。我们要努力去习惯用let声明,减少var声明去污染全局空间,在vue的使用中也要注意这点。
const a="aaa";
var a='bbb';
console.log(a);
在编译这段代码的过程中,你就会发现已经报错,无法编译了,原因就是我们const声明的变量是不可以改变的。
//ES5写法
let a=0;
let b=1;
let c=2;
//ES6写法
let [a,b,c]=[1,2,3];
console.log(a);
console.log(b);
console.log(c);
等号左边和等号右边的形式要统一,如果不统一解构将失败。
let [a,[b,c],d]=[1,[2,3],4];
let [foo = true] =[];
console.log(foo); //控制台打印出true
现在我们对默认值有所了解,需要注意的是undefined和null的区别。
let[a="aa"]=[undefined];
console.log(a); //控制台显示aa
let[a="aa"]=[null];
console.log(a); //控制台显示null
null相当于有值,但值为null。所以b并没有取默认值,而是解构成了null。
let {name,sex}={name:'lm',sex:'男'}
console.log(name+sex);
如果在解构之前就定义了变量,这时候你再解构会出现问题。下面是错误的代码,编译会报错。
let name;
{name}={name:'lm'}
console.log(name);
要解决报错,使程序正常,我们这时候只要在解构的语句外边加一个圆括号就可以了。
let name;
({name}={name:'lm'})
console.log(name);
const [a,b,c,d,e]="guosh";
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
当编写一个方法时,我们允许它传入的参数是不确定的。这时候可以使用对象扩展运算符来作参数,看一个简单的列子
function sj(...arg){
console.log(arg[0]);
console.log(arg[1]);
console.log(arg[2]);
console.log(arg[3]);
}
sj(1,2,3,)
这时我们看到控制台输出了 1,2,3,undefined,这说明是可以传入多个值,并且就算方法中引用多了也不会报错
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
console.log(arr1) //结果 0,1,2,3,4,5
对象扩展运算符,rest运算符并它们有很多相似之处,不用特意去区分。它也用…(三个点)来表示。
function gsh(first,...arg){
console.log("first="+first); //结果是0
console.log("arg="+arg);//结果是1,2,3,4,5,6,7
}
gsh(0,1,2,3,4,5,6,7)
字符串拼接
//ES5语法
let a="姓名"
let c="我的"+a+"LM";
console.log(c);
//ES6语法
let a="姓名"
let c=`我的${a}LM`;
console.log(c);
对html标签支持
let a="姓名"
let c=`<b>我的${a}LM<b>`;
console.log(c);
let a="姓名"
let c="我的姓名";
document.write(c.includes(a)); //true
let a="姓名"
let c="我的姓名";
document.write(c.startsWith(a)); //false
let a="姓名"
let c="我的姓名";
document.write(c.endsWith(a)); //true
document.write('Guo|'.repeat(3)); //会打印三遍Guo|
//二进制开始是0第二个是B开头
let a=0B010101;
console.log(a); //打印21
//八进制开始是0第二个是O开头
let b=0O666
console.log(b)//打印438
可以使用Number.isFinite( )来进行数字验证,只要是数字,不论是浮点型还是整形都会返回true,其他时候会返回false。
let a=1;
console.log(Number.isFinite(a))//true
console.log(Number.isFinite(''呵呵))//false
console.log(Number.isNaN(NaN)); //true
let a=123.1;
console.log(Number.isInteger(a)); //false
let a='9.18';
console.log(Number.parseInt(a));
console.log(Number.parseFloat(a));
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MAX_SAFE_INTEGER);
let a= Math.pow(2,53)-1;
console.log(Number.isSafeInteger(a));//false
//0,1,2,是下标 length是长度
let json={
"0":"AA",
"1":"BB",
"2":"CC",
length:3
}
let arr=Array.from(json);
console.log(arr);
这就是一个标准的JSON数组格式,跟普通的JSON对比是在最后多了一个length属性。只要是这种特殊的json格式都可以轻松使用ES6的语法转变成数组
let a=Array.of('A','B','C');
console.log(a);
它负责把一堆文本或者变量转换成数组
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.find(function (value, index, arr) {
return value > 5;
}));
控制台输出了6,说明找到了符合条件的值,并进行返回了,如果找不到会显示undefined。
fill()也是一个实例方法,它的作用是把数组进行填充,它接收三个参数,第一个参数是填充的变量,第二个是开始填充的下标位置,第三个是填充到的具体位置。
let arr=[1,2,3,4,5,6,7,8,9];
arr.fill('a',4,9);
console.log(arr); //结果 [1, 2, 3, 4, "a", "a", "a", "a", "a"]
let arr=['AA','BB','CC'];
for (let item of arr) {
console.log(item)
}
let arr=['AA','BB','CC'];
for (let item of arr.keys()) {
console.log(item)
}
let arr=['AA','BB','CC'];
for (let [index,value] of arr.entries()) {
console.log(index+value)
}
entries()实例方式生成的是Iterator形式的数组,那这种形式的好处就是可以让我们在需要时用next()手动跳转到下一个值。我们来看下面的代码:
let arr=['AA','BB','CC'];
let list=arr.entries();
console(list.next().value);
console(list.next().value);
console(list.next().value);
ES5写法
function add(a,b){
return a+b;
}
console.log(add(2,3));
ES6写法
var add=(a,b)=>a+b;
console.log(add(1,2));
在箭头函数中,方法体内如果是两句话,那就需要在方法体外边加上{}括号。例如下边的代码就必须使用{}.
var add=(a,b)=>{
console.log("AAA")
return a+b;
};
console.log(add(1,2));
let json={
name:'xm',
age:'18'
}
function fun({name,age}){
console.log(name);
console.log(age);
}
fun(json);
let arr = ['a','b','c'];
function fun(a,b,c){
console.log(a,b,c);
}
fun(...arr);
let obj={
name:'xm',
age:'18'
}
console.log('name' in obj) //true
let arr=[,,]
console.log(0 in arr) //false
let arr1=['a','b']
console.log(0 in arr1) //true
注意:这里的0指的是数组下标位置是否为空
let arr=['aa',,'cc']
arr.forEach((value,index) => {
console.log(value,index) //结果aa 0 aa 2
});
forEach循环的特点是会自动省略为空的数组元素,相当于直接给我们筛空了。
let arr=['aa',,'cc']
arr.filter(x => {
console.log(x)
});
let arr=['aa',,'cc']
arr.some(x => {
console.log(x)
});
let arr=['aa','bb','cc']
console.log(arr.map(x=>'web')) // 'web' 'web' 'web'
map在这里起到一个替换的作用
let arr=['aa','bb','cc']
console.log(arr.toString())
let arr=['aa','bb','cc']
console.log(arr.join('|')) //自定义分隔符 aa|bb|cc
let name="XM";
let age="18";
let obj={name,age};
console.log(obj) //{name: "XM", age: "18"}
有时候我们会在后台取出key值,而不是我们前台定义好的,这时候我们如何构建我们的key值那。比如我们在后台取了一个key值,然后可以用[ ] 的形式,进行对象的构建。
let key="name"
let obj={
[key]:'XM'
}
console.log(obj); //{name: "XM"}
let a={name:'XM'};
let b={name:'XM'};
console.log(a.name === b.name);
//ES6比较方法
let a={name:'XM'};
let b={name:'XM'};
console.log(Object.is(a.name,b.name));
区分=== 和 is方法的区别是什么,看下面的代码输出结果。
console.log(+0 === -0); //true
console.log(NaN === NaN ); //false
console.log(Object.is(+0,-0)); //false
console.log(Object.is(NaN,NaN)); //true
===为同值相等,is()为严格相等
let a={name:'XM'};
let b={age:'18',sex:'男'};
let c=Object.assign(a,b);
console.log(c); //{name: "XM", age: "18", sex: "男"}
var a=Symbol("ES6");
console.log(a);
console.log(a.toString());
var xm=Symbol();
var obj={
[xm]:'ES6'
}
console.log(obj[xm]); //ES6
没有进行保护的写法:
var obj={name:'ES6',sex:'男',age:'18'}
for(let item in obj){
console.log(obj[item]); //ES6 男 18
}
现在我不想别人知道我的年龄,这时候我就可以使用Symbol来进行循环保护。
var obj={name:'ES6',sex:'男'}
var age=Symbol();
obj[age]='18';
for(let item in obj){
console.log(obj[item]); //ES6 男
}
Set和Array 的区别是Set不允许内部有重复的值,如果有只显示一个,相当于去重。虽然Set很像数组,但是他不是数组。
let setArr=new Set(['aa','bb','cc','aa']);
console.log(setArr); //aa,bb,cc
let setArr=new Set(['aa','bb','cc','aa']);
setArr.add('dd');
console.log(setArr)//aa,bb,cc,dd
let setArr=new Set(['aa','bb','cc','aa']);
setArr.delete('aa');
console.log(setArr)//bb,cc
let setArr=new Set(['aa','bb','cc','aa']);
console.log(setArr.has('aa'));//true
let setArr=new Set(['aa','bb','cc','aa']);
setArr.clear();
console.log(setArr);
let setArr=new Set(['aa','bb','cc','aa']);
for (let item of setArr) {
console.log(item);
}
let weakObj=new WeakSet();
let obj={
name:"XM",
age:"18"
};
weakObj.add(obj);
console.log(weakObj);
这里需要注意的是,如果你直接在new 的时候就放入值,将报错,只能通过add()插入
let weakObj=new WeakSet();
let obj={
name:"XM",
age:"18"
};
let obj1=obj;
weakObj.add(obj);
weakObj.add(obj1);
console.log(weakObj);
内存空间相同只会插入一个对象
let obj={
name:"XM",
age:"18"
};
let map=new Map();
map.set("a",obj);
map.set("b",1);
console.log(map);
console.log(map.get("b"));
map.delete("b")
根据key删除值
console.log(map.size);
console.log(map.has('a'))//true
map.clear()
let pro =new Proxy({
add: function(val){
return val+10
},
name: 'gg'
},{
//get属性是在你得到某对象属性值时预处理的方法 target:目标值。key:目标的Key值。
get: function(target,key,property){
return target[key];
},
//set属性是值你要改变Proxy属性值时,进行的预先处理的方法 target:目标值。key:目标的Key值。value:要改变的值。receiver:改变前的原始值。
set: function(target,key,value,receiver){
return target[key] = value;
}
})
console.log(pro); //触发get
pro.name='aaa'; //触发set
console.log(pro);
apply的作用是调用内部的方法,它使用在方法体是一个匿名函数时。
let target = function () {
return 'Hello';
};
var handler = {
apply(target, ctx, args) {
console.log('do apply');
return Reflect.apply(...arguments);
}
}
var pro = new Proxy(target, handler);
console.log(pro());
promise执行多步操作非常好用
let state=1;
function step1(resolve,reject){
console.log('1.开始-第一步');
if(state==1){
resolve('第一步--完成');
}else{
reject('第一步--出错');
}
}
function step2(resolve,reject){
console.log('2.开始-第二步');
if(state==1){
resolve('第二步--完成');
}else{
reject('第二步--出错');
}
}
function step3(resolve,reject){
console.log('3.开始-第三步');
if(state==1){
resolve('第三步--完成');
}else{
reject('第三步-出错');
}
}
new Promise(step1).then(function(val){
console.log(val);
return new Promise(step2);
}).then(function(val){
console.log(val);
return new Promise(step3);
}).then(function(val){
console.log(val);
return val;
});
class Coder{
//类中的方法
name(val){
console.log(val);
}
}
let guo=new Coder();
guo.name('AA')
class Coder{
//类中的方法
name(val){
console.log(val);
return val;
}
skill(val){
console.log(this.name("aa")+":"+"skill:"+val)
}
}
let guo=new Coder();
guo.skill('bb');
class Coder{
constructor(a,b){
this.a=a;
this.b=b;
}
add(){
return this.a+this.b;
}
}
let guo=new Coder(1,2);
console.log(guo.add())
我们用constructor来约定了传递参数,然后用作了一个add方法,把参数相加
class Htmlel extends Coder{
}
let guo=new Htmlel();
我们新建一个temp.js文件,然后在文件中输出一个模块变量
export var a='guo';
然后可以在index.js中以import的形式引入
import {a} from './temp.js'
console.log(a);
var a='guo';
var b='guoa';
var c='guob';
export {a,b,c}
export function add(a,b){
return a+b;
}
有些时候我们并不想暴露模块里边的变量名称,而给模块起一个更语义话的名称,这时候我们就可以使用as来操作。
var a='guo';
var b='guoa';
var c='guob';
export {
a as x,
b as c,
c as v
}
加上default相当是一个默认的入口。在一个文件里export default只能有一个。我们来对比一下export和export default的区别
export var a ='guo';
对应导入方式
import {a} form './temp';
export var a ='guo';
对应导入方式
import str from './temp';