ES面试题
本篇文章是小白自己对面试题的一个记录与积累。
如若发下不对或则不完善的地方,望指出我好及时改正。谢谢
ES6(2015)新增方法面试题
1.let const var比较
var:全局变量
var定义变量存在变量提升:只提升声明语句,不提升赋值语句
let:块级作用域
不存在变量提升,其所声明的变量一定要在声明语句之后使用。
const:块级作用域
声明变量时必须赋值,完成初始化后,值不得更改。
2.反引号(`)标识
它可以当作普通字符串使用,也可以用来定义多行字符串,也可以在字符串中嵌入变量,js表达式或函数,变量、js表达式或函数需要写在${ }中。
3.函数默认参数
const fn = (x='1')=>{console.log(a)}
4.箭头函数
更简短的函数并且不绑定
this
使用function定义的函数,this的指向随着调用环境的变化而变化的,而箭头函数中的this指向是固定不变的,一直指向的是定义函数的环境。
function是可以定义构造函数的,而箭头函数是不行的。
箭头函数定义在调用之前
5.属性简写
const obj = {name}
6.方法简写
const o = { method() { return "Hello!"; } }; // 等同于 const o = { method: function() { return "Hello!"; } };
7.Object.keys()方法,获取对象的所有属性名或方法名
var fruits = { first: "apple", second:"banana ",last: "banana", }, Object.keys(fruits) // 返回数组: first,second, last
8.Object.assign ()原对象的属性和方法都合并到了目标对象
浅拷贝
let a = { name:'tom', age:20, friends:{ student:['jack'] } } let b = Object.assign({},a); a.friends.student = ['tony']; console.log(a);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } } console.log(b);// { name: 'tom', age: 20, friends: { student: [ 'tony' ] } }
深拷贝
let obj = { name:'tom', age:10, friend:{ name:'jack' } }; let copy = JSON.parse(JSON.stringify(obj)); obj.name = 'elric'; console.log(obj);// {name: "elric", age: 10, friend: {…}} console.log(copy);// {name: "tom", age: 10, friend: {…}}
9.for…of 循环
const products = ['oranges', 'apples']; for (const product of products) { console.log(product); } // 'oranges' // 'apples' const message = 'hello'; for (const character of message) { console.log(character); } // 'h' // 'e' // 'l' // 'l' // 'o'
10.import和export
1、export default,其他模块加载该模块时,
import
命令可以为该匿名函数指定任意名字。
11.Promise对象
Promise 是JS中进行异步编程的新的解决方案
有三种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
一旦状态改变,就不会再变。
Promise 的状态改变
- pending 变为 resolved
- pending 变为rejected
Async/await 实际上只是一种基于 promises 的糖衣语法糖,Async/await 和 promises 一样,都是非堵塞式的,Async/await 让异步代码更具同步代码风格,这也是其优势所在。
Async/await 比 Promise 更优越的表现
简洁干净,使用 async/await 能省去写多少行代码
错误处理,async/wait 能用相同的结构和好用的经典 try/catch 处理同步和异步错误,错误堆栈能指出包含错误的函数。
调试,async/await 的一个极大优势是它更容易调试,使用 async/await 则无需过多箭头函数,并且能像正常的同步调用一样直接跨过 await 调用。
12.解构赋值
[a, b, ...rest] = [10, 20, 30, 40, 50]; console.log(a); // 10 console.log(b); // 20 console.log(rest); // [30, 40, 50]
13.set数据结构(可用于快速去重)
类似于数组,但是成员的值都是唯一的,没有重复。Set本身是一个构造函数,用来生成Set数据结构
var arr = [1, 2, 3, 4, 2, 3, 4, 2]; console.log([...new Set(arr)]); //[ 1, 2, 3, 4 ]
14.Spread Operator 展开运算符(…)
function addNumbers(...numbers){ return numbers.reduce((sum,number) => { return sum + number; },0) } console.log(addNumbers(1,2,1,3,5,))//12
15.字符串新增方法
1、String.fromCodePoint()
用于从Unicode码点返回对应的字符,但是这个字符不能正确识别码点大于0xFFFF的字符
2、String.raw()
该方法返回一个斜杠都被转义(即斜杠前再加一个斜杠)的字符串,常用于模板字符串的处理方法。
String.raw`Hi\n${2+3}!`; // 返回 "Hi\\n5!" String.raw`Hi\u000A!`; // 返回 "Hi\\u000A!"
3、codePointAt()
与String.fromCharCode()方法类似,String.charCodeAt()也不能正确处理Unicode 码点大于0xFFFF的字符。
var s = "?"; s.length // 2 s.charAt(0) // '' s.charAt(1) // '' s.charCodeAt(0) // 55362 s.charCodeAt(1) // 57271 let s = '?a'; s.codePointAt(0) // 134071 s.codePointAt(1) // 57271 s.codePointAt(2) // 97
4、includes() startsWith() endsWith()
- includes(): 返回布尔值。表示参数字符串是否在原字符串里面。
- startsWith(): 返回布尔值。表示参数字符串是否在原字符串头部。
- endsWith(): 返回布尔值。表示参数字符串是否在原字符串尾部。
let s = 'Hello world!'; s.startsWith('Hello') // true s.endsWith('!') // true s.includes('o') // true let s = `Hello world!` s.startsWith(`world`, 6) //true s.endsWith(`Hello`, 5) //true s.includes(`Hello`, 6) //false
5、repeat()
repeat()方法返回一个新字符串,表示将原字符串重复n次。
参数如果是小数,会被取整。
参数时infinity或-1,会报错。
参数如果是0到-1之间的小数,会被取整为0。
参数为NaN等同于0。
参数为字符串,则先转换为数字。
`hello`.repeat(2) //"hellohello" `na`.repeat(1.99) //"na" `na`.repeat(Infinity) //range error `na`.repeat(-1) //range error `na`.repeat(-0.9) //"" `na`.repeat(NaN) // "" `na`.repeat("na) //"" `na`.repeat("2) //"nana"
ES6数组面试题
1.forEach()
let array = [1,2,3,4] array.forEach(item,index,arr)=>{ //arr 即 array }
2.map()
map和forEach等遍历方法不同,在forEach中return语句是没有任何效果的,而map则可以****改变当前循环的值**,****返回一个新的被改变过值之后的数组****(map需return),一般用来处理需要修改某一个数组的值。
let arr1 = [1,2,3]; let arr2 = arr1.map((value,key,arr) => { console.log(value) // 1,2,3 console.log(key) // 0,1,2 console.log(arr) //[1,2,3] [1,2,3] [1,2,3] return value * value; })
3.filter()
filter函数可以看成是一个过滤函数,返回符合条件的元素的数组
let arr1 = [1,2,3]; let arr2 = arr1.filter((value,key,arr) => { console.log(value) // 1,2,3 console.log(key) // 0,1,2 console.log(arr) // [1,2,3] return value >= 3 ? false : true; }) console.log(arr1); // [ 1, 2, 3 ] console.log(arr2); // [ 1, 2 ]
4.reduce()
对数组中的所有元素调用指定的回调函数。
该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供。
arr1.reduce(a,b) //两个参数 a是处理方法,b为初始化参数
let arr1=['a','b','c']; let rs1 = arr1.reduce((prev,cur) =>{ return prev+'::' +cur }) console.info('rs1',rs1); //rs1 a::b::c let arr2=[[1,2],[3,4],[5,6],[7]] let rs2 = arr2.reduce((a, b) => { return a.concat(b) },[]) console.info('rs2',rs2);//输出 [1,2,3,4,5,6,7]
5.some() every()
every:一假即假
some:一真即真
let computers = [ {name:"Apple",ram:8}, {name:"IBM",ram:4}, {name:"Acer",ram:32}, ]; let result= computers.every((computer)=>{ return computer.ram > 16 }) console.log(result)//false; let some = computers.some((computer)=>{ return computer.ram > 16 }) console.log(some)//true;
ES6编程题
1.使用解构,实现两个变量的值的交换
let a=5;
let b=3;
[a,b]=[b,a]
2.利用数组推导,计算出数组 [1,2,3,4] 每一个元素的平方并组成新的数组。
var arr1 = [1, 2, 3, 4];
var arr2 = [];
for (i of arr1) arr2.push(i * i)
console.log(arr2);
ES7(2016)
1、Array.prototype.includes()
数组内包含什么
[1].includes(1); // true
2、 指数操作符
2**10; // 1024
ES8(2017)
1. async/await
异步终极解决方案
async getData(){ const res = await api.getTableData(); // await 异步任务 // do something }
2、Object.values()
1
Object.values({a: 1, b: 2, c: 3}); // [1, 2, 3]
3、Object.entries()
1
Object.entries({a: 1, b: 2, c: 3}); // [["a", 1], ["b", 2], ["c", 3]]
4、String padding
// padStart 'hello'.padStart(10); // " hello" // padEnd 'hello'.padEnd(10) "hello "
5、函数参数列表结尾允许逗号
6、Object.getOwnPropertyDescriptors()
获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。
7、SharedArrayBuffer对象
SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,
/**Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。 * * @param {*} length 所创建的数组缓冲区的大小,以字节(byte)为单位。 * @returns {SharedArrayBuffer} 一个大小指定的新 SharedArrayBuffer 对象。其内容被初始化为 0。 */ new SharedArrayBuffer(10)
8、Atomics对象
Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。
ES9(2018)
1. 异步迭代
await可以和for…of循环一起使用,以串行的方式运行异步操作
async function process(array) {
for await (let i of array) {
// doSomething(i);
}
}
2. Promise.finally()
Promise.resolve().then().catch(e => e).finally();
3. Rest/Spread 属性
const values = [1, 2, 3, 5, 6];
console.log( Math.max(...values) ); // 6
4. 正则表达式命名捕获组
const reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
const match = reg.exec('2021-02-23');
5. 正则表达式反向断言
(?=p)、(?<=p) p 前面(位置)、p 后面(位置)
(?!p)、(?<!p>) 除了 p 前面(位置)、除了 p 后面(位置)
(?<=w)
(?<!w)
6. 正则表达式dotAll模式
正则表达式中点.匹配除回车外的任何单字符,标记s改变这种行为,允许行终止符的出现
/hello.world/.test('hello\nworld'); // false
ES10(2019)
1. Array.flat()和Array.flatMap()
flat()
[1, 2, [3, 4]].flat(Infinity); // [1, 2, 3, 4]
flatMap()
[1, 2, 3, 4].flatMap(a => [a**2]); // [1, 4, 9, 16]
2. String.trimStart()和String.trimEnd()
去除字符串首尾空白字符
3. String.prototype.matchAll
matchAll()为所有匹配的匹配对象返回一个迭代器
const raw_arr = 'test1 test2 test3'.matchAll((/t(e)(st(\d?))/g));
const arr = [...raw_arr];
4. Symbol.prototype.description
只读属性,回 Symbol 对象的可选描述的字符串。
Symbol('description').description; // 'description'
5. Object.fromEntries()
返回一个给定对象自身可枚举属性的键值对数组
// 通过 Object.fromEntries, 可以将 Map 转化为 Object:
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
console.log(Object.fromEntries(map)); // { foo: "bar", baz: 42 }
6. 可选 Catch
ES11(2020)
1. Nullish coalescing Operator(空值处理)
表达式在 ?? 的左侧 运算符求值为undefined或null,返回其右侧。
let user = {
u1: 0,
u2: false,
u3: null,
u4: undefined
u5: '',
}
let u2 = user.u2 ?? '用户2' // false
let u3 = user.u3 ?? '用户3' // 用户3
let u4 = user.u4 ?? '用户4' // 用户4
let u5 = user.u5 ?? '用户5' // ''
2. Optional chaining(可选链)
?.用户检测不确定的中间节点
let user = {}
let u1 = user.childer.name // TypeError: Cannot read property 'name' of undefined
let u1 = user.childer?.name // undefined
3. Promise.allSettled
返回一个在所有给定的promise已被决议或被拒绝后决议的promise,并带有一个对象数组,每个对象表示对应的promise结果
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => reject('我是失败的Promise_1'));
const promise4 = new Promise((resolve, reject) => reject('我是失败的Promise_2'));
const promiseList = [promise1,promise2,promise3, promise4]
Promise.allSettled(promiseList)
.then(values=>{
console.log(values)
});
4. import()
按需导入
5. 新基本数据类型BigInt
任意精度的整数
6. globalThis
- 浏览器:window
- worker:self
- node:global
ES12(2021)
1. replaceAll
返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉
const str = 'hello world';
str.replaceAll('l', ''); // "heo word"
2. Promise.any
Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise
const promise1 = new Promise((resolve, reject) => reject('我是失败的Promise_1'));
const promise2 = new Promise((resolve, reject) => reject('我是失败的Promise_2'));
const promiseList = [promise1, promise2];
Promise.any(promiseList)
.then(values=>{
console.log(values);
})
.catch(e=>{
console.log(e);
});
3. WeakRefs
使用WeakRefs的Class类创建对对象的弱引用(对对象的弱引用是指当该对象应该被GC回收时不会阻止GC的回收行为)
4. 逻辑运算符和赋值表达式
逻辑运算符和赋值表达式,新特性结合了逻辑运算符(&&,||,??)和赋值表达式而JavaScript已存在的 复合赋值运算符有:
a ||= b
//等价于
a = a || (a = b)
a &&= b
//等价于
a = a && (a = b)
a ??= b
//等价于
a = a ?? (a = b)
5. 数字分隔符
数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性
const money = 1_000_000_000;
//等价于
const money = 1000000000;
1_000_000_000 === 1000000000; // true