es6语法特性,解构,箭头函数,尾调用优化,proxy,primise,async,装饰器

2023-04-07 13:36:32

1.let,const

let,const定义的变量,不是绑定在window下。

2.解构,ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

//数组解构
let [a, b, c] = [1, 2, 3];
//对象解构
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
//字符串解构
const [a, b, c, d, e] = 'hello';//a=h,b=e ...

3.字符

1.ES6 加强了对 Unicode 的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。

"\uD842\uDFB7"
// "𠮷"

"\u20BB7"
// " 7"

2.ES6 为字符串添加了遍历器接口(详见《Iterator》一章),使得字符串可以被for…of循环遍历。

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

3.模板字符串 `是反引号

`里面的内容被原样输出,包括换行`
`里面的${变量名}`
let func = (name) => `Hello ${name}!`;
func('Jack') // "Hello Jack!"

4.字符串新增了一些方法

1.row()

ES6 还为原生的 String 对象,提供了一个raw()方法。该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。

String.raw`Hi\n${2+3}!`
// 实际返回 "Hi\\n5!",显示的是转义后的结果 "Hi\n5!"

2.传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。都支持第二个参数,表示开始搜索的位置。

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

3.repeat方法返回一个新字符串,表示将原字符串重复n次。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""  如果传的参数是小数,向下取整

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

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

5.ES2019 对字符串实例新增了trimStart()和trimEnd()这两个方法。它们的行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。

5.数值

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

ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。

2.ES6 在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法。

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

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

3.ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。目的,是逐步减少全局性方法,使得语言逐步模块化。

4.ES2016 新增了一个指数运算符(**)。

6.函数

1.函数参数赋默认值

function log(x, y) {
  y = y || 'World';
  console.log(x, y);
}
这种写法的缺点在于,如果参数y赋值了,但是对应的布尔值为false,则该赋值不起作用。就像上面代码的最后一行,参数y等于空字符,结果被改为默认值。所以es6用下面的方法
function log(x, y = 'World') {
  console.log(x, y);
}

参数变量是默认声明的,所以不能用let或const再次声明。
function foo(x = 5) {
  let x = 1; // error
  const x = 2; // error
}

上面代码中,参数变量x是默认声明的,在函数体中,不能用let或const再次声明,否则会报错。

参数默认值可以与解构赋值的默认值,结合起来使用。

function foo({x, y = 5}) {
  console.log(x, y);
}

foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined

函数的length属性

length属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,后文的 rest 参数也不会计入length属性。

(function (a,b=1){}).length//1

2.rest参数(形式为…变量名),用于获取函数的多余参数,

3.ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。

两种方法可以规避这种限制。第一种是设定全局性的严格模式,这是合法的。

第二种是把函数包在一个无参数的立即执行函数里面。

4.函数的name属性,返回该函数的函数名。

5.箭头函数

var f = v => v;
// 等同于
var f = function (v) {
  return v;
};

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

https://blog.csdn.net/w390058785/article/details/82884032

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

6.尾调用优化

尾调用:某个函数的最后一步是调用另一个函数。

function f() {
  let m = 1;
  let n = 2;
  return g(m + n);
}
f();

// 等同于
function f() {
  return g(3);
}
f();

// 等同于
g(3);

上面代码中,如果函数g不是尾调用,函数f就需要保存内部变量m和n的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除f(x)的调用帧,只保留g(3)的调用帧。

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

尾递归:https://www.cnblogs.com/J1ac/p/9326444.html

由于尾递归只存在一个调用记录,所以永远不会发生"栈溢出"错误。

function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}

factorial(5) // 120

上面代码是一个阶乘函数,计算n的阶乘,最多需要保存n个调用记录,复杂度 O(n) 。

如果改写成尾递归,只保留一个调用记录,复杂度 O(1) 。return不用n*

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

factorial(5, 1) // 120
第一次:4,5
第二次:3,20
第三次:2,60
第四次:1,120		返回120

7.proxy

在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

8.promise

三种状态:1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败

只能从1变成2,1变成2,不可以2变3

当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;

then()是用来进行链式编程下去的。

promise是用来解决问题:

  • 异步无法保证输出顺序,通过嵌套达到输出有序。但promise容器本身不是异步的,里面需要放一个异步任务去执行他。
  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise可以支持多个并发的请求,获取并发请求中的数据
  • 这个promise可以解决异步的问题,本身不能说promise是异步的

9.Iterator

作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of消费。

使用和java的类似

10.async

async 函数是什么?一句话,它就是 Generator 函数的语法糖。

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

11.编程风格

1.静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。

2.单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾。

3.模块,import取代require。

4.ESLint 是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。

12.装饰器

类似 java的注解

  • 作者:若等无在
  • 原文链接:https://blog.csdn.net/weixin_45574792/article/details/107332443
    更新时间:2023-04-07 13:36:32