Promise对象
Promise的出现,是对异步处理的优化、也是对回调地狱的避免。
虽然JavaScript本身是单线程的,但是有一些操作可以开启新线程,比如回调函数。换言之,JavaScript一方面从上往下按照语句顺序依次执行,一旦遇上回调函数,就会另外开启一个线程,这个线程中也开始从回调函数最上方往下依次执行,而另一边,并不会等待该回调函数执行完毕,而是直接往下执行JavaScript语句。
有时候我们需要另外新开启的线程的返回数据,将其作为另一个线程的变量,进行处理,这样一来就需要异步操作,最原始的做法,就是编写回调函数,但是一旦异步操作变多,回调函数嵌套加深,就会带来一个很复杂的链式代码块——回调地狱,其代码逻辑可谓“乱花渐欲迷人眼”,debug起来也是自讨苦吃。
Promise写法简介
Promise就是一种新写法:
const p = new Promise((resolve, reject) => {
resolve('Lairucy is awesome!')
})
p.then(data => {
console.log(data);
})
在上面这个简洁的栗子中,Promise()构造函数可以接收一个回调函数作为参数,这个回调函数自身有俩参数,通常记作resolve、reject:
- resolve函数用于将Promise对象的状态变为“成功”
- reject函数用于将Promise对象的状态变为“失败”
Promise.then()
Promise对象的then()方法是对回调函数的优化,是在Promise对象为成功状态下的进一步处理;换言之,上面的栗子中,再构造函数内部,resolve函数接收了字符串参数,就会将状态变成“成功”,而then()方法就会触发,并且data即为传入的字符串参数。
Proxy
proxy,代理,也就是给对象进行一番“修改”,一般用作改变对象原有的属性、逻辑,功能类似于拦截器、预处理。
const personProxy = new Proxy(target, handler)
target是原对象,handler是处理函数,在handler中,我们可以任意修改target对象上的属性。
const person = {
name: 'Huxinting',
age: 999
}
const personProxy = new Proxy(person, {
// get(),当原对象被读取时,自动调用
get(target, key) {
console.log('someone ask for', target, key)
// 返回读取的结果为属性值大写
return target[key].toUpperCase()
},
// set(), 当原对象被写(修改)时,自动调用
set(target, key, value) {
// 表示如果要将target对象的key属性的value值修改为一个字符串,就会自动去除其中的空白符
if(typeof value === 'string') {
target[key] = value.trim()
}
}
})
personProxy.name = 'Luqing '
console.log(personProxy);
/**{ name: 'Luqing', age: 999 }
* Luqing后面的空白符全部去除
*/
再谈JavaScript原型特性
这并不是ES的新特性,只不过,这个知识点很重要,关联了很多其他的知识和新特性,不得不再次学习。
为了学好JavaScript的原型,我们首先还是从熟悉的传统OOP讲起。在C++、Java等传统OOP语言中,都是先定义class(类),再根据类创建出实例对象,此时,class中定义的所有属性、方法就会被复制到实例对象中。然而,JavaScript中却并不是这样做的。
在JavaScript中,对象实例创建时,它会和其创造器之间建立一个链接(也就是对象实例的proto属性,派生于构造函数的prototype)
也就是说——
- 构造函数的prototype实际上就是对象实例的proto对象
- 构造函数的prototype存储的所有属性、方法,都可以被继承者使用
- 每一个实例对象都聪原型中继承了constructor属性,该属性指向了用于创建此实例对象的构造函数