高优先级知识点,需要熟练掌握。
不能直接捕获
try {
setTimeout(() => {
throw new Error('err')
}, 200)
} catch (err) {
console.log(err)
}
// 上面是错误的示范
// 正确的写法
// 方法1: 使用Promise
new Promise((resolve, reject) => {
setTimeout(() => {
try {
throw new Error('err')
// 如果没有错误,可以调用resolve()
// resolve('成功结果');
} catch (error) {
reject(error)
}
}, 200)
})
.then(result => {
console.log('成功:', result)
})
.catch(err => {
console.log('捕获到错误:', err)
})
// 方法2: 使用async/await (更接近同步代码的写法)
async function handleAsyncOperation() {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
try {
throw new Error('err')
// resolve('成功结果');
} catch (error) {
reject(error)
}
}, 200)
})
} catch (err) {
console.log('捕获到错误:', err)
}
}
总结:try...catch 不能捕获到异步代码中的错误,对于异步代码,需要结合 Promise 、async/await 或者事件监听器等机制来处理错误。
Generator 是 ES6 引入的新语法,Generator 是一个可以暂停和继续执行的函数。
function* count() {
yield 1
yield 2
return 3
}
let c = count()
console.log(c.next()) // { value: 1, done: false }
console.log(c.next()) // { value: 2, done: false }
console.log(c.next()) // { value: 3, done: true }
console.log(c.next()) // { value: undefined, done: true }
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用 arguments 对象了。
rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
// 报错
function f(a, ...b, c) {
// ...
}
// 正确
function f(a, ...b) {
}
ES5:语法层面没有“类”,全靠函数 + prototype 模拟,繁琐、易错。 ES6:引入真正语法级的 class,语义更清晰、继承更安全,但仍基于原型链实现,只是语法糖而非新模型。
箭头函数没有自己的 this,它的 this 是在定义时(词法作用域)就绑定好的外层(最近一层非箭头函数)的 this,并且永远不变。
简单记忆:箭头函数里的 this 跟写代码时所在的位置有关,跟运行时谁调用它无关。
let sayHi = () => {
console.log('Hello World !')
}
console.log(sayHi.prototype) // undefined
Proxy 相比 Object.defineProperty 提供了更全面的拦截功能,支持更多的操作类型,对数组和新增属性有更好的支持,并且在性能和错误处理方面也有优势。这也是为什么 Vue 3.0 选择使用 Proxy 替代 Object.defineProperty 来实现其响应式系统的原因。但是,Proxy 的浏览器兼容性不如 Object.defineProperty,在需要支持旧版浏览器的项目中需要谨慎使用。
用户想了解 ES6 中的 Reflect 对象的用途。我需要搜索相关信息,然后整理成一个全面的回答。
toolName: web_search
status: success
query: ES6 Reflect 对象 用途 特点 方法
我需要继续搜索更多关于 Reflect 对象的具体方法和用例,以便提供更全面的回答。
toolName: web_search
status: success
query: ES6 Reflect 对象 方法 实例 应用场景
Reflect 是 ES6 引入的一个新的全局对象,它提供了一系列用于操作对象的静态方法。Reflect 对象的设计目的主要有以下几点:
将对象的内部方法集中化管理
Object.defineProperty)移植到 Reflect 对象上提供函数式的对象操作方法
delete、in 等)转变为函数式操作(如 Reflect.deleteProperty、Reflect.has)与 Proxy 配合使用
改进错误处理方式
不是构造函数
所有方法都是静态的
Reflect 对象提供了 13 个静态方法,这些方法与 Proxy 的处理器方法一一对应:
Reflect.apply(target, thisArgument, argumentsList)
Function.prototype.apply()Reflect.apply(Math.max, undefined, [1, 2, 3]) 等同于 Math.max.apply(undefined, [1, 2, 3])Reflect.construct(target, argumentsList[, newTarget])
new target(...args)Reflect.defineProperty(target, propertyKey, attributes)
Object.defineProperty(),但返回布尔值表示操作是否成功Reflect.deleteProperty(target, propertyKey)
delete target[name]Reflect.get(target, propertyKey[, receiver])
target[name]Reflect.getOwnPropertyDescriptor(target, propertyKey)
Object.getOwnPropertyDescriptor()Reflect.getPrototypeOf(target)
Object.getPrototypeOf()Reflect.has(target, propertyKey)
in 运算符相同Reflect.isExtensible(target)
Object.isExtensible()Reflect.ownKeys(target)
Object.keys()Reflect.preventExtensions(target)
Object.preventExtensions()Reflect.set(target, propertyKey, value[, receiver])
Reflect.setPrototypeOf(target, prototype)
const obj = { name: 'John', age: 30 }
// 使用 Reflect.has
Reflect.has(obj, 'name') // true
Reflect.has(obj, 'gender') // false
// 等同于使用 in 运算符
'name' in obj // true
'gender' in obj // false
const obj = { name: 'John' }
// 获取属性值
Reflect.get(obj, 'name') // 'John'
// 设置属性值
Reflect.set(obj, 'age', 30) // true
console.log(obj) // { name: 'John', age: 30 }
const target = { name: 'John' }
const handler = {
get(target, prop, receiver) {
console.log(`Getting ${prop}`)
return Reflect.get(target, prop, receiver)
},
set(target, prop, value, receiver) {
console.log(`Setting ${prop} to ${value}`)
return Reflect.set(target, prop, value, receiver)
}
}
const proxy = new Proxy(target, handler)
proxy.name // 输出: "Getting name",返回: "John"
proxy.age = 30 // 输出: "Setting age to 30",返回: true
// 查找数组中的最大值
const arr = [1, 3, 5, 7]
// 使用 Reflect.apply
const max = Reflect.apply(Math.max, undefined, arr) // 7
// 等同于
const max2 = Math.max.apply(undefined, arr) // 7
总结来说,Reflect 对象提供了一种更加函数式、更加统一的方式来操作对象,特别是在与 Proxy 配合使用时,能够更方便地实现对象的元编程。
在 let/const 声明语句 之前 的代码区域里,该变量已存在但不可访问;一旦访问就会抛出 ReferenceError
console.log(a) // ❌ ReferenceError: Cannot access 'a' before initialization
let a = 1
对比 var
console.log(b) // undefined(不会报错)
var b = 2
ES5 的对象属性名都是字符串,这容易造成属性名的冲突
Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
es2017 的新语法,async/await 就是 generator + promise 的语法糖 async/await 就是将异步操作以同步的流程表达出来,避免了回调地狱,而且语义更清晰。
Generator 让函数拥有了「时间切片」能力,下面是高频使用场景
| 场景 | 说明 | 极简示例 |
|---|---|---|
| 1. 自定义可迭代对象 | 用 yield* 轻松写出 for…of 可用的数据结构 | function* fib(){ let a=0,b=1; while(true){ yield a; [a,b]=[b,a+b]; } } |
| 2. 惰性序列/无限流 | 按需计算,节省内存 | 同上斐波那契,用到第 n 个才计算第 n 个 |
| 3. 异步流程管理 | 在 async/await 出现前,用库(co、redux-saga)把 Generator 变成「同步写法异步执行」 | co(function*(){ const u = yield fetch('/user'); console.log(u); }); |
| 4. 状态机 | 用 yield 做状态节点,代码比回调/标志位清晰很多 | 见下方小例子 |
| 5. 任务分片 & 可取消 | 长任务拆成多次 yield,浏览器有时间渲染;可中途 return 取消 | 页面大列表分批渲染 |