1、深度比较两个对象是否相等
所有不相等的返回false
function diff (obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
else {
for (let key in obj1) {
if (!obj2.hasOwnProperty(key)) {
return false;
}
//类型相同
if (typeof obj1[key] === typeof obj2[key]) {
//两个对象同为引用类型
if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
const equal = diff(obj1[key], obj2[key]);
if (!equal) {
return false;
}
}
//两个对象同为基础数据类型
if (typeof obj1[key] !== 'object' && typeof obj2[key] !== 'object' && obj1[key] !== obj2[key]) {
return false;
}
}
else {
return false;
}
}
}
return true;
}
hasOwnProperty: 检查对象自身属性;
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
2、实现eventEmitter
export default class EventEmitter {
constructor() {
this.event = {};
this.maxListerners = 10;
}
// 监听
on(type, listener) {
if (this.event[type]) {
if (this.event[type].length >= this.maxListerners) {
console.error('同一个监听器最多被十个对象监听,否则可能造成内存泄漏.\n');
return;
}
this.event[type].push(listener);
} else {
this.event[type] = [listener];
}
}
//发送监听
emit(type, ...rest) {
if (this.event[type]) {
this.event[type].map(fn => fn.apply(this, rest));
}
}
//移除监听器
removeListener(type) {
if (this.event[type]) {
delete this.event[type];
console.log(this.event);
}
}
//移除所有的监听器
removeAllListener() {
this.event = {};
}
}
3、生成随机长度混合的密码
const randomFunc = {
lower: getRandomLower,
upper: getRandomUpper,
number: getRandomNumber,
symbol: getRandomSymbol
}
function generatePassword(lower, upper, number, symbol, length) {
let generatedPassword = ''
//密码的组成是小写+大写+数字+符号
const typesCount = lower + upper + number + symbol
const typesArr = [{lower}, {upper}, {number}, {symbol}].filter(item => Object.values(item)[0])
if(typesCount === 0) {
return ''
}
//每次循环输出一个typesCount长度的字符串,i+typesCount
for(let i = 0; i < length; i += typesCount) {
typesArr.forEach(type => {
const funcName = Object.keys(type)[0]
generatedPassword += randomFunc[funcName]()
})
}
const finalPassword = generatedPassword.slice(0, length)
return finalPassword
}
function getRandomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97)
}
function getRandomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65)
}
function getRandomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48)
}
function getRandomSymbol() {
const symbols = '!@#$%^&*(){}[]=<>/,.'
return symbols[Math.floor(Math.random() * symbols.length)]
}
//调用
var hasLower = true; var hasUpper = true; var hasNumber = true; var hasSymbol = true; var length = 10;
generatePassword(hasLower, hasUpper, hasNumber,hasSymbol,length)
//输出
'tD1*vF8,yN'
4、react为什么需要key
key作用: 判断元素是新创建的还是被移动的元素,从而减少不必要的元素渲染
5、parseInt遇上map
['1','2','3'].map(parseInt) 输出为[1,NaN,NaN]
解析: parseInt 函数只需两个参数parseInt(value, radix),而map的回调函数需要三个参数callback(currentValue,index,array);
parseInt的第二个参数是一个2-36之间的整数值,用于制定转换中采用的基数。
- 如果省略该参数或者值为0,则当作十进制来解析。
- 该参数小于2或者大于36,则parseInt返回NaN
- 转换失败也返回NaN。
上述题目:parseInt(‘1’,0)的结果是当作十进制解析,返回1;parseInt(‘2’,1)的第二个参数非法,返回NaN;parseInt(‘3’,2)会当作二进制来解析,但是‘3’在二进制中是非法的,转换失败,返回NaN。
map方法
var ary = Array(3);
ary[0] = 2;
ary.map(function(elem){
return '1';
});
输出['1',undefined,undefined]
map方法: 给原数组中的每个元素都按顺序调用一次callback函数。callback每次执行后的返回值组合起来形成一个新数组。callback函数只会在有值的索引上被调用;从来没被赋值或者使用delete删除的索引则不会被调用。
6、
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
输出Something
解析: + 运算符优先级大于? 所以上述表达式相当于’value is’+true ? ‘Something’: ‘Nothing’
7、javascript强制转换
题目
var a = [0];
if([0]){
console.log(a == true);
}else{
console.log('wut')
}
输出false
当[0]需要被强制转换成Boolean的时候被认为是true。所以进入第一个if语句;
a == true 的转换规则,由ES规范指出,是: == 相等中,如果有一个操作符是布尔类型,会先把他转成数字,所以
a == true 相当于 [0] == 1;同时规范指出如果其他类型和数字比较,会尝试把这个类型转成数字再进行宽松比较,而对
象会先调用它的toString()方法,此时[0[会变成‘0’,然后将该字符串转成0,0==1结果显然false
[] == [] 输出false
如果比较的两个对象指向的是同一个对象返回true,否则返回false
8、二分查找
//循环不变式 guess 等于l r中间位置
const bsearch = (A, x) => {
let l = 0
let r = A.length - 1
let guess
while (l <= r) {
console.log('find')
guess = Math.floor((l + r) / 2)
if (A[guess] === x) return guess
if (A[guess] > x) r = guess - 1
else l = guess + 1
}
return -1
}
let arr = [1, 2, 3, 4, 5, 6, 7, 8]
console.log(bsearch(arr, 6)) // 5
https://juejin.cn/post/6844903575559077895 (重要!基本涵盖了所有的js手写题和代码实现)
9、react 子组件向父组件传递值
- 父组件给子组件传递一个函数
- 子组件通过props获取该函数并给该函数附上参数
- 父组件通过函数拿到子组件传递的值
https://blog.csdn.net/w544924116/article/details/119565219