最近在找新的机会,于是看了投了一些大厂的简历。可惜的是,国内的游戏厂依旧是架子极高,而相对的其他厂则慢慢走向僵化。
或许以前是为了筛选人才。但以现在这种搜索一下,3分钟就能知道答案的情况来看,业界不仅在走下坡路,而且创新能力也在下降,面试的水平不敢恭维。
第一家
一面
常见八股文:
- http1.1和http2.0的区别。 答案: 多路复用。
- BFC的问题结局.
答案:
overflow: hidden; - 变量提升问题:
for(let i = 0; i <= 5; i++ ) {
console.log(i)
}
for(var i = 0; i <= 5; i++ ) {
console.log(i)
}
const a = [1,2,3];
for(var j = 0; j < a.length; j++ ) {
console.log(a[j])
}
- map获取key-value
面试过程中发现面试官对
Map的理解只停留在表面,而对实际内部对如何迭代和取值并不清楚。
原题:
const a = new Map([["a", 1], ["b", 2]])
console.log(a.entries())
面试官只是照本宣科去考察对基础语法的概念,却没有注意到实际下的问题。
以stackoverflow's iterator这篇帖子为例。
首先,先看调用Entries不生效的场景。
function pushAndLog(array, values) {
array.push(...values);
for (const value of values.entries()) {
console.log(value);
}
}
const array = [];
const map = new Map([["a", 1], ["b", 2]]);
pushAndLog(array, map.keys());
在这种情况下,将不会进入到for循环内部。
原因:
Map.keys() / Map.values() / Map.entries()方法返回的都是迭代器而不是可迭代对象。- 和可迭代对象相反的是,迭代器是一个有状态的对象。一旦使用,则不可复用。如果需要使用,则需要自己去构造一个新的迭代器。
答案:
- 修复上述代码最简单的办法是解构为函数。因为函数是一个可迭代对象,可以多次迭代,也就是自定义迭代器
pushAndLog(array, [...map.keys()]);
本质就是:
var test = {}
testIterator[Symbol.iterator] = function*() {
yield 1;
yield 2;
};
[...testIterator] // [1,2]
但是这种办法不是最高效的,会消耗内存和CPU的时间。于是,我们可以写更为高效的办法:
export function getIterableKeys<K, V>(map: Iterable<readonly [K, V]>): Iterable<K> {
return {
[Symbol.iterator]: function* () {
for (const [key, _] of map) {
yield key;
}
}
};
}
export function getIterableValues<K, V>(map: Iterable<readonly [K, V]>): Iterable<V> {
return {
[Symbol.iterator]: function* () {
for (const [_, value] of map) {
yield value;
}
}
};
}
二面
- 你们公司的BFF架构.
- BFF为什么要和SSO通讯。
- 架构升级的话,你主要是做了什么。
- 升级API gateway的好处。
- Schema-AST这种低代码平台的应用?
- 怎么管理团队的?
- WebGL主要做了什么?
第二家
1. 八股文
问题: js的对象在堆还是栈? 答案: 堆 问题: js的字符串在堆还是栈? 答案: 栈
1. var-结果
var a
if('a' in window) {
a = 1
}
console.log(a) // 1
2. let-结果
let a
if('a' in window) {
a = 1
}
console.log(a) // undefined
3. use strict-结果
'use strict'
let a
if('a' in window) {
a = 1
}
console.log(a) // undefined
2. TypeScript
已经声明一个接口后,转而对这个接口进行增查删改。
1. Pick
interface IUser {
name: string
age: string
location: string
}
interface ITest {
name: string
age: string
map: string[]
}
type ITest1 = Pick<IUser, "name" | "age">
interface ITest2 extends ITest1 {
map: string[]
}
const a: ITest2 = {
name: '1',
age: '2',
map: [
'1'
]
}
简化版:
interface IUser {
name: string
age: string
location: string
}
interface ITest extends Pick<IUser, "name" | "age"> {
map: string[]
}
const a: ITest = {
name: '1',
age: '1',
map: ["1"],
}
2. Omit
interface IUser {
name: string
age: string
location: string
}
type ITest3 = Omit<IUser, "location">
interface ITest4 extends ITest3 {
map: string[]
}
const b: ITest4 = {
map: [
"1",
],
name: '1',
age: '1'
}
3. Pick的问题
问题: 上述的IUser的name改变,下面的声明是否会改变?
答案: 会改变。