一:let与块级作用域
在ES2015之前只有两中作用域
全局作用域
函数作用域
在ES2015中新增了一个块级作用域
块级作用域:定义在{}中,if 和 for中的{}都属于块级作用域
// 例1:if (true) {var a = 123}console.log(a) // 123if (true) {let a = 123}console.log(a) // a is not defined// 例2:for (var i = 0; i < 3; i++) {for (var i = 0; i < 3; i++) {console.log(i)}}// 输出:012for (let i = 0; i < 3; i++) {for (let i = 0; i < 3; i++) {console.log(i)}}// 输出:012 012 012
以上都是定义块级作用域的方法,使用let关键字来定义块级作用域,因为在ES2015之前没有块级作用域的说法,所以使用var在{}定义的变量并不属于块级作用域
二:const
const是一个常量/衡量,一旦声明不可修改
注意:const声明的常量只是不能重新去指向新的内存地址,并不是不能修改常量中的属性成员
const a = '123'a = '456'// Assignment to constant variable// 注意:const obj = {'name': 'jack'}console.log(obj.name) // jackobj.name = 'tom'console.log(obj.name) // tom
最佳实践:不用var,主用const,配合let
这样定义的的话能搞提高代码的质量
三:数组的解构
从数组或对象中获取指定元素的快捷方式
1、数组的解构
const arr = [100, 200, 300]// 传统的做法const foo = arr[0]const bar = arr[1]const baz = arr[2]console.log(foo) // 100// 解构的做法const [foo, bar, baz] = arrconsole.log(foo) // 100// 如果只想定义一个值,长度必须跟数组长度一致const [, , baz] = arrconsole.log(baz) // 300// 如果只想取从当前位置开始之后的所有成员const [foo, ...rest] = arrconsole.log(rest) // [200, 300]// 注意:这种用法只能在解构成员的最后一个位置上使用// 如果解构位置的长度小于解构的数组,会默认从第一个位置提取const [foo] = arrconsole.log(foo) // 100// 如果解构位置的的长度大于解构的数组,则返回undefinedconst [foo, bar, baz, more] = arrconsole.log(more) // undefined// 设置默认值const [foo, bar, baz, more = "default value"] = arrconsole.log(more) // default value
四:对象的解构
基本上和数组的解构方式差不多
const obj = { name: 'jack', age: '23' }// 例1:const { name } = objconsole.log(name) // jack注意:如果变量名和对象中的属性名冲突的话会报错const name = 'tom'const { name } = objconsole.log(name) // Identifier 'name' has already been declared所以我们可以更改属性名来成功输出const name = 'tom'const { name: nameObj } = objconsole.log(nameObj) // jack我们还可以设置默认属性const { sex = '男' } = objconsole.log(sex) // 男
五:模版字符串
// 传统的做法const str = 'hello es2015, this is a string'console.log(str) // hello es2015, this is a string// 新的写法const str = `hello es2015, this is a string`console.log(str) // hello es2015, this is a string// 好处:// 传统的做法需要在字符串中换行的话必须加上\n进行换行// 而新的做法直接换行就行了const str = `hello es2015,this is a string`console.log(str)// hello es2015,// this is a string// 如果需要在字符串中加入单引号或新双引号const str = `hello es2015, this is a \'string\'`console.log(str) // hello es2015, this is a 'string'// 支持插值表达式的形式const name = 'es2015'const str = `hello ${name}, this is a string`console.log(str) // hello es2015, this is a string// 还可以支持js的表达式const str = `hello es2015, this is a string, ${ 1 + 2}, ${ Math.random() }`console.log(str) // hello es2015, this is a string, 3, 随机值
六:带标签的模版字符串
const str = console.log`hello world` // ['hello', 'world']// 还可以加变量或者表达式例:const name = `jack`const age = `23`result`hello ${name}, this is a ${age}`function result(string, name, age) {console.log(string, name, age) // ['hello', ', this is a', ''] jack 23}// 这种方式其实是以变量或者表达式的方式进行分割
七:字符串的扩展方法:
// 其中最常用的包括// 1、includes: 字符串当中是否包含某些字段,返回true or false// 2、startsWith: 是否以某个字段开头,返回true or false// 3、endsWith: 是否以某个字段结尾,返回true or false// 例:const str = `hello world`console.log(str.includes(`o`)) // trueconsole.log(str.startsWith(`h`)) // trueconsole.log(str.endsWith(`d`)) // true
八:参数默认值
// 在函数参数没有传值的情况下,默认undefined// 传统的做法:function foo (parmas) {parmas = parmas === undefined ? '123' : parmasconsole.log(parmas) // 123}foo()// 新的做法:function foo (parmas = 123) {console.log(parmas) // 123}foo()注意:如果有多个参数的话,设置参数默认值一定要放到参数列表的最后例:// 错误写法function foo (parmas = 123, parmas2) {console.log(parmas) // 123}foo()// 正确写法function foo (parmas2, parmas = 123) {console.log(parmas) // 123}foo()
九:剩余参数
// 在参数数量不确定的情况下// 传统做法通过arguments获取到参数// 例:function foo () {console.log(arguments) // {'0': 1, '1': 2, '2': 3}}foo(1,2,3)// 新的做法:function foo (...args) {console.log(args) // [1, 2, 3]}foo(1,2,3)注意:...args只能出现在参数的最后位置function foo (first, ...args) {console.log(args) // [2, 3]}foo(1,2,3)
十:展开数组
使用…的方式展开数组
const arr = ['bar', 'bat', 'jack']console.log(...arr) // bar bat jack把数组中的每一项传递给console.log 打印出来
十一:箭头函数
// 比如筛选出一个数组中的奇数const arr = [1, 2, ,3, 4, 5]console.log(arr.filter(i => i % 2)) // [1, 3, 5]// 上面箭头函数使用普通函数筛选console.log(arr.filter(function(i) {return i % 2})) // [1, 3, 5]// 箭头函数中的this指向const obj = {name: 'jack',sayHi: function () {console.log(this.name) // jack}}obj.sayHi()// 因为sayHi这个方法是obj去调用的,所以this指向obj这个对象const obj = {name: 'jack',sayHi: () => {console.log(this.name) // undefined}}obj.sayHi()// 因为箭头函数中没有this的概念,所以箭头函数中的this指向window
十二:Proxy代理对象
用来监听某个对象中的数据读写
const person = {name: 'jack',age: 23}const personProxy = new Proxy(person, { // person目标对象get(target, property) { // target目标对象,property属性名console(target, property) // { name: 'jack', age: 23 } name},// get方法读取目标set(target, property, value) {console.log(target, property, value) // target目标对象,property属性名, value要写入的值}// set方法写入目标})console.log(personProxy.name)
十三:生成器
生成器函数会自动帮我们返回一个生成器对象,调用这个对象的next()方法这个生成器函数就开始执行,在执行的过程中一旦遇到yield关键词,执行就会被暂停下来。而且yield的值将会作为next的结果返回,如果再调用next方法,这个函数将会从暂停的位置继续执行,直到全部结束
function * foo() { // 定义生成器函数console.log(1)yield 100 // 遇到yield暂停执行, 直到执行下一次next方法console.log(2)yield 101console.log(3)yield 102}const generator = foo() // console.log(foo()) 返回[Generator] {}console.log(generator.next()) // 1 { value: 100, done: false }console.log(generator.next()) // 2 { value: 101, done: false }console.log(generator.next()) // 3 { value: 102, done: false }最大的特点:惰性执行,就是说你给它一个命令它就执行一次
