es6新特性
栏目: JavaScript · 发布时间: 5年前
内容简介:有几个点需要注意:在日常开发中,我的建议是全面拥抱let/const,一般的变量声明使用let关键字,而当声明一些配置项(类似接口地址,npm依赖包,分页器默认页数等一些一旦声明后就不会改变的变量)的时候可以使用const,来显式的告诉项目其他开发者,这个变量是不能改变的(const声明的常量建议使用全大写字母标识,单词间用下划线),同时也建议了解var关键字的缺陷(变量提升,污染全局变量等),这样才能更好的使用新语法Promise作为ES6中推出的新的概念,改变了JS的异步编程,现代前端大部分的异步请求都
- 1.变量提升
- var声明 无论声明在何处,都会被视为声明在函数的最顶部
- let和const声明不会提升
- 2.作用域
- var是函数作用域, 在函数内部作用, 但是{}里是一样会提升的
- let和const是块级作用域, 在{}里就形成了一个作用域
- 3.重复声明
- var 可以重复定义
- let和const不可以重复定义,否则报错
- 4.const常量不可修改
- const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了;
- 5. 如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:
const student = { name: 'cc' } student.name = 'yy';// 不报错 student = { name: 'yy' };// 报错 复制代码
2. 暂时性死区
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; } 复制代码
- 上面代码中,存在全局变量
tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
有几个点需要注意:
# let 关键词声明的变量不具备变量提升(hoisting)特性 # let 和 const 声明只在最靠近的一个块中(花括号内)有效 # 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING # const 在声明时必须被赋值 复制代码
3. 建议
在日常开发中,我的建议是全面拥抱let/const,一般的变量声明使用let关键字,而当声明一些配置项(类似接口地址,npm依赖包,分页器默认页数等一些一旦声明后就不会改变的变量)的时候可以使用const,来显式的告诉项目其他开发者,这个变量是不能改变的(const声明的常量建议使用全大写字母标识,单词间用下划线),同时也建议了解var关键字的缺陷(变量提升,污染全局变量等),这样才能更好的使用新语法
函数
(一) 箭头函数(Arrow Functions)
- ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;
1. 箭头函数对于使用function关键字创建的函数有以下区别:
- 箭头函数没有arguments(建议使用更好的语法,剩余运算符替代)
- 箭头函数没有prototype属性,不能用作构造函数(不能用new关键字调用)
- 箭头函数没有自己this,它的this是词法的,引用的是上下文的this,即在你写这行代码的时候就箭头函数的this就已经和外层执行上下文的this绑定了(这里个人认为并不代表完全是静态的,因为外层的上下文仍是动态的可以使用call,apply,bind修改,这里只是说明了箭头函数的this始终等于它上层上下文中的this)
2. 箭头函数最直观的三个特点
# 不需要 function 关键字来创建函数 # 省略 return 关键字 # 继承当前上下文的 this 关键字 复制代码
- 细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;
3. 规则
- 使用了块语句的箭头函数不会自动返回值,你需要使用return语句将所需值返回。
- 不可以当作构造函数,即,不可以使用new 关键字来实例化对象,否则会抛出一个错误。
- 不可以使用arguments对象,更不能通过arguments对象访问传入参数,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- 不可以使用yield命令,因此箭头函数不能用作 Generator 函数.
- 返回的就是一个对象, 需要在外面加一个括号 var getTempItem = id = > ({id: id,});
(二) 函数的参数默认值
// ES6之前,当未传入参数时,text = 'default'; function printText(text) { text = text || 'default'; console.log(text); } // ES6; function printText(text = 'default') { console.log(text); } printText('hello'); // hello printText();// default 复制代码
(三) Promise(常用)
Promise作为ES6中推出的新的概念,改变了JS的异步编程,现代前端大部分的异步请求都是使用Promise实现,fetch这个web api也是基于Promise的,这里不得简述一下之前统治JS异步编程的回调函数,回调函数有什么缺点,Promise又是怎么改善这些缺点
回调函数缺点
- 多重嵌套,导致回调地狱
- 代码跳跃,并非人类习惯的思维模式
- 信任问题,你不能把你的回调完全寄托与第三方库,因为你不知道第三方库到底会怎么执行回调(多次执行)
- 第三方库可能没有提供错误处理
- 不清楚回调是否都是异步调用的(可以同步调用ajax,在收到响应前会阻塞整个线程,会陷入假死状态,非常不推荐)
Promise
针对回调函数这么多缺点,ES6中引入了一个新的概念Promise,Promise是一个构造函数,通过new关键字创建一个Promise的实例,来看看Promise是怎么解决回调函数的这些问题
- 不清楚回调是否都是异步调用的(可以同步调用ajax,在收到响应前会阻塞整个线程,会陷入假死状态,非常不推荐)
- Promise在设计的时候保证所有响应的处理回调都是异步调用的,不会阻塞代码的执行,Promise将then方法的回调放入一个叫微任务的队列中(MicroTask),确保这些回调任务在同步任务执行完以后再执行,这部分同样也是事件循环的知识点,有兴趣的朋友可以深入研究一下
建议
- 在日常开发中,建议全面拥抱新的Promise语法,其实现在的异步编程基本也都使用的是Promise
- 建议使用ES7的async/await进一步的优化Promise的写法,async函数始终返回一个Promise,await可以实现一个"等待"的功能,async/await被成为异步编程的终极解决方案,即用同步的形式书写异步代码,并且能够更优雅的实现异步代码顺序执行以及在发生异步的错误时提供更精准的错误信息
字符串
(一) 字符串模板
- 需要拼接字符串的时候尽量改成使用模板字符串:
// bad const foo = 'this is a' + example; // good const foo = `this is a ${example}`; 复制代码
- 而对ES6来说
- 基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;
- ES6反引号(``)直接搞定;
数组
for ... of循环
- for ... of是作为ES6新增的遍历方式,允许遍历一个含有iterator接口的数据结构并且返回各项的值,和ES3中的for ... in的区别如下
- for ... of只能用在可迭代对象上,获取的是迭代器返回的value值, for ... in 可以获取所有对象的键名
- for ... in会遍历对象的整个原型链,性能非常差不推荐使用, 而for ... of只遍历当前对象不会遍历它的原型链
- 对于数组的遍历,for ... in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性), for ... of只返回数组的下标对应的属性值
- for ... of循环的原理其实也是利用了可迭代对象内部部署的iterator接口,如果将for ... of循环分解成最原始的for循环,内部实现的机制可以这么理解
- 可以看到只要满足第二个条件(iterator.next()存在且res.done为true)就可以一直循环下去,并且每次把迭代器的next方法生成的对象赋值给res,然后将res的value属性赋值给for ... of第一个条件中声明的变量即可,res的done属性控制是否继续遍历下去
3. for... of循环同时支持break,continue,return(在函数中调用的话)并且可以和对象解构赋值一起使用
- arr数组每次使用for ... of循环都返回一对象({a:1},{a:2},{a:3}),然后会经过对象解构,寻找属性为a的值,赋值给obj.a,所以在每轮循环的时候obj.a会分别赋值为1,2,3
对象
(一) 对象属性/方法简写(常用)
1. es6允许当对象的属性和值相同时,省略属性名
- 需要注意的是**
- 省略的是属性名而不是值
- 值必须是一个变量
2. 对象属性简写经常与解构赋值一起使用
- 结合上文的解构赋值,这里的代码会其实是声明了x,y,z变量,因为bar函数会返回一个对象,这个对象有x,y,z这3个属性,解构赋值会寻找等号右边表达式的x,y,z属性,找到后赋值给声明的x,y,z变量
3. 方法简写
- es6允许当一个对象的属性的值是一个函数(即是一个方法),可以使用简写的形式
Module模块化(常用)
在ES6 Module出现之前,模块化一直是前端开发者讨论的重点,面对日益增长的需求和代码,需要一种方案来将臃肿的代码拆分成一个个小模块,从而推出了AMD,CMD和CommonJs这3种模块化方案,前者用在浏览器端,后面2种用在服务端,直到ES6 Module出现
- ES6 Module默认目前还没有被浏览器支持,需要使用babel,在日常写demo的时候经常会显示这个错误
Module特点
- ES6 Module是静态的,也就是说它是在编译阶段运行,和var以及function一样具有提升效果(这个特点使得它支持tree shaking)
- 自动采用严格模式(顶层的this返回undefined)
- ES6 Module支持使用export {<变量>}导出具名的接口,或者export default导出匿名的接口
module.js导出
import导入
- 这两者的区别是,export {<变量>}导出的是一个变量的引用,export default导出的是一个值
- 什么意思呢,就是说在a.js中使用import导入这2个变量的后,在module.js中因为某些原因x变量被改变了,那么会立刻反映到a.js,而module.js中的y变量改变后,a.js中的y还是原来的值
解构赋值
理解
解构赋值可以直接使用对象的某个属性,而不需要通过属性访问的形式使用,对象解构原理个人认为是通过寻找相同的属性名,然后原对象的这个属性名的值赋值给新对象对应的属性, 键找键,找到了就赋值了
- 解构数组
var arr = [1, 2, 3, 4]; let [a, b, c, d] = arr; console.log(a); // 1 console.log(b); // 2 复制代码
- 解构对象
var luke = { occupation: 'jedi', father: 'anakin' }; let {occupation, father} = luke; console.log(occupation); // jedi console.log(father); // anakin 复制代码
- vuex使用对象解构
建议
同样建议使用,因为解构赋值语意化更强,对于作为对象的函数参数来说,可以减少形参的声明,直接使用对象的属性(如果嵌套层数过多我个人认为不适合用对象解构,不太优雅)
剩余运算符rest/扩展运算符(常用)
剩余/扩展运算符同样也是ES6一个非常重要的语法,使用3个点(...),后面跟着一个含有iterator接口的数据结构
扩展运算符
- 以数组为例,使用扩展运算符使得可以"展开"这个数组,可以这么理解,数组是存放元素集合的一个容器,而使用扩展运算符可以将这个容器拆开,这样就只剩下元素集合,你可以把这些元素集合放到另外一个数组里面, 代替ES3中数组原型的concat方法
剩余运算符
剩余运算符最重要的一个特点就是替代了以前的arguments
rest只是形参, 可以随意取名
- 访问函数的arguments对象是一个很昂贵的操作,以前的arguments.callee,arguments.caller都被废止了,建议在支持ES6语法的环境下不要在使用arguments对象,使用剩余运算符替代(箭头函数没有arguments,必须使用剩余运算符才能访问参数集合)
- 剩余运算符可以和数组的解构赋值一起使用,但是必须放在最后一个,因为剩余运算符的原理其实是利用了数组的迭代器,它会消耗3个点后面的数组的所有迭代器,读取所有迭代器生成对象的value属性,剩运算符后不能在有解构赋值,因为剩余运算符已经消耗了所有迭代器,而数组的解构赋值也是消耗迭代器,但是这个时候已经没有迭代器了,所以会报错
- 这里first会消耗右边数组的一个迭代器,...arr会消耗剩余所有的迭代器,而第二个例子...arr直接消耗了所有迭代器,导致last没有迭代器可供消耗了,所以会报错,因为这是毫无意义的操作
区别
剩余运算符和扩展运算符的区别就是,剩余运算符会收集这些集合,放到右边的数组中,扩展运算符是将右边的数组拆分成元素的集合,它们是相反的
在对象中使用扩展运算符
- 这个是ES9的语法,ES9中支持在对象中使用扩展运算符,之前说过数组的扩展运算符原理是消耗所有迭代器,但对象中并没有迭代器,我个人认为可能是实现原理不同,但是仍可以理解为将键值对从对象中拆开,它可以放到另外一个普通对象中
- 其实它和另外一个ES6新增的API相似,即Object.assign,它们都可以合并对象,但是还是有一些不同Object.assign会触发目标对象的setter函数,而对象扩展运算符不会
以上所述就是小编给大家介绍的《es6新特性》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 『互联网架构』软件架构-redis特性和集群特性(中)(49)
- 『互联网架构』软件架构-redis特性和集群特性(上)(48)
- 『互联网架构』软件架构-redis特性和集群特性(下)(50)
- JDK 14 功能特性
- C# 特性(Attribute)
- python—高级特性
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RGB转16进制工具
RGB HEX 互转工具
HSV CMYK 转换工具
HSV CMYK互换工具