这篇可以帮助刚入门的小伙伴对es6有个简单的理解。
常量对比
// es5常量写法
Object.defineProperties(window,"PI2",{
value:3.14159,
writable:false,//只读不可写
})//需要用api去声明常量。给对象定义一个属性,让这个属性变成只读,常量挂载在window下
//运行
console.log(window.PI2)
//es6常量写法,不需要api声明常量
//声明一个常量
const PT=3.14159//只读,不允许给其赋值
console.log(PI)
作用域
//es5的写法
const callbacks=[]//声明一个数组
for(var i=0;i<=2;i++){//用的是var声明的一个i变量,会得到一个变量的提升,因为var i=0放在前面,不属于for循环只内的,
//但赋值callbacks[0],var i是从callbacks[0]取值为0,
callbacks[i]=function(){//但是这个函数并没有把这个i取值为0,
return i*2 //这里是对变量的引用并不是对变量的值的引用,所以这个函数体内是一个表达式而不是一个值,而这个表达式用到的是i变量,所以这里会有一个闭包
}
}//所以执行callbacks[0]()的时候,i已经变成3了
//因为这个闭包的作用域i就是一个全局
console.table([
callbacks[0](),
callbacks[1](),
callbacks[2](),
])
//输出的值都是6
//es6中的作用域
const callbacks2=[]
for(let j=0;j<=2;j++){//用let声明的变量会有一个叫跨作用域的一个概念,也就是以下的闭包是取决于当前的跨作用域,他会把当前跨作用域下的变量保存下来供后面的闭包所使用,循环的时候没循环一次就会重新生成一次新的作用域,所以这闭包就会导向闭包中的作用域的导向
callbacks2[j]=function(){
return j*2
}
}
console.table([
callbacks2[0](),
callbacks2[1](),
callbacks2[2](),
])
//输出为0 2 4
立即执行函数
//es5立即执行函数
(function(){//这个作用域是有个函数,也就是说这个作用域在函数体内,声明了一个变量是有个foo函数
const foo=function(){
return 1
}
console.log("foo()===1",foo()===1)
//为了分隔这个作用域就叫立即执行作用域
;((function(){
const foo=function(){
return 2
}
console.log("foo()===2",foo()===2)
})())
})()//声明了两个函数,表示的是整两个函数已经被两个作用域给隔离开,在es5中保证一块代码要执行所在作用域的问题
//输出的是foo()===1 true
// foo()===2 true
//es6就会很简单直接用{}就能指定一个跨作用域
{
function foo(){
return 1
}
console.log('foo()===1',foo()===1);
{
function foo(){
return 2
}
console.log('foo()===2',foo()===2);
}
}
//也就是说在es6中,一个{}就把作用域进行了隔离,而在es5中必须使用立即执行函数(function(){})()才能对作用域进行隔离
箭头函数
function a(){()=>{
//()是声明参数的,如果参数只有一个的话这个()是可以被省略的,如果{}中的表达式直接作为返回值的话是可以省略{}的
}}
//es5声明一个函数
{ //es5,es3中对数组的遍历
var evens=[1,2,3,4,5];
var odds=evens.map(function(v){
return v+1
})
console.log(evens,odds);
}
//输出结果为 [1,2,3,4,5] [2,3,4,5,6]
{
//es6中的写法
let evens=[1,2,3,4,5];
let odds=evens.map(v => v + 1)
console.log(evens,odds);
}
//输出结果为 [1,2,3,4,5] [2,3,4,5,6]
//箭头函数跟普通函数的区别
//es3,es5
{
var factory=function(){
this.a='a';
this.b='b';
this.c={
a:'a+',
b:function(){
return this.a
}
}
//this的指向是该函数被调用的对象,也就是所函数被执行的时候,this指向的是哪个对象调用的function,也就是
//b()是c调用的,而c本身就是一个对象,所以这个this指向的是c,c中的a也就是a+
}
console.log(new factory().c.b())//输出结果为 a+
};
//es6写法
{
var factory=function(){
this.a='a';
this.b='b';//这里的this指向的是这个构造函数factory的实例
this.c={
a:'a+',
b:()=>{
return this.a
}//b在定义这个函数的时候this指向的是函数体中的this的
}
}//箭头函数中this的指向是定义式this的指向
console.log(new factory().c.b())//输出结果为 a
// new factory().c.b()中c.b()实例就是 new factory(),而new factory()的实例也就是这个构造函数中的a
}//这就是es6中的箭头函数
默认参数
//默认参数
function a(x,y){
x=x||1;
y=y||2;
};
{
//es3,es5中的写法
function f(x,y,z){
if(y===underfined){
y=7;
}
if(z===underfined){
z=42
}
return x+y+z
}
console.log(f(1,3) )//输出 46
};
{
//es6
function f(x,y=7,z=42){
return x+y+z
}
console.log(f(1))//输出50
console.log(f(1,3))//输出46,默认参数起作用
}
可变参数
{
//es3,es5可变参数
function f(){
var a=Array.prototype.slice.call(arguments)//argument是一个伪数组,他不是一个真正的数组
var sum=0;
a.forEach(function(item){
sum+=item*1
})
return sum;
}//通过arguments来获取函数当前的参数列表然后进行一个循环一个运算,这就是一个可
//变参数的获取然后的一个求和
console.log(f(1,2,3));//输出结果 6
console.log(f(1,2,3,6));//输出结果 12
}
{
//es6中的可变参数
function f(...a){//...a是一个扩展运算符,a表示的就是一个可变参数的列表而且它是一个数组
var sum=0;
a.forEach(item=>{
sum+=item*1
})
return sum;
}//在es6中去获取一个可变的参数只需要...a,不需要伪数组什么的了
console.log(f(1,2,3));//输出结果 6
console.log(f(1,2,3,6));//输出结果 12
}
…a还可以有其他的用途,在es6中可用合并,如下所示:
{
//es5关于合并,合并数组
var params=['hello',true,1];
var other=[1,2].concat(params);//把[1,2]数组与patams合并
console.log(other);//输出[1,2,'hello',true,7]
}
{
//es6利用扩展运算符合并数组
var params=['hello',true,1];
var other=[1,2,...params];//把[1,2]数组与patams合并
console.log(other);//输出[1,2,'hello',true,7]
}
对象代理,解决私有变量的问题,数据的隐私保护,添加有个代理层对原始数据达到一个保护的效果
{
//es3数据保护
var Preson=function(){
var data={//内部声明一个局部作用域,因为没有被类访问到,所以对象的实例是拿不到data的数据的,我们就是利用这个原理把数据保护起来
name:'es3',
sex:'male',
age:15
}
//或想让外部去操作这个数据,只能get添加一个api
this.get=function(key){
return data[key]//读取走这个借口
}
//想赋值,这时候要检查
this.set=function(key){
if(key!=='sex'){
data[key]=value//如果key不等于性别就可以进行赋值
}
}
}
//声明一个实例
var person =new Preson();
//读取
console.table({
name:person.get('name'),
sex:person.get('sex'),
age:person.get('age'),
})
//修改
person.set('name','es3-cname');
console.table({
name:person.get('name'),
sex:person.get('sex'),
age:person.get('age'),
})//输出的表格中name已经被修改为es3-cname
person.set('sex','csex');
console.table({
name:person.get('name'),
sex:person.get('sex'),
age:person.get('age'),
})//输出的表格中sex没有被修改,因为进行判断了,sex不允许修改
}
{
//es5中的数据保护
var Person={
name:'es5',
age:15
};
Object.defineProperties(Person,'sex',{
writable:false,
value:'male'
})//在es5中利用这个api达到一个只读的效果,也就达到一个保护的效果,只读不可写
console.table({
name:Person.name,
sex:Person.sex,
age:Person.age,
})
Person.name='es5=cname';
console.table({
name:Person.name,
sex:Person.sex,
age:Person.age,
})//输出的表格中name已经被修改为es5=cname
Person.sex='es5=sex';
console.table({
name:Person.name,
sex:Person.sex,
age:Person.age,
})//报错,不能给一个只读的属性赋值
}
{
//es6
let Person={
name:'es6',
sex:'male',
age:15
};
let person=new Proxy(Person,{//new Proxy()是es6提供的一个原生的语法,一个代理,也就是代理Person
//代理之后可以写一个get和set的操作
get(target,key){
return target[key]
},
set(target,key,value){
if(key!=='sex'){
target[key]=value
}
}
})//这个person是将来暴露给用户操作的一个对象,把最前面的Person保护起来,以后操作的就是这个person,
//二这个person通过Proxy()这个代理挂上钩,代理的就是一个原始数据,这里面的target就是代理的数据,key就是数据里面的属性
console.table({
name:person.name,
sex:person.sex,
age:person.age
})
//修改
try{
person.sex='female';
}catch(e){
console.log(e)
}finally{
}//报错,不允许修改
}
好啦,以上就是对es6相比于es5,es3的不同之处做了简单的对比。
需要转载的麻烦备注文章来源