一:let与块级作用域
1、在ES2015之前只有两中作用域
- 全局作用域
- 函数作用域
2、在ES2015中新增了一个
- 块级作用域
块级作用域:定义在{}中,if 和 for中的{}都属于块级作用域
// 例1:
if (true) {
var a = 123
}
console.log(a) // 123
if (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)
}
}
// 输出:012
for (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) // jack
obj.name = 'tom'
console.log(obj.name) // tom
最佳实践:不用var,主用const,配合let
这样定义的的话能搞提高代码的质量
三:数组的解构
从数组或对象中获取指定元素的快捷方式
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] = arr
console.log(foo) // 100
// 如果只想定义一个值,长度必须跟数组长度一致
const [, , baz] = arr
console.log(baz) // 300
// 如果只想取从当前位置开始之后的所有成员
const [foo, ...rest] = arr
console.log(rest) // [200, 300]
// 注意:这种用法只能在解构成员的最后一个位置上使用
// 如果解构位置的长度小于解构的数组,会默认从第一个位置提取
const [foo] = arr
console.log(foo) // 100
// 如果解构位置的的长度大于解构的数组,则返回undefined
const [foo, bar, baz, more] = arr
console.log(more) // undefined
// 设置默认值
const [foo, bar, baz, more = "default value"] = arr
console.log(more) // default value
四:对象的解构
基本上和数组的解构方式差不多
const obj = { name: 'jack', age: '23' }
// 例1:
const { name } = obj
console.log(name) // jack
注意:如果变量名和对象中的属性名冲突的话会报错
const name = 'tom'
const { name } = obj
console.log(name) // Identifier 'name' has already been declared
所以我们可以更改属性名来成功输出
const name = 'tom'
const { name: nameObj } = obj
console.log(nameObj) // jack
我们还可以设置默认属性
const { sex = '男' } = obj
console.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
}
// 这种方式其实是以变量或者表达式的方式进行分割
七:字符串的扩展方法
- includes: 字符串当中是否包含某些字段,返回true or false
- startsWith: 是否以某个字段开头,返回true or false
- endsWith: 是否以某个字段结尾,返回true or false
// 例:
const str = `hello world`
console.log(str.includes(`o`)) // true
console.log(str.startsWith(`h`)) // true
console.log(str.endsWith(`d`)) // true
八:参数默认值
// 在函数参数没有传值的情况下,默认undefined
// 传统的做法:
function foo (parmas) {
parmas = parmas === undefined ? '123' : parmas
console.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 101
console.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 }
最大的特点:惰性执行,就是说你给它一个命令它就执行一次