JavaScript ES语法学习笔记(五)

Callback(异步操作)

异步操作不会立马执行,优先同步操作
实际中应避免回调地狱

Promise then

promise就是为了解决“回调地狱”问题的,他可以优雅地处理异步操作

举个例子:
加载1.js,如果没有发生错误;
加载2.js,如果没有发生错误;
加载3.js,如果没有发生错误——做其他操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function loadScript (src{
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    script.src = src
    script.onload = () => resolve(src)// fulfilled,result 状态不可逆,只有一个执行
    script.onerror = (err) => reject(err)// rejected,error
    document.head.append(script)
  })
}

loadScript('./1.js')
  .then(() => {
    return loadScript('./4.js')
  }, (err) => {
    console.log(err)
  })
  .then(() => {
    loadScript('./3.js')
  }, (err) => {
    console.log(err)
  })

Promise的基本语法

Resolve & Reject (异步操作)

promise提供的两个静态方法,需通过promise调用

1
new Promise(function(resolve,reject){...})

通过创建Promise对象开启一个异步操作的过程,一般用几部完成多次异步操作:

  1. new Promise(fn) 返回一个Promise对象
  2. 在fn中指定异步等处理
  3. 处理结果正常的话,调用resolve(处理结果值)
  4. 处理结果错误的话,调用reject(Error对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function test (bool{
  if (bool) {
    return new Promise((resolve, reject) => {
      resolve(30)
    })
  } else {
    return Promise.reject(new Error('ss')) //非异步转化成异步
  }
}
test(0).then((value) => {
  console.log(value)
}, (err) => {
  console.log(err)
})

Catch(异步操作)

捕获异步操作过程中出现的任何异常
基本语法

1
2
3
4
5
p.catch(onRejected)

p.catch(function(reason)){
//rejection
}

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function loadScript (src{
  // pending,undefined--挂起,未定义
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    script.src = src
    script.onload = () => resolve(src)// fulfilled,result
    script.onerror = (err) => reject(err)// rejected,error
    document.head.append(script)
  })
}
loadScript('./1.js')
  .then(() => {
    return loadScript('./2.js')
  })
  .then(() => {
    return loadScript('./4.js')
  })
  .catch(err => { //捕获then传递链上所有的报错(触发reject时捕获)
    console.log(err)
  })

All(异步操作)

不分先后,只接受数据
promise.all 生成并返回一个新的Promise对象,所以它可以使用Promise实例的所有方法。参数传递promise数组中的所有promise对象都变为resolve的时候,该方法才会返回,新建的promise则会使用这些promise的值。
如果参数中任何一个promise为reject的话,则整个promise.all调用会立即终止,并返回一个reject的新的对象

1
2
3
4
5
6
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(20)
const p3 = Promise.resolve(3)
Promise.all([p1, p2, p3]).then((value) => {
  console.log(value)
})

Race(异步操作)

先到先得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const p1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function ({
      resolve(1)
    }, 1000)
  })
}
const p2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function ({
      resolve(2)
    }, 3000)
  })
}
Promise.race([p1(), p2()]).then((value) => {
  console.log(value)
})

Reflect.apply(反射机制)

Java的反射机制是在编译阶段不知道是哪个类被加载,而是在运行的时候才加载、执行

1
2
3
4
//Math.floor这个函数应用到null作用域上,参数为3.72
console.log(Math.floor.apply(null, [3.72])) //ES5写法

console.log(Reflect.apply(Math.floor, null, [4.72])) //ES6写法

Reflect.construct(反射机制)

用反射机制去动态实例化一个类
Reflect.construct( )方法的行为有点像 new 操作符 构造函数,相当于运行new target(…args)

1
2
3
4
5
6
7
8
9
10
11
12
13
let d = Reflect.construct(Date, [1776,6,4])
d instanceof Date //true
d.getFullYear() //1776
```’

#### **Reflect.deleteProperty() Reflect.get()(反射机制)**
```javascript
//reflect读取内容
const obj = { x1y2 }
Reflect.deleteProperty(obj, 'x') //删除
console.log(obj)
console.log(Reflect.get(obj, 'x')) //读取
console.log(Reflect.get([34], 1))

