ES6真题合集(一)
- 1. var、let、const之间的区别
- 2. ES6中数组新增了哪些扩展
- 2.1 扩展运算符
- 2.2 Array.from() 方法
- 2.3 Array.of() 方法
- 2.4 find() 和 findIndex() 方法
- 2.5 箭头函数
- 2.6 模板字符串
- 3. ES6中对象新增了哪些扩展
- 3.1 属性的简写
- 3.2 属性名表达式
- 3.3 方法简写
- 3.4 计算得到的属性名
- 3.5 Object 新增方法
- 4. 函数新增了哪些扩展
- 4.1 函数参数的默认值
- 4.2 rest参数(剩余参数)
- 4.3 函数的name属性
- 4.4 箭头函数
- 4.5 扩展运算符
- 5. ES6中 Promise
1. var、let、const之间的区别
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域或全局作用域 | 块级作用域 | 块级作用域 |
变量提升 | 有 | 无 | 有 |
暂时性死区 | 无 | 有 | 有 |
重新声明 | 允许 | 不允许 | 不允许 |
重新赋值 | 允许 | 允许 | 不允许(但对象/数组内容可以修改) |
必须初始化 | 不需要 | 不需要 | 需要 |
全局对象属性 | 成为全局对象属性(如window) | 不成为全局对象属性 | 不成为全局对象属性 |
2. ES6中数组新增了哪些扩展
2.1 扩展运算符
使用 … 语法可以将一个数组展开成多个独立的元素,或者将多个元素合并为一个数组。
// 展开数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5] // 合并数组
const arr3 = [6, 7];
const arr4 = [...arr2, ...arr3]; // [1, 2, 3, 4, 5, 6, 7]
2.2 Array.from() 方法
通过类似数组的对象或可迭代对象创建一个新的数组。
// 字符串转换为数组
const str = 'hello';
const arr5 = Array.from(str); // ["h", "e", "l", "l", "o"] // 类似数组的对象转换为数组
const arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
const arr6 = Array.from(arrayLike); // ["a", "b", "c"]
2.3 Array.of() 方法
创建一个由传入参数组成的新数组。与Array构造函数不同,Array.of()不会因为单个数值参数而创建特殊类型的数组。
const arr7 = Array.of(1); // [1]
const arr8 = Array.of(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
2.4 find() 和 findIndex() 方法
find() 方法用于在数组中查找满足指定条件的第一个元素。
findIndex() 方法用于查找满足指定条件的第一个元素的索引。
const numbers = [1, 2, 3, 4, 5]; // 使用 find()
const foundNumber = numbers.find(num => num > 3); // 4 // 使用 findIndex()
const foundIndex = numbers.findIndex(num => num > 3); // 3
2.5 箭头函数
虽然箭头函数本身不是数组的扩展,但它在数组方法(如.map()、.filter()和.forEach())中的应用,使得数组操作更加简洁。
const numbers = [1, 2, 3, 4, 5]; // 使用箭头函数和 map()
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10] // 使用箭头函数和 filter()
const evenNumbers = numbers.filter(num => num % 2 === 0); // [2, 4]
2.6 模板字符串
虽然模板字符串不是直接针对数组的扩展,但它与数组的结合使用可以创建动态的数组内容。
const items = ['apple', 'banana', 'cherry'];
const list = `Fruits: ${items.join(', ')}`; // Fruits: apple, banana, cherry
3. ES6中对象新增了哪些扩展
3.1 属性的简写
允许在对象字面量中直接写入变量和函数作为对象的属性和方法。
const foo = 'bar';
const baz = { foo }; // 等同于 { foo: foo } function hello() { console.log('Hello, world!');
}
const obj = { hello }; // 等同于 { hello: hello }
3.2 属性名表达式
允许在对象字面量中使用表达式作为属性名,表达式需要放在方括号[]内。
let propName = 'myProp';
let obj = { [propName]: 'Hello', ['a' + 'b']: 'World'
}; // 等同于 { myProp: 'Hello', ab: 'World' }
3.3 方法简写
允许直接写函数名作为对象的方法,不需要使用冒号和function关键字。
const obj = { sayHello() { console.log('Hello, world!'); }
};
// 等同于 const obj = { sayHello: function() { console.log('Hello, world!'); } };
3.4 计算得到的属性名
类似于属性名表达式,但特别指出,这种方式可以用于定义方法名。
let methodName = 'greet';
let obj = { [methodName]() { return 'Hello'; }
};
// obj.greet() 会返回 'Hello'
3.5 Object 新增方法
- Object.is(): 用于比较两个值是否严格相等,它与严格相等运算符(===)的行为基本一致。
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0, -0)); // false
console.log(Object.is(5, 5)); // true
console.log(Object.is('foo', 'foo')); // true
- Object.assign(): 用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 }; Object.assign(target, source1, source2); console.log(target); // { a: 1, b: 2, c: 3 }
- Object.getOwnPropertyDescriptors(): 返回一个给定对象所有自身属性(包括不可枚举属性但不包括Symbol值作为名称的属性)的属性描述符组成的对象。
const obj = { name: 'Alice'
}; const descriptor = Object.getOwnPropertyDescriptor(obj, 'name'); console.log(descriptor); // { value: 'Alice', writable: true, enumerable: true, configurable: true } // 注意:Object.getOwnPropertyDescriptors()通常用于更复杂的场景,比如合并对象时保留属性描述符
- Object.setPrototypeOf(): 设置一个对象的原型(即,内部[[Prototype]]属性)到另一个对象或null。
const obj = { name: 'Alice'
}; const descriptor = Object.getOwnPropertyDescriptor(obj, 'name'); console.log(descriptor); // { value: 'Alice', writable: true, enumerable: true, configurable: true } // 注意:Object.getOwnPropertyDescriptors()通常用于更复杂的场景,比如合并对象时保留属性描述符
- Object.getPrototypeOf(): 返回指定对象的原型(即,内部[[Prototype]]属性的值)。
- Object.keys(), Object.values(), Object.entries(): 分别返回给定对象所有可枚举属性的键名、值、键值对数组。
const obj = { name: 'Alice', age: 30, city: 'New York'
}; console.log(Object.keys(obj)); // ['name', 'age', 'city']
console.log(Object.values(obj)); // ['Alice', 30, 'New York']
console.log(Object.entries(obj)); // [['name', 'Alice'], ['age', 30], ['city', 'New York']]
- Object.fromEntries(): 是Object.entries()的逆操作,把键值对列表转换为一个对象。
const entries = [['name', 'Alice'], ['age', 30], ['city', 'New York']]; const obj = Object.fromEntries(entries); console.log(obj); // { name: 'Alice', age: 30, city: 'New York' }
4. 函数新增了哪些扩展
4.1 函数参数的默认值
不能直接为函数的参数指定默认值,只能采用变通的方法。ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x, y = 'World') { console.log(x, y);
}
log('Hello'); // Hello World
log('Hello', 'China'); // Hello China
4.2 rest参数(剩余参数)
rest参数(形式为…变量名)用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum;
}
add(1, 2, 3); // 6
4.3 函数的name属性
ES6为每个函数都提供了一个name属性,返回该函数的函数名。
function foo() {}
console.log(foo.name); // "foo" const bar = function() {};
console.log(bar.name); // "bar" const baz = () => {};
console.log(baz.name); // "baz" 或可能是 "anonymous" 在某些环境中
4.4 箭头函数
箭头函数提供了一种更简洁的函数语法。它没有自己的this、arguments、super或new.target。这些值由外围的正常函数或全局作用域定义。
const arrowFunc = (x, y) => x + y;
console.log(arrowFunc(1, 2)); // 3 // 当函数体中只有一个表达式时,{} 和 return 可以省略
const double = x => x * 2;
console.log(double(3)); // 6
4.5 扩展运算符
扩展运算符(…)可以在函数调用/函数体内部,展开一个数组(或类似数组对象)为多个独立的参数。
function greet(name, age, city) { console.log(`Hello, ${name}. You are ${age} years old and live in ${city}.`);
} const person = ['Alice', 30, 'New York'];
greet(...person); // Hello, Alice. You are 30 years old and live in New York.
5. ES6中 Promise
用于处理异步操作的对象,它表示一个最终可能完成(也可能被拒绝)的异步操作及其结果值。Promise 对象代表了一个异步操作的最终完成(或失败)及其结果值的状态。
Promise 对象有三种状态:
- pending(待定):初始状态,既不是成功,也不是失败状态。
- fulfilled(已实现):意味着操作成功完成。
- rejected(已拒绝):意味着操作失败。
1.开始:从调用 new Promise(executor) 开始,其中 executor 是一个执行函数,它接收两个参数:resolve 和 reject。
2.Pending(待定):这是 Promise 的初始状态。
3.resolve(value):当异步操作成功完成时,调用 resolve 函数并传入一个值。这会将 Promise 的状态从 Pending 变为 Fulfilled,并将结果值传递给 .then 方法中注册的 onFulfilled 回调函数。
4.Fulfilled(已实现):这是 Promise 操作成功的状态。一旦进入这个状态,就不能再改变。此时可以调用 .then 方法来处理成功的结果。
5.reject(reason):当异步操作失败时,调用 reject 函数并传入一个原因。这会将 Promise 的状态从 Pending 变为 Rejected,并将失败原因传递给 .catch 方法中注册的 onRejected 回调函数。
6.Rejected(已拒绝):这是 Promise 操作失败的状态。一旦进入这个状态,就不能再改变。此时可以调用 .catch 方法来处理失败的情况。
7.then(onFulfilled, onRejected):用于处理 Promise 的成功或失败结果。它返回一个新的 Promise 对象,以便进行链式调用。
8.catch(onRejected):是 .then(null, onRejected) 的简写形式,专门用于处理 Promise 的失败情况。
9.循环:.then 和 .catch 方法返回的都是新的 Promise 对象,这意味着可以进行链式调用,形成一个 Promise 链。每个 Promise 都可以有自己的成功或失败处理函数。
注意点:
1.一旦 Promise 被 resolve 或 reject,它的状态就不能再改变。
2.如果没有在 Promise 链的末尾处理失败情况(即没有 .catch),则可能导致未捕获的拒绝(Unhandled rejection),这通常是编程错误,应该避免。
3.Promise 的链式调用允许你更优雅地处理异步操作的流程,避免了传统的“回调地狱”。
// 创建一个新的 Promise 对象
function fetchData() { return new Promise((resolve, reject) => { // 假设这是一个异步操作,比如网络请求 // 这里我们使用 setTimeout 来模拟异步操作 setTimeout(() => { // 模拟网络请求成功,返回数据 let data = { message: 'Data fetched successfully!' }; resolve(data); // 将 Promise 的状态设置为 Fulfilled,并传递结果 }, 2000); // 假设异步操作需要 2 秒完成 // 如果需要模拟网络请求失败,可以调用 reject 函数 // reject(new Error('Failed to fetch data')); });
} // 使用 Promise
fetchData() .then(data => { // 这个回调函数会在 Promise 状态为 Fulfilled 时被调用 console.log(data.message); // 输出:Data fetched successfully! // 可以继续返回一个新的 Promise 或其他值 // return fetchAnotherData(); // 假设这是另一个异步操作 }) .catch(error => { // 这个回调函数会在 Promise 状态为 Rejected 时被调用 console.error('An error occurred:', error.message); }) .finally(() => { // finally 方法无论 Promise 是成功还是失败都会被调用 console.log('Promise processing completed.'); }); // 控制台输出将会是:
// Data fetched successfully!
// Promise processing completed.