es6 个人简略笔记
es6常用总结
- 兼容性:http://kangax.github.io/compat-table/es6/
- babel转的是.js文件,如果.html文件不会转
./node_modules/.bin/babel src --out-dir lib
es6支持度
- ie10+、Chrome、FireFox、移动端、node.js
- 若要兼容ie9-,要babel-polyfill具体看官网
在线编译 、提前编译、在线编译器
线上编译
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 地址来自于 https://github.com/babel/babel-standalone -->
<script type="text/babel">
//text/babel 一定要加上
const a='6';
</script>
提前编译(建议这种)(按阮一峰的测试,无效,待测!!!!!)
看babel官网
在线编译器
var、let、const 区别
var
1. 无法限制修改 - 可以重复声明 - 没有块级作用域(for var=i 循环就是个例子)
2. 允许修改原生的。以及,多人合作时,容易覆盖别人的
let
1. 变量可修改 - 不能重复声明 - 有 块级作用域
const
1. 变量不可修改 - 不能重复声明 - 有 块级作用域(即{})
针对let 和 const
- let、const不存在变量提升。顺序执行,访问后来才声明的变量,var是undefined,let、const 会报错
- 只要代码块含有 let、const或其它es6语法,就有块级作用域
- typeOf x 若x未声明,则undefined。若后面是声明let x,就是报错了
- 函数的
function show(x=y,y=2){ //报错! //因为相当于 let x=y;let y=2; 第一句的y还没声明呢 }
若无块级作用域
- 内层变量覆盖外层变量
var a='1' function test(){ console.log(a) if(true){ var a=2 } } test() //undefined - for(var i=0;i<...) i泄露为外层变量
const
- 一声明,就得马上赋值,否则报错
- 常用于常量
- 实质指的是变量指向的那个内存地址不得改动。因此若是对象和数组,保存的就是指针。
- 冻结对象
//新添的属性 无效。自己原有的属性也不能修改。但若属性是对象,便还能修改。因此若想真正冻结,遍历对象的属性 const f=Object.freeze({b:5}) f.a=12; console.log(f.a) //undefined
es6 六种声明变量的方法
var、function、let、const、import、class
顶层对象,以及 this
- es6里,全局变量与顶层对象的属性隔离
let a=1; window.a // undefined -
- 全局环境中,this会返回顶层对象。但,node模块和es6模块,this会返回当前模块
- 函数中的this,若不是作为对象的方法运行,单纯作为函数运行,this指向顶层对象。但严格模式下,this返回undefined
变量的解构赋值
数组
- 左右模式要相同、可以不完全解构、可设默认值
let [a,[b,c]]=[1,[2,3]] let [a,b]=[1] let [a,b,...ha]=[1] //a=1,b=undefined,ha=[] ,...ha 这种一定要放最后 let [a=1]=[10,2,3,4] - es6用的是 === 来判断位置是否有值。另外,如果右边的值是 undefined 就触发默认值
let [x=1]=[undefined] //x=1 let [x=1]=[null] // x=null
对象
- 无关次序,变量与属性名必须相同、可不完全解构、可设默认值、用 === 判断
let {aa=100,bb}={bb:'1',cc:'2',dd:'3'} // aa=100,bb=1 let {x=3}={x:undefined} //x=3 let {x=3}={x:null} //x=null - 重新定义变量名
let {v:value}={v:10} //访问v 报错;访问value,输出10 let {a:a,b:b}={a:1,b:2} //实际是这样的 ,但一般会简写成 let {a,b} - 可嵌套赋值,例如和数组
let obj={ p:[ 'me', {who:'you'} ] } let {p:[x,y]}=obj //访问p,报错 is not defined ;而 访问 x='me',y={who:'you'} let {p,p:[c,{who:k}]}=obj //p 有对应的值了 ;而 访问 c='me',k={who:'you'} - 让 A对象的属性aa 直接赋给 B对象的属性bb,数组一样
let obj={second:0}; // 这里必须加”;“,否则第三句报错 let arr=[];// 这里必须加”;“,否则第三句报错 ({a:obj.frist,b:obj.second,c:arr[0]}={a:10,b:100,c:50}) //不能let 声明了,否则报错。且必须有括号(),否则报错 - 让 数组的某一项arr[3] 直接存为变量。(数组本质是特殊的对象)
let arr=[1,2,3] let {0:first,[arr.length-1]:last}=arr //first=1,last=3
字符串、数值(转Number对象)、布尔值(转Boolean对象)
- 只要右边的值不是对象或数组,就先将其转为对象(包括类似数组的对象)
let [a,b,c]='hello' // a='h' b='e' c='l' let {length:len}='hello' // len= 5 //注意,这里是指 toString 这个方法 赋值给了 s, 是s===Number.property.toString let {toString:s}=123 //但是... let a=456 let num1=a.toString() // 是 456 let num2=a.s() // 报错! a.s is not a function let {toString:s}=true;
函数参数 *
- 可设默认值
function add([x,y]){} add([1,3]); [[1,2],[3,4]].map(([x,y])=>{ // 结果[3,7] return x+y }) // 如果B对象传入,就使用B对象的,再判断B对象是否有x,y属性,否则使用设定的默认值 //如果传进来的是空对象或 什么都没传,用设定的默认值 function move({x=1,y=2}={}){} move({x:3,y:4})
圆括号问题 (看书,p43)
函数的扩展
参数的默认值
- 参数是默认声明的,故函数内部不能再次声明
- fun(x,x,y)报错,不能有同名参数
- 如果参数是一个对象,参数等号的右边最好设置{},如 {x,y}={}
function fun({x,y=5}){ } fun() //直接报错,解构赋值的前提是,左右模式一致。fun()相当于fun(undefined)了,模式都不对 fun() //有效 // 或者改为如下,第一个fun()调用就不报错了 function fun({x,y=5}={}){ } - 如果想使用默认值,传 undefined
//es5 function add(a,b,c){ } add(1,,3)// 报错,js语法编写上报的错 Unexpected token //es6 // 同样,es6的add(,3)也会报错 function add(a=1,c){ } add(undefined,3) //触发默认值,a=1 add(null,3) // a=null - 函数的length属性
//只计算 第一个默认值 a=5 或 ...arr 前面的参数个数,这两种后面的参数都不算 let a=(function(a){}).length //1 let b=(function(a,b,c=5){}).length //2 let c=(function(a,b,c=5,d,e=6,f){}).length //2 let d=(function(...arr){}).length //0 let e=(function(a,b,...arr){}).length //2 - 作用域
//设置默认值,就会形成单独作用域 //函数参数 y=a ,变量a,先在(参数1、参数2...)里找。如果没有,就在全局找。如果都没有,就报错 var a=1 function fun1(a,y=a){} // y=a 的a 对应的 函数第一个的参数a function fun2(y=a){} // y=a 的a对应 var a=1 这个a - 应用:让调用者 必须带参数
function throwError(){ throw new Error('请传入参数') } function fun(x=throwError()){ return x } fun() //报错 fun(2) // 不报错
- ...arr必须是最后一个,否则报错
let a=[1] let b=[1] function push(x,y,...values){ a.push(...values) //逐个的参数 b.push(values) // 该变量 变为了数组 } push(2,3,4) // a=[1,2,3,4] b=[1,[2,3,4]]
严格模式
- es6只要函数使用了 默认值、解构赋值、或扩展运算符(...),函数内部就不能显式设定严格模式,否则就报错。
name属性,返回函数名
- 以下 均为es6 的情况
var f=function(){} // f.name 输出 f ,若es5 输出空字符串"" var f=function ha(){} // f.name 输出 ha ,若es5 输出空字符串"" (new Function).name // 输出 anonymous //1、bind 返回的函数,会加上bound前缀 function fun(){} fun.bind({}).name //输出 bound fun console.log(fun.bind({}).name)
箭头函数
- 基本使用
var f=()=>{} //没有参数 var f=v=>{} //只有一个参数 var f=(num,num2)=>console.log(num+num2) //代码块只有一句话,可省略 {},同时也省略了 "return" var f=(num,num2)=>{let a=num+num2; console.log(a)} //代码块多于一句话,必须加 {} var f=v=>({v:v1,a:'a'}) //返回对象,必须加括号()。因为{}会解释为代码块 var f=({first,second})=>{} //与变量解构结合使用 - 注意事项
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象
- 不可当构造函数,即 new Person() 这种,因为箭头函数没有自己的this
- 不可使用arguments 对象,该对象在函数体内不存在。若要用,用 ...arr 这种代替
- 不可用yield命令,因为箭头函数不能用作Generator函数
//若是普通函数,执行时,指向全局window对象,应输出21。但因箭头函数 输出42 function foo(){ setTimeout(()=>{ console.log('id:',this.id); //箭头函数,输出42 },100); setTimeout(function(){ console.log('id:',this.id); //普通函数,输出21 },200) } var id=21; foo.call({id:42}); foo(10,100); // arguments // 个人觉得:因为 this是绑定当前定义的对象,arguments同理,但箭头函数内又不能使用 arguments 。所以,用箭头函数定义时会报错,而用function 定义函数时 正常 var foo2=()=>{ setTimeout(()=>{ console.log('foo2',arguments[1]) //报错,arguments is not defined },300) } foo2(1,2,3) function foo3(){ setTimeout(()=>{ console.log('foo3',arguments[1]) //输出100 },300) } foo3(1,2,3) //箭头函数里面的this,总是指向handle对象。否则,回调函数运行时,this.doFun会报错,因 为指向的是document对象 var handle={ init:function(){ document.addEventListener('click',event=>{ this.doFun() }) }, doFun:function(){ console.log('哈哈') } } //不能用 call()、bind()、apply()改变this的指向 function fun(){ return (()=>this.x).bind({x:'inner'})() // return (function(){return this.x}).bind({x:'inner'})() //如果换成这一 句,输出inner } console.log(fun.call({x:'outer'})) //输出 outer
- 嵌套的箭头函数
- 管道机制,即前一个函数的输出是后一个函数的输入
const pipeLine=(...items)=>val=>items.reduce((a,b)=>b(a) ,val); const plus1=a=>a+1 const mult2=a=>a*2 const addThenMult=pipeLine(plus1,mult2); console.log( addThenMult(5) ) //输出12 console.log( mult2(plus1(5)) ) //输出12,跟上一句是同样的// 上面的其实展开就是如下 const pipeLine = function (...items) { return function (val) { console.log('val:',val) // 输出5 console.log(items) return items.reduce(function (a,b,index){ console.log('---', a,b,index) return b(a) }, val) //这里的val是设置总和的初始值,即设置 a=5 } };
- 管道机制,即前一个函数的输出是后一个函数的输入
数组的扩展
扩展运算符(...)
- 使用:函数参数必须最后一个点击跳转 ...values例子,但调用时可任意位置,如:
var arr=[1,2,3] fun("18",...arr,100) //若是空数组[],不产生任何效果 [...[],1] //[1] - 替代es5中的apply方法、concat()
注意*,扩展运算符,若用于数组赋值,只能将其参数放最后一位,否则报错// aplly方法 function fun(x,y,z){} var args=[0,2,3] fun.apply(null,args) //es5 fun(...args) //es6 var arr1=[1,2,3] var arr2=[4,5,6] Array.prototype.push.apply(arr1,arr2) //es5 arr1 =[1, 2, 3, 4, 5, 6] arr1.push(...arr2) //es6 // 合并数组 var arr3=arr1.concat(arr2); //es5 [1,2, ...arr2] //es6const [first,second,...arr]=[1,2,3,4] - 将字符串转数组
[...'hello'] //['h','e','l','l','o']
Array.from() 将对象转数组
- 第一个参数 (类似数组的对象 和 可遍历的对象)
//得是这种风格,且length属性是必需的。即任何具有length属性的对象,都能转为数组 let obj={'0':'AA','1':'BB',length:2} Array.from(obj) //['AA','BB'] let obj2={b:'bb',length:3} Array.from(obj2) //[undefined, undefined, undefined] // NodeList对象 let ps=document.getElementsByTagName('p'); Array.from(ps); [...ps] //扩展运算符(...)也能将某些数据结构转对象 // arguments对象 function foo(){ var args=Array.from(arguments); var args=[...arguments] } //字符串 Array.from('hello') - 第二个参数,类似于map方法
补充*:如果浏览器还没有部署该方法的,可用以下替换let ps=document.getElementsByTagName('p'); let names=Array.from(ps,item=>item.textContent);const toArray=(()=> Array.from?Array.from:obj=>[].slice.call(obj) )(); toArray({'0':'AA','1':'BB',length:2}) //['AA','BB']
Array.of() 将一组值转数组
- 如下:
补充*:可用以下代码模拟Array.of(1,3,8) //[1,3,8]function ArrayOf(){ return [].slice.call(arguments) } ArrayOf(1,2,3)//[1,2,3]
.copyWithIn() 复制
- 复制原数组的B段 覆盖在原数组上A段。三个参数:
- 一:A段的起始位置(必选)
- 二:B段的起始位置(可选),默认0,负值为倒数
- 三:B段的末位置的下一个位置(可选),默认数组长度,负值为倒数
[1,2,3,4,5].copyWithin(0,3,4); //[4,2,3,4,5] // 负值,-3相当于索引2位置 [1,2,3,4,5].copyWithin(0,-3,-1) //[3,4,3,4,5]
.find() 返回值 & .findIndex() 返下标
- 找到第一个符合条件的,就返回,效率好。.find(),如无符合的,则返 undefined,.findIndex() 则返-1
[1,3,9,100,200].find((value,index,arr)=>value>50) //100 [1,3,9,100,200].findIndex(value=>value>500) //-1 - 这两个方法都都返回第二个参数绑定回调函数的this对象
- 可以发现NaN,弥补IndexOf的不足
[NaN].indexOf(NaN) //-1 [100,NaN].findIndex(y=>Object.is(NaN,y)) // 返下标1
.fill() 填充数组
- 三个参数:填充值、填充的起始位置、填充的末位置的下一个位置
['a','b','c'].fill(7);// [7,7,7] new Array(3).fill(0);// [0,0,0] 填充空数组非常有用 ['a','b','c'].fill(7,1,2); //['a',7,'c']
.entries()、.keys()、.values()
- 遍历数组
var arr=[10,100,1000] for(let item of arr.keys()){} //返 下标index for(let item of arr.values()){} //返 值 for(let [index,item] of arr.entries()){} //返 键值对
.includes() 返布尔值
- 判断数组是否包含某个值
[NaN].includes(NaN); //true - 第二个参数则是 搜索的起始位置,若为负,表示倒数,若大于数组长度,则置0
- 若考虑浏览器的环境,兼容写法
const contains=(()=> Array.prototype.includes?(arr,value)=>arr.includes(value):(arr,value)=>arr.some(el=>el===value) )(); contains(['foo','baz'],'baz'); // true
空位
- es6 是将数组的空位转 undefined,如 Array.from()

浙公网安备 33010602011771号