es6入门语法和扩展总结一
读了阮一峰大神的《ECMAScript 6 入门》后,总结下常用的语法和一些扩展的知识点。
目录
常用的
变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 -------《ECMAScript 6 入门》 阮一峰
例子
- 默认值(通用)
let [x = 1, y = x] = [];
var {x = 3} = {};
- 数组 (事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值),原来有Iterator接口不止java呀 😄
let [a, b, c] = [1, 2, 3];
let [x, y, z] = new Set(['a', 'b', 'c']);
- 对象
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
- 函数参数
function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8]
用途 ✓
-
a,b值互换
let x = 1; let y = 2; [x, y] = [y, x];
-
提取 JSON 数据 (项目中使用最多的)
可以直接从对象中提取所要的数据,很方便优雅let user = { id: '000', name: "A", email: '' }; let { id, name, email } = user;
-
加载输入模块的指定方法
import { Message } from 'element-ui'
正则
RegExp对象方法
方法 | 描述 |
---|---|
compile | 编译正则表达式。 |
exec | 检索字符串中指定的值。返回找到的值,并确定其位置。 |
test | 检索字符串中指定的值。返回 true 或 false。 |
字符串对象共有 4 个方法,可以使用正则表达式:match()、replace()、search()和split()。
方法 | 描述 |
---|---|
search | 检索与正则表达式相匹配的值。 |
match | 找到一个或多个正则表达式的匹配。 |
replace | 替换与正则表达式匹配的子串。 |
split | 把字符串分割为字符串数组。 |
- 例子
var message='I am 18 years old' var reg=/\d+/g var match=reg.exec(message) var exist=reg.test(message) reg.compile(/[A-Z]+/g) // 编译之后的正则表达式执行速度将会提高,如果正则表达式多次被调用,那么调用compile方法可以有效的提高代码的执行速度,如果该正则表达式只能被使用一次,则不会有明显的效果。 ----参考 https://www.imooc.com/qadetail/247367 match=reg.exec(message) message.search(reg) // 0 index位置 message.match(reg) // ["I"] message.replace(reg,'i') // i am 18 years old message.split(' ') //["I", "am", "18", "years", "old"] /** match 值: 0: "18" index: 5 input: "I am 18 years old" groups: undefined exist 值: true compile 后 的 match 值: 0: "I" index: 0 input: "I am 18 years old" groups: undefined */
Number
- Number.parseInt(‘12.34’) // 12
- Number.isNaN(NaN) // true
- Math.trunc(‘123.456’) // 123 用于去除一个数的小数部分,返回整数部分
函数
ES6 允许使用“箭头”(=>)定义函数。
注意点:
- 函数体内的this对象,感觉这个就是指当前对象呀(java级理解 哈哈哈)
var id=22 function foo(obj){ console.log(this.id,obj.id) //22 11 this为调用foo的对象即window,Obj为传入的对象{id:11} } function foo2(){ console.log(this.id) //11 this为调用foo2的对象{id:11},结果为11 } //call 函数的第一个参数为调用该方法的对象,后面的为方法的参数 foo.call(this,{id:11}) foo2.call({id:11})
扩展(新大陆 Σ(っ °Д °;)っ
字符串的遍历器接口
for (let codePoint of 'foo') { console.log(codePoint) } // "f" // "o" // "o"
标签模板
“标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。 -------《ECMAScript 6 入门》 阮一峰
经常用在评论,留言这块
- 模板字符串,是普通字符串的增强版,用反引号 ` 标识,除了可以写多行的字符串外,我们还可以通过 ${} 引用定义的变量!
var message='hello' var div=` <div>1 ${message}</div> <div>2 ${message}</div> <div>3 ${message}</div> ` console.log(div)
- String.raw()
String.raw()是专用于模板字符串的标签函数,该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串 -------《ECMAScript 6 入门》 阮一峰
``` String.raw`Hi\n` === "Hi\\n" //true ```
补全字符串
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。 -------《ECMAScript 6 入门》 阮一峰
'hi'.padStart(5, '*') // "***hi" 'hi'.padEnd(5, '*') //"hi***"
正则
先行断言
“先行断言”指的是,x只有在y前面才匹配,必须写成/x(?=y)/
先行否定断言 必须写成/x(!=y)/ 即不在y前面的x
/\d+(?=\$)/.exec("It's 100$") //100 /\d{2}(?!a)/.exec("12a 34b") //34 先行否定断言 必须写成/x(!=y)/ 即不在y前面的x
后行断言
x只有在y后面才匹配,必须写成/(?<=y)x/
“后行否定断言”,x只有不在y后面才匹配,必须写成/(?<!y)x/
/(?<=\$)\d+/.exec("It's $100") //100 /(?<!a)\d{2}/.exec("a12 b34b") //34
函数
尾调用优化
尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。
// 情况一 调用函数g之后,还有赋值操作,所以不属于尾调用 function f(x){ let y = g(x); return y; } // 情况二 也属于调用后还有操作 所以不属于尾调用 function f(x){ return g(x) + 1; } // 情况三 最后一步为 return undefined; 所以不属于尾调用 function f(x){ g(x); }
每次调用函数时,都会产生一个调用栈(会进行一个压栈的操作,栈的特点是先进后出,看看下面的例子),而尾调用是函数的最后一步操作,可以直接用内层函数的调用帧替换外层函数。
function getB(){ //第四步: 执行getB函数中的代码 return 'B' } function c(a,b){ return a+b } function foo() { //第二步: 执行foo函数中的代码 let a=1 let b=getB(); // 第三步: 调用 getB 函数 getB 进栈 return c(a , b); //第五步:调用c函数 c进栈 执行尾调用优化 } foo(); //第一步:调用foo函数 foo进栈
代码流程浅析:
操作 | 栈 |
---|---|
1. 调用foo函数 | foo 进栈 |
2. 执行foo函数中的代码 | |
3. 调用 getB 函数 | getB 进栈 |
4. 执行getB函数中的代码 | |
5. getB 函数执行完 | getB 出栈 |
6. 调用 c 函数(尾调用) | 用c的栈帧替换foo的栈帧 |
7. 执行 c 函数中的代码 | |
8. c 函数执行完 | c 出栈 |
注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”
尾递归 ✓ (牛!)
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
递归时会容易造成这个stack overflow,但是尝试将代码改成尾递归之后,那个速度就是飞起了。
function Fibonacci (n) { if ( n <= 1 ) {return 1}; return Fibonacci(n - 1) + Fibonacci(n - 2); } function Fibonacci2 (n , ac1 = 1 , ac2 = 1) { if( n <= 1 ) {return ac2}; return Fibonacci2 (n - 1, ac2, ac1 + ac2); } console.time("Fibonacci(10) time"); Fibonacci(10) // 89 console.timeEnd("Fibonacci(10) time"); console.time("Fibonacci(20) time"); Fibonacci(20) console.timeEnd("Fibonacci(20) time"); console.time("Fibonacci(40) time"); Fibonacci(40) console.timeEnd("Fibonacci(40) time"); console.log('----------------------------') console.time("尾递归优化过的Fibonacci2(10) time"); Fibonacci2(10) console.timeEnd("尾递归优化过的Fibonacci2(10) time"); console.time("尾递归优化过的Fibonacci2(20) time"); Fibonacci2(20) console.timeEnd("尾递归优化过的Fibonacci2(20) time"); console.time("尾递归优化过的Fibonacci2(1000) time"); Fibonacci2(1000) console.timeEnd("尾递归优化过的Fibonacci2(1000) time");
通过chrome浏览器的性能分析工具 performance 可以得到下面这张图
可以明显地看出没有优化过的 Fibonacci 函数 在递归次数为10时 没优化过的 Fibonacci 比使用尾递归优化过的Fibonacci2 还快了0.02ms,超过10之后性能明显下降,左边的红框是Fibonacci(40)的执行结果,要花费2450.614990234375ms 而后边是Fibonacci2(1000)的执行结果 只要0.22412109375ms 这个性能真的差老远了 🙃
通过这个图,还可以明显地看到,右边的红框中Fibonacci2是笔直下来的,即Fibonacci2(1000) 的每次递归消耗的时间是没变的,而左边的这个Fibonacci 会有不同的长度, 说明它每次递归消耗的时间是在变化的。
这个直接展示了这个尾递归的优势。(chrome也支持尾递归了,不止safari)
- pig实战 pig常用语法总结,教你快速入门——算法篇
- Object es5-es6扩展总结
- ES6学习——新的语法:对象字面量扩展(Object Literal Extensions)
- ES6常用语法总结
- ES6总结--数据类型的扩展
- es6语法之解构赋值总结
- ES6常用语法总结
- 新人自我总结基本语法接口 数据库入门 swing界面(未完待续)
- 如何理解es6语法的,对象前面加三个点(...) 对象的解构赋值和扩展
- es6 -- 语法(扩展)
- ES6入门——数值的扩展
- ES6语法let、const与var的区别-总结
- ES6基础语法(八) —— 函数扩展
- ES6入门——函数的扩展
- PHP编程入门的基本语法知识点总结
- ES6常用的一些语法总结
- es6入门基础总结
- Python入门知识总结基础语法【人生苦短,我学Python】
- iOS开发 入门学习总结(二)Objective-C 语法特性总结
- react入门系列之todolist代码优化(使用react 新特性,es6语法)