@(StuRep)javascript
解构:ES6容许按照必定模式,从数组和对象中提取值,对变量进行赋值,这被成为解构。以下:java
//ES5 var a = 1; var b = 2; var c = 3; //ES6 var [a, b, c] = [1, 2, 3]; //嵌套 let [foo, [[bar], baz]] = [1, [[2], 3]]; foo;//1 bar;//2 baz;//3 //若是等号右边不是能够遍历的结构,就没法匹配就会报错。
解构赋值是容许设置默认值的,在ES6内部使用'==='来判断一个位置是否有值。因此,若是一个数组成员不严格等于undefined,默认值是不会生效的。例如:正则表达式
[x, y = 'b'] = ['a', undefined];//x='a',y='b' [x = 1] = [null];//x=null
默认值能够引用解构赋值的其余变量,但该变量必须已经声明。例如:编程
let [x = 1, y = x] = []; //x=1; y=1 let [x = 1, y = x] = [2]; //x=2; y=2 let [x = 1, y = x] = [1, 2]; //x=1; y=2 let [x = y, y = 1] = []; //报错,由于x在使用y做为其默认值的时候y尚未被声明
对象的解构赋值:json
var {foo, bar} = {foo: "aaa", bar:"bbb"}; foo //"aaa" bar //"bbb"
对象的解构赋值和数组有一个重要的不一样:数组的元素是按次序排列的,变量的取值由它的位置来决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
对象的解构赋值能够很方便地将现有对象的方法赋值到某个变量。例如:数组
let {log, sin, cos} = Math; //这样就能够把取对数、正弦、余弦3个方法赋值到对应的变量上面,用起来很方便;
字符串也能够解构赋值,由于字符串会被转换成一个相似数组的对象。例如:浏览器
const [a, b, c, d, e] = 'hello'; a // 'h' b // 'e' c // 'l' d // 'l' e // 'o' let {length : len} = 'hello'; len //5
函数参数也能够解构赋值,例如:babel
function add([x,y]){ return x + y; } add([1, 2]) //3
变量的解构赋值的用途不少,简洁易读:app
[x, y] = [y, x]
;function example(){ return [1, 2, 3]; } var [a, b, c] = example();
函数参数的定义;编程语言
//有序 function f([x, y, z]){...}; f([1, 2, 3]); //无序 function f({x, y, z}){...}; f({z:3, y:2, x:1});
ES6增强了对Unicode的支持,而且扩展了字符串对象。
includes(),startsWith(),endsWith()方法。JS中只有indexOf方法能够用来肯定一个字符串是否包含在另外一个字符串中,ES6又提供了三种方法:
padStart(),padEnd():ES7推出了字符串补全长度的功能。若是某个字符串长度未达指定长度,会在头部或尾部补全。padStart用于头部补全,padEnd用于尾部补全。若是原字符串的长度大于或等于指定的最小长度,则返回原字符串。例如:
'x'.padStart(5, 'ab') //'ababx' 'x'.padStart(4, 'ab') //'abax' 'x'.padEnd(5, 'ab') //'xabab' 'x'.padEnd(4, 'ab') //'xaba' 'xxx'.padStart(2, 'ab') //'xxx'
var regex = new RegExp("xyz", "i");
。在ES6中容许RegExp构造函数接受正则表达式做为参数,这时会返回一个原有正则表达式的拷贝。ES6新增了使用大括号表示Unicode字符的表示法,这种表示法在正则表达式中必须加上u修饰符才能识别。例如:
/\u{61}/.test('a'); //false /\u{61}/u.test('a'); //true
Number.parseInt(),Number.parseFloat():ES6将全局方法parseInt()和parseFloat()移植到了Number对象上。这样是为了逐步减小全局性的方法,使语言逐步模块化。
//ES5 parseInt(''); //ES6 Number.parseInt(''); Number.parseInt === parseInt; //true
Math对象的扩展,ES6在Math对象上新增了17个与数学相关的方法:
Math.imul(-1, 8); //-8
Math.hypot(3, 4);//5
Array.of(3, 11, 8) //[3,11,8]
new Array(3).fill(7) //[7,7,7]
x = x || "XXX"
这样的写法,ES6容许为函数的参数设置默认值,就能够这样写function test(x, y = "xxx"){};
,这样的设计还有一个好处就是开发人员阅读别人的代码一眼就能看出来在调用这个接口哪些参数是可省的。此外,这种写法还能够和解构赋值结合使用,很是灵活。(function(a=5){}).length;//0
ES6引入了rest参数(形式为"...变量名"),用于获取函数的多余参数,这样就不须要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入其中,例如:
function add(...values){ let sum = 0; for(var val of values){ sum += val; } return sum; } add(2, 5, 3); //10 //add函数是一个求和函数,利用rest参数能够向该函数传入任意数目的参数。
console.log(1,...[2,3,4],5);//1 2 3 4 5
;扩展运算符替代数组的apply方法,扩展运算符能够直接把数组拆开,例如:
//ES5 function f(x,y,z){}; var args = [0,1,2]; f.apply(null, args); //ES6 function f(x,y,z){}; var args = [0,1,2]; f(...args);
扩展运算符提供了数组合并的新方法:
//ES5 [1,2].concat(more) //ES6 [1,2, ...more]
箭头函数:ES6容许使用"箭头"(=>)定义函数,例如:
var sum = (num1, num2) => num1 + num2; //等价于 var sum = function(num1, num2){ return num1 + num2; }
使用箭头函数有几个注意点:
foo::bar(...arguments)等价于bar.apply(foo,arguments;)
。感受函数绑定这个设计很是的便捷,不须要在显式的去绑定一下上下文,期待该提案的经过(目前babel已经支持这个写法了);尾递归:函数调用自身称为递归,若是尾调用自身就称为尾递归。递归很是耗费内存,由于须要同时保存成千上百个调用帧,很容易stackoverflow。但对于尾递归来讲,只存在一个调用帧,因此永远不会发生“栈溢出”错误。例如:
//这是一个阶乘函数,计算n的阶乘,最多须要保存n个调用记录,复杂度为O(n)。 function factorial(n){ if(n === 1) return 1; return n * factorial(n - 1); } //改写成尾递归,只保用一个调用记录,则复杂度为O(1); function factorial(n, totla){ if(n === 1) return total; return factorial(n - 1, n * total); }
因而可知‘尾调用优化’对于递归操做的意义很是重大,因此一些函数式编程语言将其写入了语言规格。ES6也是如此,第一次明确规定,全部ECMAScript的实现,都必须部署‘尾调用优化’。这就是说,在ES6中,只要使用尾递归,就不会栈溢出,节省内存。
(未完待续......)