es6学习3

一、字符串的扩展
  1.字符串的遍历器接口
for (let codePoint of 'foo') {
       console.log(codePoint)
}
// "f"
// "o"
// "o"
 
2.includes(), startsWith(), endsWith()
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
var s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

这三个方法都支持第二个参数,表示开始搜索的位置。
var s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

3.repeat()
repeat方法返回一个新字符串,表示将原字符串重复n次。
'x'.repeat(3) // "xxx"

4.padStart(),padEnd()
padStart()用于头部补全,padEnd()用于尾部补全。
如果某个字符串不够指定长度,会在头部或尾部补全。

5.模板字符串
模板字符串中嵌入变量,需要将变量名写在${}之中。
$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);

如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
var greeting = `\`Yo\` World!`;

6.模板编译
JAVASCRIPT
var template = `
<ul>
<% for(var i=0; i < data.supplies.length; i++) { %>
<li><%= data.supplies[i] %></li>
<% } %>
</ul>
`;

7.标签模板
模板字符串前面有一个标识名tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串后的返回值。
var a = 5;
var b = 10;

tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);

二、正则的扩展
三、数值的扩展
1.Number.isFinite()用来检查一个数值是否为有限的(finite)。
Number.isNaN()用来检查一个值是否为NaN。

2.ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45
 
3.Number.isInteger()用来判断一个值是否为整数。

4.Math对象的扩展
a.Math.trunc()
Math.trunc()方法用于去除一个数的小数部分,返回整数部分。
b.Math.sign()
Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
它会返回五种值。
参数为正数,返回+1;
参数为负数,返回-1;
参数为0,返回0;
参数为-0,返回-0;
其他值,返回NaN。
c.Math.cbrt()
Math.cbrt方法用于计算一个数的立方根。
d.Math.clz32()
JavaScript的整数使用32位二进制形式表示,Math.clz32方法返回一个数的32位无符号整数形式有多少个前导0。
e.Math.imul()
Math.imul方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。
Math.imul(2, 4) // 8
Math.imul(-1, 8) // -8
Math.imul(-2, -2) // 4
f.Math.fround()
Math.fround方法返回一个数的单精度浮点数形式。
Math.fround(0) // 0
Math.fround(1) // 1
Math.fround(1.337) // 1.3370000123977661
Math.fround(1.5) // 1.5
Math.fround(NaN) // NaN
g.Math.hypot()
Math.hypot方法返回所有参数的平方和的平方根。
Math.hypot(3, 4); // 5 3的平方加上4的平方,等于5的平方。
h.对数方法
Math.expm1(x)返回ex - 1,即Math.exp(x) - 1。
Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。
Math.log10(x)返回以10为底的x的对数。如果x小于0,则返回NaN。
Math.log2(x)返回以2为底的x的对数。如果x小于0,则返回NaN。
i.双曲函数方法
Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)
Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)
Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)
Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)
Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)
Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)
j.指数运算符(**)
2 ** 2 // 4
2 ** 3 // 8
   
四、函数的扩展
  1.ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x, y = 'World') {
console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

2.参数变量是默认声明的,所以不能用let或const再次声明。

3.使用参数默认值时,函数不能有同名参数。

4.默认实例
// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}

// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]

// x和y都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x有值,y无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]

// x和y都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]

5.通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
如果传入undefined,将触发该参数等于默认值,null则没有这个效果。

6.函数的length属性
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0

7.实例
let foo = 'outer';

function bar(func = x => foo) {
let foo = 'inner';
console.log(func());
}

bar(); // outer
其中func的默认值是一个匿名函数,返回值为变量foo

8.rest参数
ES6 引入rest参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {
let sum = 0;

for (var val of values) {
sum += val;
}

return sum;
}

add(2, 5, 3) // 10
下面是一个 rest 参数代替arguments变量的例子。
// arguments变量的写法
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}

// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

9.严格模式
ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
// 报错
function doSomething(value = 070) {
'use strict';
return value;
}
两种方法可以规避这种限制。
A.第一种是设定全局性的严格模式,这是合法的。
'use strict';

function doSomething(a, b = a) {
// code
}
B.第二种是把函数包在一个无参数的立即执行函数里面。
const doSomething = (function () {
'use strict';
return function(value = 42) {
return value;
};
}());
10.箭头函数
11.绑定 this
函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
return obj::hasOwnProperty(key);
}
如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

12.尾调用优化
尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。
function f(x){
return g(x);
}
“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。

注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。

13.尾递归
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。

递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1);
}

factorial(5) // 120
上面代码是一个阶乘函数,计算n的阶乘,最多需要保存n个调用记录,复杂度 O(n) 。
如果改写成尾递归,只保留一个调用记录,复杂度 O(1) 。
function factorial(n, total) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}

factorial(5, 1) // 120

14.递归函数的改写
第一种方法
function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
}

function factorial(n) {
return tailFactorial(n, 1);
}

factorial(5) // 120
第二种方法就简单多了,就是采用 ES6 的函数默认值。
function factorial(n, total = 1) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}

factorial(5) // 120

猜你喜欢

转载自blog.csdn.net/qq_32439381/article/details/76546416