最近公司拆分
,以及裁员
,不小心部门
连带我一起都扬
了,所以无奈开始找工作
,现在开始记录面试过的题目
,讲究
的就是一个细节
。
javascript乱炖
1. == 号的转换
多的就不说了,查看相等(==) - JavaScript | MDN (mozilla.org)
要注意面试的最多的就是undefined == null
,注意两点:
- 只有
undefined == null
的比较是true
- 有一端是
undefined
或者null
,那另一段除了undefined
或者null
之外,都是false
2. 比较version之间的大小
说明:version1 > version2
,就返回1
,version1 < version2
就返回-1
, 等于就返回0
;
例如:
1.01.1 > 1.01
返回1
1.01 == 1.01
返回0
1.01 < 1.02
返回-1
function compareVersion(version1:string ,version2:string) {
let flag = 0;
const processVersion1 = version1.split('.');
const processVersion2 = version2.split('.');
const maxVersion = processVersion1.length > processVersion2.length ? processVersion1 : processVersion2;
for (let i = 0; i < maxVersion.length; i++) {
const version1 = processVersion1[i] === undefined ? 0 : Number.parseInt(processVersion1[i]);
const version2 = processVersion2[i] === undefined ? 0 : Number.parseInt(processVersion2[i]);
if(version1 > version2) {
flag = 1;
break;
} else if(version1 < version2){
flag = -1;
break;
}
}
return flag;
}
3. 手写Promise.all
这题比较简单,只要记住失败时
,Promise.all
直接变成rejected
状态,并返回原因就行了。
Promise.myAll = promiseArray => {
const result = [];
let resolveFn;
let rejectFn;
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
promiseArray.forEach((promise, index) => {
promise.then(
value => {
result[index] = value;
if (
result.filter(_ => _ !== undefined).length === promiseArray.length
) {
resolveFn(result);
}
},
reason => {
rejectFn(reason);
},
);
});
return promise;
};
const a = Promise.myAll([Promise.reject(1), Promise.resolve(2)]);
const b = Promise.myAll([Promise.resolve(1), Promise.resolve(2)]);
setTimeout(() => {
console.log(a);
});
setTimeout(() => {
console.log(b);
});
4. 手写Promise.allSettled
和Promise.all
一样,只要记住allSettled
返回value
结构是怎么样的就行了
Promise.myAllSettled = promiseArray => {
const result = [];
let resolveFn;
const promise = new Promise(resolve => {
resolveFn = resolve;
});
promiseArray.forEach((promise, index) => {
promise.then(
value => {
result[index] = { status: 'resolved', value };
if (
result.filter(_ => _ !== undefined).length === promiseArray.length
) {
resolveFn(result);
}
},
reason => {
result[index] = { status: 'reject', reason };
if (
result.filter(_ => _ !== undefined).length === promiseArray.length
) {
resolveFn(result);
}
},
);
});
return promise;
};
const a = Promise.myAllSettled([Promise.reject(1), Promise.resolve(2)]);
const b = Promise.myAllSettled([Promise.resolve(1), Promise.resolve(2)]);
setTimeout(() => {
console.log(a);
});
setTimeout(() => {
console.log(b);
});
5. 什么是闭包,你都有哪些应用?
闭包
就是函数
携带其它函数环境内变量
的一种形式
应用:写一个简单的useLock
函数,用于等待函数执行完成,期间其它触发都会被取消
,常用于滚动到底部时的数据加载
。
const useLock = (fn: (...args: any[]) => any) => {
let isLock = false;
return async (...args: any[]) => {
if (isLock) return;
isLock = true;
await fn(...args);
isLock = false;
};
};
const lock = useLock(async () => {
await new Promise(resolve => {
setTimeout(() => {
resolve(2);
}, 1000);
});
console.log('end');
});
lock();
lock();
lock();
lock();
lock();
lock();
之前遇到个略微刻薄的面试官,原题是“什么是闭包,你都在哪里用到过闭包”,我以为只是让我解释一下闭包,并说明闭包在哪些情况下存在,现在想想他说的应该是有哪些应用,由于我说的都是存在的场景,于是他非常没耐心的结束了面试🥺。实际上这才第二个问题。。。
6. 有一个盒子,宽高100px,里面的item,宽高20px,请实现如下布局
7.请用递归计算1到100的总和
function getTotal( value:number ) {
if(value === 1) return 1;
const result = value + getTotal(value - 1);
return result
}
getTotal(100)
8.微信小程序写个dialog
直接看代码 dialog
写一个changeName()达到一下效果
这题竟然没看最后的一行的结果,哭了。
const departmentList1 = [{name:'Bob'}, {name:'Develop'}, {name:'Alice'}]
const departmentList2 = changeName('Bob','Dialog',departmentList1);
console.log(departmentList2[0].name); // Dialog
console.log(departmentList2[1].name); // Develop
console.log(departmentList2[2].name); // Alice
console.log(departmentList1[0].name); // Bob
const changeName = (name,value,arr)=>{
const newArr = [...arr];
const targetIndex = newArr.findIndex(_=>_.name === name)
newArr[targetIndex] = {...newArr[targetIndex] ,name: value};
return newArr;
}
数组打平
- 手写
const arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
10,
];
const flatArray = arr => {
function getArray(arr = [], see = []) {
return arr.reduce((pre, current) => {
if (Array.isArray(current)) {
getArray(current, see);
} else {
pre.push(current);
}
return pre;
}, see);
}
return [...getArray(arr).values()];
};
console.log(flatArray(arr));
- flat
const arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
10,
];
console.log(arr.flat(Number.POSITIVE_INFINITY));
算最大公共长度字符串
例子: 给出一个数组['flight','flior', 'flmor']
,计算最大公共字符串为fl
;
function getCommon(arr){
const firstString = arr[0];
const otherStringArray = arr.slice(1);
let common = '';
for(let i = 0; i < firstString.length; i++) {
let flag = true;
for(let b of otherStringArray) {
if(b[i] === firstString[i]) {
break;
} else {
flag = false;
break;
}
}
if(flag) {
common += firstString[i]
}
}
return common;
}
阿里外包算法一
/**
* 简单实现一个queryString,具有parse和stringify的能力,
* parse,用于把一个URL查询字符串解析成一个键值对的集合。
* 输入:查询字符串 'foo=bar&abc=xyz&abc=123'
* 输出:一个键值对的对象
* {
* foo: 'bar',
* abc: ['xyz', '123'],
* }
*/
function parse(input = 'foo=bar&abc=xyz&abc=123') {
const queryStringArr = input.split('&').map(_ => _.split('='));
const result = {};
queryStringArr.forEach(_ => {
const prop = _[0];
const value = _[1];
if (prop in result) {
if (Array.isArray(value)) {
result[prop].push(value);
} else {
result[prop] = [result[prop]].concat(value);
}
} else {
result[prop] = value;
}
});
return result;
}
webpack
plugin和loader有什么区别
chatgpt的回答
Webpack 中的插件(Plugin)和加载器(Loader)是两个不同的概念,它们分别用于不同的任务,主要区别如下:
-
功能和作用:
- Loader:加载器用于转换非 JavaScript 文件(例如,CSS、图片、字体等)成模块,以便可以在 JavaScript 中引入。它们主要处理模块的加载和转换。
- Plugin:插件用于执行一些特定的任务,如代码压缩、文件拷贝、环境变量注入、生成 HTML 文件等。插件可以扩展 Webpack 的功能,但它们通常不会处理模块的转换。
-
配置位置:
- Loader:Loader 配置通常位于
module.rules
中,用于指定文件类型和相应的加载器。 - Plugin:Plugin 配置位于
plugins
中,用于指定需要执行的插件。
- Loader:Loader 配置通常位于
-
使用场景:
- Loader:主要用于处理模块的加载和转换,例如将 Sass 文件转换为 CSS,将图片文件转换为 base64 字符串,或将 TypeScript 转换为 JavaScript。
- Plugin:主要用于执行各种构建任务,如生成 HTML 文件、拷贝静态资源、代码分离、压缩、代码分析、环境变量注入等。
-
执行时机:
- Loader:在模块加载过程中执行,用于将非 JavaScript 模块转换为可导入的 JavaScript 模块。
- Plugin:在 Webpack 构建过程的不同阶段执行,例如在编译、输出文件、压缩、热模块替换等各个阶段。
总之,Loader 主要用于处理模块级别的任务,将非 JavaScript 文件转换为 JavaScript 模块,而插件用于执行更高级别的构建任务,扩展和增强 Webpack 的功能。它们在 Webpack 配置中各自发挥着不同的作用。
总结一句话
loader
主要用于解析处理资源,而plugin
主要是用来加强webpack
的功能。
typescript
type和interface有什么区别
实际上如果只用于标明类型
的话,type
基本可以实现interface
的所有功能
继承(泛化)
interface
interface a { name: string; }
interface b extends a { sex: string; }
type
type a = { name: string; }
type b = a & { sex: string; }
标明函数类型以及函数重载
interface
interface a {
(): void; // 普通调用
(a: string): void; // 重载
new(): Date; // 构造函数
}
type
type a = {
(): void; //普通调用
(a: string): void; //重载
new(): Date; // 构造函数
}
// 或者这样写构造函数
type a = new () => Date;
但是interface
强大的地方就在于,它可以扩展全局对象
,当然这也与interface
的合并特性
有关。也是和type
的主要区别
举个例子
给全局Date
对象加个format
interface Date {
format(template: string): string
}
当然如果你想给Date
构造函数添加一个format
interface DateConstructor {
format(template: string): string
}
当然interface
作为接口的话,那还有一个特性就是implements
之后,必须被实现
。这也是和type
的一个区别。
持续更新中。。。