块级作用域概念 let 和 const的加入
let
ES6的规范慢慢的成为主流,再加上打包工具能够将我们的ES6代码无缝的压缩成为可读的ES5代码。渐渐的深受大部分开发者喜爱(不排除一些人对ES5情有独钟)。
在ES6之前的版本,其实是没有块级作用于概念的,不论是在{}里面还是外面都可以被访问到。
举个栗子: 下面代码中,我在if中才定义的test变量在它的父作用域依旧能被调取到,这很明显不是我们希望得到的。因此ES6的块级作用域给与了我们更大的严谨性。
function foo() {
if (true) {
// 我在 if 的局部中定义一个变量 : test
var test = '如果if 为 true 就输出我'
console.log(test)
// --end if
}
console.log(test)
}
foo () // 运行函数
// print :
// 如果if 为 true 就输出我
// 如果if 为 true 就输出我
当我们用 let 的时候,可以发现,程序报错了,提示我们找不到该变量。这个时候我们就知道了,let定义的变量只能在当前 {} 中生效。我感觉这是一个非常好的现象。
// ReferenceError: test is not defined
const
const 作用是定义一个只读的变量。它定义的变量值是无法更改的。避免一些不需要修改的参数被你是同事给“意外”更换掉。 举个栗子: 可以看的到 a = 2赋值的话是会直接报错的。这样就能给开发人员提示,不要动我,我被安排了。所以我个人比较喜欢const,甚至在写程序的时候会默认const,只有需要去变动的时候,我才会去将const换成let。
let b = 0
b = 1
const a = 1
a = 2 // TypeError: Assignment to constant variable.
const 面试的坑
面试: const定义的值能被修改吗? 你如果说不能的时候,可能这个面试官在坑你,其实const 定义对象内部的值是能够修改的。 举个栗子: 可以看得到,没有弹出常量错误,值被修改了。
const a = {
name : 111
}
a.name = 2222
console.log(a.name) // => 2222
模板字符串
模板字符串可以方便我们去拼接一些字符串,这也是我常用的一个地方了,也没有去深入的了解,在以前都是用+号去这个干的。模板字符串不是 '' 是反单引 ``。 举个例子:
const name = 'Annai'
console.log('name : ' + name)
console.log(`name : ${ name }`)
// URL get参数拼接
const _LOGIN = `http://www.baidu.com/mobile/login?name=${param.name}&passward=${param.passward}`
console.log(_LOGIN)
箭头函数
箭头函数是ES6的一大两点,非常简便的就能去写一个函数和一些计算属性。和传统函数的区别在于:
- 没有this
- 没有Prototype
- 没有argments
- 没有constructor
- 其他的可以自行百度
没有this
箭头函数是没有this指向的,那么箭头函数的this是哪里来的呢?其实箭头函数的this指向是绑定的最近一层非箭头函数的this指向。 举个栗子: 可以看到下面两个例子的this指向,因为箭头函数没有this,所以它会去找上一层非箭头函数绑定的this,所以找到全局去了。
let Person = {
name: 'wang',
run: () =>{
console.log(this) // {} || window
console.log(this.name) //undefined
},
run1: function (){
console.log(this) // Person
console.log(this.name) //wang
}
}
Person.run()
Person.run1()
没有原型(Prototype)
当我们去输出箭头函数的prototype原型的时候。沃特,怎么没有定义。 举个栗子
const foo = value => {}
console.log(foo.prototype)
没有argments
可以看到当你试图去输出argments的话,箭头函数直接抛一个不能调用错误给你。 举个栗子
const a = function (){}
const b = () => {}
console.log(a.arguments) // null
console.log(b.arguments)
//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
没有consttructor,无法使用new
不只是没有原型,甚至连构造函数都没有了,所以箭头函数也就无法使用new去进行获取。因为new 操作后会去找函数中的constructor,因为没有自带构造函数,所以会提示错误 举个栗子:
const Foo = value => {}
const foo = new Foo() // TypeError: Foo is not a constructor
Set 和 Map
Set(集合) 和 Map(字典)是ES6中新增加的数据结构,不过对于学过数据结构的小伙伴来讲,这一点都不显得陌生。
Set
我们可以把Set看成集合,既然是集合,那么它肯定不能有重复值。因此,Set去重法就来了 简单实现Set去重数组: 下面就实现了一个非常简单的数组去重。
const arr = [1,2,3,3,2,2,1,1]
console.log(arr) // [ 1, 2, 3, 3, 2, 2, 1, 1 ]
const new_arr = [...new Set(arr)]
console.log(new_arr) // [ 1, 2, 3 ]
Set的属性
Set中只有一个size属性,和数组的length属性功能一致,用于返回集合的长度 举个栗子: 通过条用size属性,就能知道集合有多长了。
const set = new Set([1,2,3,4,5,6])
console.log(set.size) // => 6
Set的方法
Set方法都是对Set本身进行一些判断和操作
1.add(value) 向集合添加一个值 2.delete(value) 删除集合中的一个值 3.has(value) 判断该值是否存在 4.clear 清除集合
Map
Map就相当于是字典,新华字典中都有拼音文字来表示对应关系。Map中也是通过键对值来进行分布的。它和Set都可以存储不重复的数据,只是不同的地方在于,Set是通过值值来存储的,Map是通过键值来存储的。键值相对应。 举个栗子: Map的生成。
const map = new Map()
map.set('name','wangly')
console.log(map) // Map { 'name' => 'wangly' }
Map的属性
Map和Set一样,只有一一个size属性。
const map = new Map()
map.set('name','wangly')
console.log(map.size) // 1
Map的方法
1.set(key, val): 向字典中添加新元素 2.get(key):通过键值查找特定的数值并返回 3.has(key):如果键存在字典中返回true,否则false 4.delete(key): 通过键值从字典中移除对应的数据 5.clear():将这个字典中的所有元素删除
Promise
Promise 是现在使用非常广泛的一个异步任务处理对象,也是目前JavaScript流行的异步处理方式之一。
Promise使用方式
Promise我们可以通过实例化一个Promise对象,并且接收一个函数来作为参数,这个函数有两个参数 resovle(成功) 和 reject(失败)。Promise只有三种状态
- pending : 对象初始化,开始工作
- fulfilled : 当调用resovle,则从pending变为fulfilled成功。
- rejected: 当调用reject(失败),会由pending 变为 rejected
const promise = new Promise((resolve,reject) => {
console.log('promise执行中........')
resolve() // 成功了|| reject()
})
.then()回调
then方法是当resolve(成功)/reject(失败)状态的回调函数,then()中有两个参数,类型都是参数,第一个是onFulfilled(),第二个是onRejected() 举个栗子:
const promise = new Promise((resolve,reject) => {
console.log('promise执行中........')
reject()// 成功了 || reject()
})
promise.then(
resolve => {
// fulfilled 成功操作
console.log('pending => fulfilled')
},
reject => {
// rejected 失败操作
console.log('pending => rejected') // 我被输出了
})
当成功时,我就执行成功的回调,当失败时,我就执行失败的回调。非常的有层次感觉和代码的优雅感觉。。then也是一个链式的操作,他返回的就是一个promise对象,下面就是一个链式调用
.then().then().then()......
.catch()异常捕获
用来捕获前面.then()的异常信息捕获,onRejected不能捕获当前onFulfilled中的异常,所以可以写成这个。
promise.then(onFulfilled)
.catch(onRrejected);
Class
在ES6之JavaScript本没有类,但是这怎么难得倒我们的JSER呢,所以就有了类的概念,到ES6也如愿的产生了class语法糖 ES5中的类
function Person (name){
this.name = name
}
Person.prototype.myName = function (){
console.log(this.name)
}
var person = new Person('wang')
person.myName()
ES6中的类
class Person{
constructor (name){
this.name = name
}
myName(){
console.log(this.name)
}
}
const person = new Person('wang')
person.myName()
解构赋值
对象的解构赋值
对象的解构赋值,如果指定的局部变量名称在对象中不存在,那么这个局部变量会被赋值为 undefined,如果能够找到,那么就会将对象中的值赋予给局部变量。
const person = {
name: 'wang',
age: 11,
score: 100
}
const { name , age , score } = person
console.log(`name: ${name},age:${age},score:${score}`) //name: wang,age:11,score:100
数组的解构赋值
数组的解构赋值就非常简单了,你给一个它就去数组中找一个,当你定义的变量超出数组下标就会赋值为undefined。非常的灵活
const a = [1,2,3]
const [b,c,d,e] = a
console.log(`${b}-${c}-${d}-${e}`) // 1-2-3-undefined