ES6的开发环境搭建
现在的Chrome浏览器已经支持ES6了,但是有些低版本的浏览器还是不支持ES6的语法,这就需要我们把ES6的语法自动的转变成ES5的语法。Webpack是有自动编译转换能力的,除了Webpack自动编译,我们还可以用Babel来完成。这节课我们就使用Babel把ES6编译成ES5
新建目录
建工程目录之后创建两个文件夹:src和dist
src:书写ES6代码的文件夹,写的js程序都放在这里。
dist:利用Babel编译成的ES5代码的文件夹,在HTML页面需要引入的时这里的js文件。
编写index.html
<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>
编写index.js
在src目录下,新建index.js用ES6声明方式
let a=1;console.log(a);
初始化项目
在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。
npm init -y
全局安装Babel-cli
npm install babel-cli -g
本地安装babel-preset-es2015 和 babel-cli
npm install babel-preset-es2015 babel-cli --save-dev
新建.babelrc
在根目录下新建.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 声明
var 在ES6里是全局变量
var a=2; { var a=3; }console.log(a); //打印出来是3
let局部声明
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声明常量
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);
扩展运算符和rest运算符
对象扩展运算符(…)
当编写一个方法时,我们允许它传入的参数是不确定的。这时候可以使用对象扩展运算符来作参数,看一个简单的列子
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运算符
对象扩展运算符,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);
字符串查找
includes判断是否存在
let a="姓名"let c="我的姓名";document.write(c.includes(a)); //true
startsWith判断开头是否存在
let a="姓名"let c="我的姓名";document.write(c.startsWith(a)); //false
endsWith判断结尾是否存在
let a="姓名"let c="我的姓名";document.write(c.endsWith(a)); //true
赋值字符串
document.write('Guo|'.repeat(3)); //会打印三遍Guo|
ES6数字操作
二进制八进制声明
//二进制开始是0第二个是B开头let a=0B010101;console.log(a); //打印21//八进制开始是0第二个是O开头let b=0O666console.log(b)//打印438
数字验证
Number.isFinite( xx )数字验证
可以使用Number.isFinite( )来进行数字验证,只要是数字,不论是浮点型还是整形都会返回true,其他时候会返回false。
let a=1;console.log(Number.isFinite(a))//trueconsole.log(Number.isFinite(''呵呵))//false
NaN验证
console.log(Number.isNaN(NaN)); //true
整数验证
let a=123.1;console.log(Number.isInteger(a)); //false
整数转换Number.parseInt(xxx)和浮点型转换Number.parseFloat(xxx)
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);
安全整数判断isSafeInteger( )
let a= Math.pow(2,53)-1;console.log(Number.isSafeInteger(a));//false
ES6中的数组
JSON数组格式转换
//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的语法转变成数组
Array.of()方法
let a=Array.of('A','B','C');console.log(a);
它负责把一堆文本或者变量转换成数组
find( )实例方法:
value:表示当前查找的值。
index:表示当前查找的数组索引。
arr:表示当前数组。
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()实例方法
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"]
数组的遍历
for…of循环
输出值
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( )实例方法
entries()实例方式生成的是Iterator形式的数组,那这种形式的好处就是可以让我们在需要时用next()手动跳转到下一个值。我们来看下面的代码:
let arr=['AA','BB','CC'];let list=arr.entries();console(list.next().value);console(list.next().value);console(list.next().value);
ES6中的箭头函数和扩展
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));
ES6中的函数和数组补漏
对象的函数解构
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);
in是用法
对象判断
let obj={ name:'xm', age:'18'}console.log('name' in obj) //true
数组判断
let arr=[,,]console.log(0 in arr) //falselet arr1=['a','b']console.log(0 in arr1) //true
注意:这里的0指的是数组下标位置是否为空
数组的遍历方法
forEach
let arr=['aa',,'cc'] arr.forEach((value,index) => { console.log(value,index) //结果aa 0 aa 2});
forEach循环的特点是会自动省略为空的数组元素,相当于直接给我们筛空了。
filter
let arr=['aa',,'cc'] arr.filter(x => { console.log(x) });
some
let arr=['aa',,'cc'] arr.some(x => { console.log(x) });
map
let arr=['aa','bb','cc'] console.log(arr.map(x=>'web')) // 'web' 'web' 'web'
map在这里起到一个替换的作用
数组转换字符串
toString()方法
let arr=['aa','bb','cc']console.log(arr.toString())
join方法
let arr=['aa','bb','cc']console.log(arr.join('|')) //自定义分隔符 aa|bb|cc
ES6中对象
对象赋值
let name="XM";let age="18";let obj={name,age};console.log(obj) //{name: "XM", age: "18"}
对象Key值构建
有时候我们会在后台取出key值,而不是我们前台定义好的,这时候我们如何构建我们的key值那。比如我们在后台取了一个key值,然后可以用[ ] 的形式,进行对象的构建。
let key="name"let obj={ [key]:'XM'}console.log(obj); //{name: "XM"}
Object.is( ) 对象比较
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); //trueconsole.log(NaN === NaN ); //falseconsole.log(Object.is(+0,-0)); //falseconsole.log(Object.is(NaN,NaN)); //true
===为同值相等,is()为严格相等
Object.assign( )合并对象
let a={name:'XM'};let b={age:'18',sex:'男'};let c=Object.assign(a,b);console.log(c); //{name: "XM", age: "18", sex: "男"}
Symbol在对象中的作用
Symbol的声明
var a=Symbol("ES6");console.log(a);console.log(a.toString());
Symbol再对象中的应用
var xm=Symbol();var obj={ [xm]:'ES6'}console.log(obj[xm]); //ES6
Symbol对象元素的保护作用
没有进行保护的写法:
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和WeakSet数据结构
Set的声明
Set和Array 的区别是Set不允许内部有重复的值,如果有只显示一个,相当于去重。虽然Set很像数组,但是他不是数组。
let setArr=new Set(['aa','bb','cc','aa']);console.log(setArr); //aa,bb,cc
Set值的增删查
追加add
let setArr=new Set(['aa','bb','cc','aa']); setArr.add('dd');console.log(setArr)//aa,bb,cc,dd
删除delete
let setArr=new Set(['aa','bb','cc','aa']); setArr.delete('aa');console.log(setArr)//bb,cc
查找has
let setArr=new Set(['aa','bb','cc','aa']);console.log(setArr.has('aa'));//true
清空clear
let setArr=new Set(['aa','bb','cc','aa']); setArr.clear();console.log(setArr);
Set循环
let setArr=new Set(['aa','bb','cc','aa']);for (let item of setArr) { console.log(item); }
WeakSet的声明
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);
内存空间相同只会插入一个对象
map数据结构
map声明
let obj={ name:"XM", age:"18"};let map=new Map(); map.set("a",obj); map.set("b",1);console.log(map);
取值get
console.log(map.get("b"));
删除delete
map.delete("b")
根据key删除值
size属性
console.log(map.size);
查找是否存在has
console.log(map.has('a'))//true
清除所有元素clear
map.clear()
用Proxy进行预处理
get属性与set属性
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); //触发getpro.name='aaa'; //触发setconsole.log(pro);
apply的使用
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对象的使用
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类的使用
类的声明
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();
模块化操作
export :负责进行模块化,也是模块的输出
import : 负责把模块引,也是模块的引入操作
export的用法
我们新建一个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的用法
有些时候我们并不想暴露模块里边的变量名称,而给模块起一个更语义话的名称,这时候我们就可以使用as来操作。
var a='guo';var b='guoa';var c='guob';export { a as x, b as c, c as v }
export default的使用
加上default相当是一个默认的入口。在一个文件里export default只能有一个。我们来对比一下export和export default的区别
export
export var a ='guo';
对应导入方式
import {a} form './temp';
export defalut
export var a ='guo';
对应导入方式
import str from './temp';
作者:郭少华
链接:https://www.jianshu.com/p/c702f5398387