reflect与object的区别:返回值不同

Reflect.getOwnPropertyDescriptor等(反射机制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const obj = { x1y2 } 
console.log(Object.getOwnPropertyDescriptor(obj, 'y')) //检查obj下的属性

let d = new Date()
console.log(Reflect.getPrototypeOf(d)) //快速打印原型对象上的方法

const obj = { x1y2 }
console.log(Reflect.has(obj, 'y')) //验证对象上有没有属性,该方法Reflect特有

Object.freeze(obj) //冻结,使不可扩展
obj.z=3 //不可增加删减
console.log(Reflect.isExtensible(obj)) //检测是否可扩展

console.log(Reflect.ownKeys(obj)) //返回对象的自身属性
console.log(Reflect.ownKeys([12])) //返回1,2,length(索引加长度)

Reflect.preventExtensions(obj) //reflect提供的API防止参数扩展

Reflect.set(obj, 'z'4) //reflect提供的API添加数据
const arr = ['duck''duck''duck']
Reflect.set(arr, 2'goose') //修改数据
console.log(arr)

Reflect.setPrototypeOf(arr, String.prototype) //将数组的原型改成字符串的原型

proxy basic syntax(该怎样使用代理功能)

语法

1
let p=new Proxy(target,handler)

通俗的讲第一个参数target就是用来代理的“对象”,被代理之后他是不能直接被访问的,而handler就是实现代理的过程。

主要业务做信息的读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let o = {
  name: 'xiaoming',
  price: 190
}
let d = new Proxy(o, {
  get (target, key) {
    if (key === 'price') {
      return target[key] + 20
    } else {
      return target[key]
    }
  }
})
console.log(d.price, d.name)

Schema Validation(写操作进行拦截)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let o = {
  name: 'xiaoming',
  price: 190
}
let d = new Proxy(o, {
  get (target, key) {
    return target[key]
  },
  set (target, key, value) { //加个set函数来禁止修改
    return false
  }
})
d.price = 300
console.log(d.price, d.name)

ES5中禁止写入的写法,完全锁死

1
2
3
4
5
6
7
for (let [key] of Object.entries(o)) {
  Object.defineProperty(o, key, {
    writable: false
  })
}
o.pirce = 300
console.log(o.name, o.price)

更复杂的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//监听错误
window.addEventListener('error', (e) => {
  console.log(e.message)
  // report('./')
}, true)

let o = {
  name: 'xiaoming',
  price: 190
}
// 校验规则
let validator = (target, key, value) => {
  if (Reflect.has(target, key)) {
    if (key === 'price') {
      if (value > 300) {
        // 不满足规则就要触发错误
        throw new TypeError('price exceed 300')
        // return false
      } else {
        target[key] = value
      }
    } else {
      target[key] = value
    }
  } else {
    return false
  }
}
let d = new Proxy(o, {
  get (target, key) {
    return target[key] || ''
  },
  set: validator //封装成一个模块
})
d.price = 301
d.name = 'hanmeimei'
d.age = 400
console.log(d.price, d.name, d.age)

不同的实例对象每次生成的值唯一,且不能被修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Component {
  constructor () {
    this.proxy = new Proxy({
      id: Math.random().toString(36).slice(-8) //生成随机数,转换成36进制的字符串,截取后8位
    }, {})
  }
  get id () {
    return this.proxy.id
  }
}
let com = new Component()
let com2 = new Component()
for (let i = 0; i < 10; i++) {
  console.log(com.id, com2.id)
}
com.id = 'abc'
console.log(com.id, com2.id)

Revocable Proxy

撤销代理,让代理失效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let o = {
  name: 'xiaoming',
  price: 190
}
let d = Proxy.revocable(o, {
  get (target, key) {
    if (key === 'price') {
      return target[key] + 20
    } else {
      return target[key]
    }
  }
})
console.log(d.proxy.price, d)
//d包含2部分内容,第一部分为被代理的信息,第二部分为revoke撤销
console.log(d.proxy.price, d)
setTimeout(function ({
  d.revoke() //代理的撤销
  setTimeout(function ({
    console.log(d.proxy.price)
  }, 100)
}, 1000)
0%