ES6学习笔记二:各种扩展

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7242967.html

一:字符串扩展

1:字符串遍历器

for (let char of str) {
  //
}

这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。

2:确定一个字符串是否包含在另一个字符串中

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。

3:字符串重复n次

str.repeat(n) //strstrstr...重复n次

如果repeat的参数是负数或者Infinity,会报错。

4:字符串补全到所需长度

padStart(n,sub)用于头部补全,padEnd(n,sub)用于尾部补全。

用sub把字符串在头/尾补全到n长度。

如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

如果省略第二个参数,默认使用空格补全长度。

5:模版字符串

在js代码中,可以用 反引号  定义模版字符串,模版字符串中可以使用 ${变量、调用函数、js表达式} 来插入值。

$('#result').append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${fn()}</em>
  are on sale!
`);

6:标签模版

是一种特殊的函数调用形式:模版字符串跟在一个函数名后面,“标签”指的就是函数,紧跟在后面的模板字符串就是函数的参数。

如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。

var a = 5;
var b = 10;

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

7:raw()

String.raw方法,用来充当模板字符串的处理函数,对模版字符串中每一个斜杠都转义(即斜杠前面再加一个斜杠),然后返回替换原模板字符串。

String.raw`Hi
${2+3}!`;
// "Hi\n5!"

如果原字符串的斜杠已经转义(即:已经有转义),那么String.raw不会做任何处理。

二:正则的扩展

1:正则表达式的创建:第一个参数是模式字符串,这时第二个参数表示正则表达式的修饰符(flag)。

var regex = new RegExp('xyz', 'i');

修饰符:
g:全局修饰符

u:unicode修饰符

y修饰符,叫做“粘连”(sticky)修饰符:后一次匹配都从上一次匹配成功的下一个位置开始,y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

s修饰符:dotall模式,使得 . 可以匹配包括行终止符在内的一切内容。

2:字符串对象共有4个方法,可以使用正则表达式:match()replace()search()split()

3:返回修饰符

新增了flags属性,会返回正则表达式的修饰符。

/abc/ig.source
// "abc"

// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'

三:Number的扩展

1:二进制和八进制表示法:

 分别用前缀0b(或0B)和0o(或0O)跟数字 来表示二进制和八进制数据。

0b111110111 == 503
0o767 == 503

如果要将0b0o前缀的字符串数值转为十进制,要使用Number方法:

Number('0b111')  // 7

2:检查数据是否有效、是否非数

Number.isFinite(number)用来检查一个数值是否为有限的(finite)。

Number.isNaN(number)用来检查一个值是否为NaN

3:字符串数字转化为数字

Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45

4:Number.isInteger()用来判断一个值是否为整数。

5:极小值

新增一个极小的常量Number.EPSILON

引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围,如果这个误差能够小于Number.EPSILON,我们就可以认为得到了正确结果。

 6:整数范围

JavaScript能够准确表示的整数范围在-2^532^53之间(不含两个端点)。

ES6引入了Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。

Number.isSafeInteger(number)则是用来判断一个整数是否落在这个范围之内。

7:Math新增方法

Math对象上新增了17个与数学相关的方法。所有这些方法都是静态方法,只能在Math对象上调用。

1)取小数的整数部分

Math.trunc方法用于去除一个数的小数部分,返回整数部分。

2)判断正负

Math.sign方法用来判断一个数到底是正数、负数、还是零。

它会返回五种值。

  • 参数为正数,返回+1;
  • 参数为负数,返回-1;
  • 参数为0,返回0;
  • 参数为-0,返回-0;
  • 其他值,返回NaN。

3)立方根

Math.cbrt方法用于计算一个数的立方根。

4)求参数平方和的平方根

Math.hypot()方法返回所有参数的平方和的平方根。

5)Math.log10(x)返回以10为底的x的对数。如果x小于0,则返回NaN。

6)Math.log2(x)返回以2为底的x的对数。如果x小于0,则返回NaN。

7)6个双曲函数方法。

  • 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)

8)指数运算符(**):a**b=a的b次幂

四:函数扩展

1)函数在定义时,可以为参数指定默认值(同python一样,默认值参数要放在参数列表后面部分)

2)调用函数时,可以通过解构赋值来传参

3)多余参数:

ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数。

rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

function add(...values) {
  let sum = 0;

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

  return sum;
}

rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

4)箭头函数:参数=>函数体

简单的箭头函数:var f=(参数)=>返回值

var sum = (num1, num2) => num1 + num2;

复杂的箭头函数:函数体多于一个语句,则用{}括起来,用return返回结果

var sum = (num1, num2) => { ......;return num1 + num2; }

箭头函数使得表达更加简洁

5)尾调用优化

尾调用(Tail Call)是函数式编程的一个重要概念,指某个函数的最后一步是调用另一个函数。【最后一步不等于最后一条语句,而是在return语句的最末尾处】

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,所以可以删除外部函数调用帧,只保留内层尾调用的函数帧即可。

这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。

6)尾递归:优化递归溢出的方法

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

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

尾递归的实现,往往需要改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数。 

函数式编程有一个概念,叫做柯里化(currying),意思是将多参数的函数转换成单参数的形式:

function currying(fn, n) {//定义currying函数:在函数内部调用参数函数
  return function (m) {
    return fn.call(this, m, n);
  };
}

function tailFactorial(n, total) {
  if (n === 1) return total;
  return tailFactorial(n - 1, n * total);
}

const factorial = currying(tailFactorial, 1);

7)尾递归优化:把递归转化为循环

function tco(f) {
  var value;
  var active = false;
  var accumulated = [];

  return function accumulator() {
    accumulated.push(arguments);
    if (!active) {
      active = true;
      while (accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}

var sum = tco(function(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1)
  }
  else {
    return x
  }
});

sum(1, 100000)

tco函数是尾递归优化的实现,奥妙就在于状态变量active。默认情况下,这个变量是不激活的。一旦进入尾递归优化的过程,这个变量就激活了。然后,每一轮递归sum返回的都是undefined,所以就避免了递归执行;而accumulated数组存放每一轮sum执行的参数,总是有值的,这就保证了accumulator函数内部的while循环总是会执行。这样就很巧妙地将“递归”改成了“循环”,而后一轮的参数会取代前一轮的参数,保证了调用栈只有一层

五:数组扩展

1)扩展运算符

 扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列

function push(array, ...items) {
  array.push(...items);
}
function f(x, y, z) {
  // ...
}
var args = [0, 1, 2];
f(...args);

扩展运算符的应用:

合并数组:

// ES6的合并数组
var combine=[...arr1, ...arr2, ...arr3]

把字符串转化为字符数组:

[...'hello']
// [ "h", "e", "l", "l", "o" ]

拆分任何可迭代对象成为数组:

let arr = [...可迭代对象];

2)将对象转为数组

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象Array.from都可以将它们转为真正的数组。

Array.from还可以接受第二个参数(处理函数),作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

Array.from(arrayLike, x => x * x);

3)将一组离散值转化为数组

Array.of方法用于将一组值,转换为数组。

Array.of(3, 11, 8)

4)数组对象的内部复制

copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。

Array.prototype.copyWithin(target, start = , end = )

它接受三个参数:

  • target(必需):从该位置开始替换数据。
  • start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

5)数组查找方法

find方法:用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个回调函数返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined

[1, 4, -5, 10].find((n) => n < 0)

findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2

6)数组填充

fill方法使用给定值,填充(覆盖)一个数组。【相当于memset】

['a', 'b', 'c'].fill(7)
// [7, 7, 7]

fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

7)数组遍历

entries()keys()values():返回一个遍历器对象,可以用for...of循环进行遍历:

keys()是对键名(下标)的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

8)是否包含

includes方法返回一个布尔值,表示某个数组是否包含给定的值:

[1, 2, 3].includes(2)

第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置:

[1, 2, 3].includes(3, -1); // true

六:对象扩展

 1)属性简写

ES6允许在对象之中,把外面定义的变量作为自己的属性:属性名为变量名, 属性值为变量的值。

var foo = 'bar';//定义变量
var baz = {foo};//把变量作为对象属性

2)方法简写

对象内定义方法,可以不加function前缀:

var o = {
  method() {
    return "Hello!";
  }
};
// 等同于
var o = {
  method: function() {
    return "Hello!";
  }
};

3)属性的getter和setter:用get、set声明函数

const obj = {
  get foo() {},
  set foo(x) {}
};

4)对象的值相等比较

ES6提出“Same-value equality”(同值相等)算法,Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

Object.is(obj1, obj2)

5)对象合并

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

第一个参数是目标对象,后面的参数都是源对象:

var target = { a: 1, b: 1 };

var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用,这个对象的任何变化,都会反映到目标对象上面。

 6)对象属性的遍历

ES6 一共有5种方法可以遍历对象的属性。

(1)for...in

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举。

7)Object.keys(),Object.values(),Object.entries()

Object.keys方法:返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。

Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

8)对象的扩展运算符
扩展运算符  ...  不仅可以作用于数组,也可以作用于对象。

对象的解构赋值:用于从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
原文地址:https://www.cnblogs.com/ygj0930/p/7242967.html