1.对象obj = { ‘a.b.c’: 1, ‘a.d’: 2, ‘e’: 3}变为obj={a:{b:{c: 3}, d: 2},e:3} (掘金上看的)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let obj = {
'a.b.c': 1,
'a.d': 2,
'e': 3
}
let newObj = {};
let keysList = Object.keys(obj).map(item => {
return item.split('.');
});
let res = null;
var keys = '';
keysList.forEach(item => {
keys = '';
for (var i = 0; i < item.length; i++) {
keys = keys ? keys + '.' + item[i] : item[i]; // 累加字段
getObjKeys(item[i], i, item.length);
}
})
function getObjKeys(item, index, length) {
if (length === 1 && index === length - 1) {
// 1.如果只有一项的话
newObj[item] = obj[item];
} else {
if (index === 0) {
// 如果是第1项判断有没有
if (!newObj[item]) {
newObj[item] = {}
}
res = newObj[item];
} else if (index !== length - 1) {
// 2.如果有多项时
if (!res[item]) {
res[item] = {}
}
res = res[item]
} else {
// 最后进行判断,如果已经到了最后一项的话就要赋值了
res[item] = obj[keys];
}
}
}
console.log(newObj)
</script>
</html>
2.扁平化数组: const array = [1,[2,[[3,4],5]]];输出array=[1,2,3,4,5] (知乎上看的)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
const array = [1,[2,[[3,4],5]]];
let newArray = [];
array.forEach(item => {
if (item instanceof Array === true) {
getFun(item);
} else {
newArray.push(item);
}
})
function getFun(array) {
array.forEach(item => {
if (item instanceof Array === true) {
getFun(item);
} else {
newArray.push(item);
}
})
}
console.log(newArray);
</script>
</html>
/*数组扁平化: 取出嵌套数组(多维)中的所有元素放到一个新数组(一维)中 如: [1, [3, [2, 4]]] ==> [1, 3, 2, 4] */
/*方法一: 递归 + reduce() + concat() + some() */
function flatten1(array) {
return array.reduce((pre, item) => {
if (Array.isArray(item) && item.some((cItem => Array.isArray(cItem)))) {
return pre.concat(flatten1(item))
} else {
return pre.concat(item)
}
}, [])
}
/*方法二: ... + some() + concat() */
function flatten2(arr) {
// 只要arr是一个多维数组(有元素是数组)
while (arr.some(item => Array.isArray(item))) {
// 对arr进行降维
arr = [].concat(...arr)
}
return arr
}
方法三:arr.flat(): 将多维数组转为一维数组(也称为: 数组扁平化) [1, [2, 3]] ==> [1, 2, 3]
let arr1 = [1, [3, [2, 4]]];
function flatten2(arr) {
// 只要arr是一个多维数组(有元素是数组)
while (arr.some(item => Array.isArray(item))) {
// 对arr进行降维
arr = arr.flat()
}
return arr
}
flatten2(arr1)
3. let arr = [ { id: 4, name: ‘部门4’, pid: 3 }, { id: 5, name: ‘部门5’, pid: 4 }, { id: 1, name: ‘部门1’, pid: 0 }, { id: 2, name: ‘部门2’, pid: 1 }, { id: 3, name: ‘部门3’, pid: 1 }, ]变为树形结构 (知乎上看的)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let arr = [
{ id: 4, name: '部门4', pid: 3 },
{ id: 5, name: '部门5', pid: 4 },
{ id: 1, name: '部门1', pid: 0 },
{ id: 2, name: '部门2', pid: 1 },
{ id: 3, name: '部门3', pid: 1 },
]
arr.forEach(item => {
for (var value of arr) {
if (item.id === value.pid) {
value.type = 1
item.children ? item.children.push(value) : item.children = [value];
}
}
})
let array = arr.find(item => {
return !item.type;
})
console.log([array]);
</script>
</html>
4. 写三个Promise函数,如果有错误就停止执行,没有错误按顺序执行(阿里外包)
function fun1(){
return new Promise(function(resolve, reject){
resolve('fun1返回的数据')
})
}
function fun2(){
return new Promise(function(resolve, reject){
// resolve('fun2返回的数据')
resolve()
// reject('fun2错误')
})
}
function fun3(){
return new Promise(function(resolve, reject){
// reject('fun3错误')
resolve('fun3返回的数据')
})
}
fun1().then(function(data) {
console.log(data)
return fun2()
}).then(function(data) {
console.log(data)
return fun3()
}).then(function(data){
console.log(data)
})
fun2错误则fun3不执行
没有错误都执行
5. 数组去重
方法一:使用fliter/find, 如果有fliter返回数组包含项[查找到的数据],如果没有则返回[], find如果有返回当前查找项,如果没有返回undefined
let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
let arrayNew = []
array.map(item => {
const result = arrayNew.find(items => item === items)
if (!result) {
arrayNew.push(item)
}
})
console.log(arrayNew)
方法二:
arrayNew.includes(item)需要查找值,includes返回true/false
let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
let arrayNew = []
array.map(item => {
const result = arrayNew.includes(item)
console.log(result)
if (!result) {
arrayNew.push(item)
}
})
console.log(arrayNew)
方法三: Set value1, value2, value3 value不会重复, 如果有自动过滤掉
new Set(array)结果为{1, 2, 3, 5, 4, 6, 8, 7, 9},Array.from会添加个[]空数组并把值放进去
let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
Array.from(new Set(array)) // (9) [1, 2, 3, 5, 4, 6, 8, 7, 9]
方法四:使用对象属性名的唯一性来保证不重复
// 数字或字符串数组去重,效率高
function unique(arr) {
var result = {}; // 利用对象属性名的唯一性来保证不重复
for (var i = 0; i < arr.length; i++) {
if (!result[arr[i]]) {
result[arr[i]] = true;
}
}
return Object.keys(result); // 获取对象所有属性名的数组
}
方法五:使用数组的indexOf(item) === -1,如果等于-1则是没有
let arr1 = [1, 1, 2, 3, 5, 2, 6, 5 , 4];
let newArray = [];
for(var i = 0; i< arr1.length; i++) {
if(newArray.indexOf(arr1[i]) === -1) {
newArray.push(arr1[i]);
}
}
console.log(newArray)
方法六:使用Map数据结构去重
let map = new Map();
let array = [1, 2, 3, 2, 3, 5, 1, 4, 6];
let newArray = []; // let newArray = new Array();
for (let i =0; i<array.length; i++) {
if(map.has(array[i])) {
// 如果有该key值
map.set(array[i], true);
} else {
map.set(array[i], false);
newArray.push(array[i]);
}
}
console.log(newArray)
6. 写个函数判断两个对象是否相等,key与值相等 (喜茶外包)
方法一: for(let key in obj) 使用for…in循环对象,delete key删除对象中某一项,再用Object.keys(obj)获取对象的key值,返回[]key的数组
当obj1循环结束时意味着obj2也要比较完,为空对象
let obj1 = {l1:1, l3:3, l4: 4, l2:2}
let obj2 = {l1:1, l2:2, l3:3, l4: 4}
function fun() {
for (let key1 in obj1) {
for(let key2 in obj2) {
if (key1 === key2) {
// 循环判断key是否相等
if (obj1[key1] === obj2[key2]) {
// 判断key的值是否相等,如果相等则删除obj2中这项
delete obj2[key2]
}
}
}
}
if (!Object.keys(obj2).length) {
// 如果obj2对象为空那就说明与obj1相等
return true
}
return false
}
console.log(fun())
当key与值相等时,即使位置换了也是为ture
位置没有变化,如果key或者值不相等为false
----------------------------------------------------------------------优化----------------------------------------------------------
如果对象中出现两个相同的key,值不同,那就用个值来计数
function fun() {
let obj1 = {l1:1, l1:2, l3:3, l4:4}
let obj2 = {l2:2, l1:1, l3:3, l4:4}
let count = Object.keys(obj1).length // obj1 keys数组的长度
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
// 如果两个对象的key值数组不等则直接返回false
return false
}
for (let key1 in obj1) {
for(let key2 in obj2) {
if (key1 === key2) {
// 循环判断key是否相等
if (obj1[key1] === obj2[key2]) {
// 判断key的值是否相等,如果相等则删除obj2中这项
// delete obj2[key2]
count --
}
}
}
}
// if (!Object.keys(obj2).length) {
// // 如果obj2对象为空那就说明与obj1相等
// return true
// }
if (!count) {
// 如果count为0那就说明都循环对应完毕
return true;
}
return false
}
console.log(fun())
方法二: 使用Object.entries获取两个对象的[key, value]数组值
function fun() {
let obj1 = {l1:1, l2:2, l3:3, l4:4}
let obj2 = {l1:1, l2:2, l3:3, l4:5}
const objValues1 = Object.entries(obj1)
const objValues2 = Object.entries(obj2)
if(objValues1.length !== objValues2.length) {
// 长度不相等返回false
return false
}
let count = objValues1.length
objValues1.forEach(item => {
objValues2.forEach(items =>{
if (item[0] === items[0]) {
// 循环,如果key值相等
if(item[1] === items[1]) {
// 如果值也相等
count --
}
}
})
})
if (!count) {
// 如果count为0则相等
return true
}
return false
}
fun()
方法三: Object.is(value1, value2): 判断2个值是否完全一样 NaN===NaN
跟上面的一样,先判断两个obj的key是否相等再判断值是否相等,当obj1循环完毕再看记步数count是否等于0
let obj1 = {l1: 1, l2: 1}
let obj2 = {l1: 1, l2: 2}
console.log(Object.is(obj1.l1, obj1.l1)) // true
7. 有一个id为list的列表,要求:往其中插入100个节点,点击每个列表项时,能弹出是第几个。事件代理(事件委托)
<ul id="list"></ul>
<script>
(()=>{
const container = document.getElementById('list')
// 创建文档片段,此时还没有插入到DOM树中
const fragments = document.createDocumentFragment() // 离线加载,不会触发重排重绘
// 动态创建节点并组合到文档片段中
for(let i = 0; i < 100; i++){
const li = document.createElement("li")
li.innerHTML = `item-${i+1}`
fragments.appendChild(li)
}
// 一次性插入DOM树中
container.appendChild(fragments)
container.addEventListener('click',function(e){
if(e.target.tagName === 'LI'){
alert(e.target.innerHTML)
}
})
})()
</script>
如果是插入50000个节点呢?
<ul id="list"></ul>
<script>
(()=>{
const container = document.getElementById('list')
const TOTAL = 50000
const BATCH_SIZE = 10 // 每批插入节点次数,越大越卡
const BATCH_COUNT = TOTAL / BATCH_SIZE // 需要批处理多少次
let batchDone = 0 // 已经完成的批处理个数
function appendItems(){
const fragments = document.createDocumentFragment()
for(let i = 0; i < BATCH_SIZE; i++){
const item = document.createElement("li")
item.innerHTML = `item-${(batchDone * BATCH_SIZE ) + i + 1}`
fragments.appendChild(item)
}
container.appendChild(fragments)
batchDone += 1
batchAppend()
}
function batchAppend(){
if(batchDone < BATCH_COUNT){
window.requestAnimationFrame(appendItems)
}
}
batchAppend()
container.addEventListener('click',function(e){
if(e.target.tagName === 'LI'){
alert(e.target.innerHTML)
}
})
})()
</script>
8. 假设有一串字符串,拿到最多连续的次数,比如:acbac, ac连续出现次数2次;abcacabacaaacd中ac连续出现3次,ksjdxsksdxskdx中dx连续出现3次 (忘记名字的公司)
<script>
let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
function soluction(str) {
let array = []; // 记录有多少种组合情况,
let count = 0; // 记录当前字符串出现的次数;
let maxCount = 0; // 记录子字符串出现最多的次数;
let childstr = ''; // 记录当前出现最多次数的是哪个字符串
for (let i = 0; i < str.length; i++) {
// 第一层循环先从第一个开始找
for (let y = str.length; y > i + 1; y--) {
array.push(str.slice(i, y))
}
}
// 设置一个递归函数
function digui(str, item) {
if (str.includes(item)) {
// 如果还有则再递归
count++;
digui(str.slice(str.indexOf(item) + item.length), item);
} else {
// 如果没有的话就return
return count;
}
}
// 循环数组,找出子字符在字符串中出现的次数
array.forEach(item => {
count = 0; // 每次循环重新记录
if (str.includes(item)) {
count++;
if (str.slice(str.indexOf(item) + item.length)) {
digui(str.slice(str.indexOf(item) + item.length), item);
}
}
if (count > maxCount) {
childstr = item;
maxCount = count
}
})
console.log(childstr, maxCount)
return maxCount; // 输出最多次数
}
soluction(str);
</script>
如果只需要出现次数最多的,要次数的话上面的可以实现。
优化:如果出现两个字符串都是3次的,把这些字符串找出来 定义个对象,把每个字符串出现的次数用键值对保存,最后再循环对象,找到最大值的key
let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
function soluction(str) {
let array = []; // 记录有多少种组合情况,
let count = 0; // 记录当前字符串出现的次数;
let maxCount = 0; // 记录子字符串出现最多的次数;
let childstr = ''; // 记录当前出现最多次数的是哪个字符串
let obj = {}; // 定义一个对象
for (let i = 0; i < str.length; i++) {
// 第一层循环先从第一个开始找
for (let y = str.length; y > i + 1; y--) {
array.push(str.slice(i, y))
}
}
// 设置一个递归函数
function digui(str, item) {
if (str.includes(item)) {
// 如果还有则再递归
count++;
digui(str.slice(str.indexOf(item) + item.length), item);
} else {
// 如果没有的话就return
return count;
}
}
// 循环数组,找出子字符在字符串中出现的次数
array.forEach(item => {
count = 0; // 每次循环重新记录
if (str.includes(item)) {
count++;
if (str.slice(str.indexOf(item) + item.length)) {
digui(str.slice(str.indexOf(item) + item.length), item);
}
}
obj[item] = count; // 把当前的保存起来
if (count > maxCount) {
childstr = item;
maxCount = count
}
})
console.log(childstr, maxCount)
// 循环对象 for in
let objArray = []; // 定义个数组用来装出现次数最多的key值
for (let key in obj) {
if (obj[key] === maxCount) {
objArray.push(key); // 把key值装进去, 对象的key值唯一性,几乎不会出现重复的key
}
}
// 循环完毕,objArray 装的就是出现次数最多的key值
console.log(objArray);
return maxCount; // 输出最多次数
}
soluction(str);
</script>
9.判断一个字符串中是否有某个key字符串,没有返回null,有则返回数组 (同上)
<script>
let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
let key = 'dx';
let array = [];
function soluction(str) {
if (str.indexOf(key) === -1) {
// 不存在则返回null
return null;
}
// 存在则返回数组
function fun(str) {
if (str.includes(key)) {
array.push(key);
if (!str.slice(str.indexOf(key) + key.length)) {
return array;
}
return fun(str.slice(str.indexOf(key) + key.length));
} else {
return array;
}
}
const resultArray = fun(str);
console.log(resultArray);
}
soluction(str);
</script>
10.冒泡排序 (丰巢)
// ---------------从小到大排----------------
<script>
const array = [1, 5, 9, 11, 2, 6, 3, 7, 8, 4];
// const array = [5, 6, 9, 7, 4, 3, 8, 2, 1];
let maxValue = 0; // 设置一个最大的接收属性
// 冒泡排序:从小到大排,思路:数组循环,当前项与后一项比较,如果当前项大于后一项,则把当前项赋值给大值,然后再把后项给当前项
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length; j++) {
if (array[j] > array[j + 1]) {
// 如果当前项大于后一项,则要把当前项记录,并跟第二项换位置
maxValue = array[j];
array[j] = array[j + 1];
array[j + 1] = maxValue;
}
}
}
console.log(array);
</script>
// ---------------从大到小排-----------------思路:变的只是存储的是小值,如果当前项小于后一项,就把当前项赋值给小值属性标志,再把当前项与后一项对换位置
<script>
const array = [1, 5, 9, 11, 2, 6, 3, 7, 8, 4];
// const array = [5, 6, 9, 7, 4, 3, 8, 2, 1];
let minValue = ''; // 设置一个最小的接收属性
// 冒泡排序:从小到大排,思路:数组循环,当前项与后一项比较,如果当前项大于后一项,则把当前项赋值给大值,然后再把后项给当前项
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length; j++) {
if (array[j] < array[j + 1]) {
// 如果当前项大于后一项,则要把当前项记录,并跟第二项换位置
minValue = array[j];
array[j] = array[j + 1];
array[j + 1] = minValue;
}
}
}
console.log(array);
</script>
11.?foo=bar&abc=123&abc=xyz输出{foo:‘bar’, abc: [‘123’, ‘xyz’]}, {foo:‘bar’, abc: [‘123’, ‘xyz’]}输出?foo=bar&abc=123&abc=xyz (阿里外包)
1.?foo=bar&abc=123&abc=xyz输出{foo:‘bar’, abc: [‘123’, ‘xyz’]}
function UrlTools(url) {
let array = url.split('?')[1].split('&');
let obj = {};
array.forEach(item => {
let itemArray = item.split('=');
if (obj[itemArray[0]]) {
// 如果已经存在则用数组装起来
let arrayComm = [];
arrayComm = [obj[itemArray[0]]];
obj[itemArray[0]] = [...arrayComm, itemArray[1]]
} else {
obj[itemArray[0]] = itemArray[1];
}
});
return obj;
}
UrlTools('?foo=bar&abc=123&abc=xyz');
2.{foo:‘bar’, abc: [‘123’, ‘xyz’]}输出?foo=bar&abc=123&abc=xyz
function UrlTools(obj) {
let params = '?';
for (let key in obj) {
// 遍历对象
if (Object.prototype.toString.call(obj[key]) === '[object Array]') {
// 如果是数组就要循环数组
obj[key].forEach(item => {
if (params === '?') {
// 如果是第一项不用加&
params = `${params}${key}=${item}`
} else {
params = `${params}&${key}=${item}`
}
});
} else {
if (params === '?') {
// 如果是第一项就不要加&
params = `${params}${key}=${obj[key]}`
} else {
// 如果不是第一项要加&
params = `${params}&${key}=${obj[key]}`
}
}
}
console.log(params)
}
UrlTools({
foo: 'bar',
abc: ['xyz', '123'],
});
-----------------------------------优化---------------------------
原本的题目是:
class UrlTools {}
console.log(‘parse’, UrlTools.parse(‘?foo=bar&abc=123&abc=xyz’));
console.log(‘styify’, UrlTools.styify({
foo: ‘bar’,
abc: [‘xyz’, ‘123’],
}));
时间紧迫,没有想起class,所以用js做了,交卷以后才想起class的做法
//static parse需要在方法前加static这样可以不用实例class,直接用UrlTools.xxx();如果没有加static的方法需要实例后才能调用:
let urlTools = new UrlTools(); urlTools.parse(), urlTools .styify();
class UrlTools {
static parse(url) {
let array = url.split('?')[1].split('&');
let obj = {};
array.forEach(item => {
let itemArray = item.split('=');
if (obj[itemArray[0]]) {
// 如果已经存在则用数组装起来
let arrayComm = [];
arrayComm = [obj[itemArray[0]]];
obj[itemArray[0]] = [...arrayComm, itemArray[1]]
} else {
obj[itemArray[0]] = itemArray[1];
}
});
return obj;
}
static styify(obj) {
let params = '?';
for (let key in obj) {
// 遍历对象
if (Object.prototype.toString.call(obj[key]) === '[object Array]') {
// 如果是数组就要循环数组
obj[key].forEach(item => {
if (params === '?') {
// 如果是第一项不用加&
params = `${params}${key}=${item}`
} else {
params = `${params}&${key}=${item}`
}
});
} else {
if (params === '?') {
// 如果是第一项就不要加&
params = `${params}${key}=${obj[key]}`
} else {
// 如果不是第一项要加&
params = `${params}&${key}=${obj[key]}`
}
}
}
return params;
}
}
console.log('parse', UrlTools.parse('?foo=bar&abc=123&abc=xyz'));
console.log('styify', UrlTools.styify({
foo: 'bar',
abc: ['xyz', '123'],
}));
12.react自定义hooks写一个计数器 (同上,阿里外包)
// 简单的计数器,题目是这样的
function Counter() {
const [count, setCount] = useState(0);
useInterval(() => {
setCount(count + 1);
}, 1000);
return <h1>{count}</h1>;
}
function useInterval(callback, delay) {
// 你的代码
}
function Counter() {
const [count, setCount] = useState(0);
useInterval(() => {
setCount(count + 1);
}, 1000);
return <h1>{count}</h1>;
}
function useInterval(callback, delay) {
// 你的代码
// let timer = null;
// if (timer) {
// clearTimeout(timer)
// }
// timer = setTimeout(callback, delay);
// useEffect(() => {
// return() => { // 清除副作用,在这里面清除定时器
// clearTimeout(timer)
// }
// })
useEffect(() => {
let timer = null;
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(callback, delay);
return() => { // 清除副作用,在这里面清除定时器
clearTimeout(timer)
}
});
}
function App() {
return (
<div className="App">
<Counter />
</div>
);
}
export default App;
13.给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。(腾讯外包)
// 给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。
// 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
// (要求ta只能操作数组,不能转成数字直接加一)
// 示例 1:
// 输入: [1, 2, 3] 输出: [1, 2, 4]
// 示例 2:
// 输入: [4, 3, 2, 1] 输出: [4, 3, 2, 2]
// 示例 3:
// 输入:[9] 输出:[1, 0]
// 示例 4:
// 输入:[9, 9, 9] 输出:[1, 0, 0, 0]
// 1. [9, 8, 9] 输出 [9, 9, 0]
// *这个题目就是数组的最后项加1,如果为9, 9 +1 =10,那么当前位为0,前一位+1;
~~悲惨的是我当时脑子一片空白没写出来,晚上沉下心来突然想到怎么做了~
<script>
// 给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。
// 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
// (要求ta只能操作数组,不能转成数字直接加一)
// 示例 1:
// 输入: [1, 2, 3] 输出: [1, 2, 4]
// 示例 2:
// 输入: [4, 3, 2, 1] 输出: [4, 3, 2, 2]
// 示例 3:
// 输入:[9] 输出:[1, 0]
// 示例 4:
// 输入:[9, 9, 9] 输出:[1, 0, 0, 0]
// 1. [9, 8, 9] 输出 [9, 9, 0]
// ******这个题目就是数组的最后项加1,如果为9, 9 +1 =10,那么当前位为0,前一位+1;*****
function getDatas(array) {
let newArray = [];
// 思路从后往前循环,逢9 + 1 =10打标记,如果循环完毕标记为true则在数组前加1
let isAddNum = false; // 用一个值来记录是否等于10需要往前+1;
for (let i = array.length - 1; i >= 0; i--) {
if (isAddNum) { // 判断是否要+1
// 加完1后判断是否为10
let newValue = array[i] + 1;
if (newValue == 10) {
isAddNum = true;
newArray.unshift(0);
} else {
isAddNum = false;
newArray.unshift(newValue);
}
} else {
if (i === array.length - 1) { // 如果是最后一项需要+1
// 先判断最后项加1之后是否是10,是打标记,需要往前进1,并把当前项置为0;
if (array[i] + 1 == 10) {
isAddNum = true
newArray.unshift(0);
} else {
isAddNum = false;
newArray.unshift(array[i] + 1);
}
} else {
isAddNum = false;
newArray.unshift(array[i]); // 如果是不需要加+1的直接返回该项
}
}
}
// 循环结束后判断isAddNum标记是否为true;为true要在数组最前面+1
if (isAddNum) {
newArray.unshift(1);
}
return newArray;
}
console.log(getDatas([9, 9, 9, 9]));
</script>
-----------------------优化-----------------把相同的代码整合一下
<script>
function getDatas(array) {
let newArray = [];
// 思路从后往前循环,逢9 + 1 =10打标记,如果循环完毕标记为true则在数组前加1
let isAddNum = false; // 用一个值来记录是否等于10需要往前+1;
for (let i = array.length - 1; i >= 0; i--) {
if (isAddNum || i === array.length - 1) { // 判断是否要+1,最后一项或者最后一项逢9打标记的加1
// 加完1后判断是否为10
const newValue = array[i] + 1;
if (newValue == 10) {
isAddNum = true;
newArray.unshift(0);
} else {
isAddNum = false;
newArray.unshift(newValue);
}
} else {
newArray.unshift(array[i]); // 如果是不需要加+1的直接返回该项
}
}
// 循环结束后判断isAddNum标记是否为true;为true要在数组最前面+1
if (isAddNum) {
newArray.unshift(1);
}
return newArray;
}
console.log(getDatas([5, 3, 9, 1]));
</script>
14.反转有符号整数
写出函数 function reverseNum( num ) 能够反转数字
输入: x = 123
输出: 321
输入: x = -123
输出: -321
输入: x = 120
输出: 21
function reverseNum( num ) {
num = num.toString();
let result = '';
for (let i = num.length; i > 0; i--) {
if (isNaN(num.substr(i - 1, 1))) {
result = num.substr(i - 1, 1) + result
} else {
result = result + num.substr(i - 1, 1);
}
}
return +result;
}
console.log(reverseNum(120));
15.URL解析器(与11相反)
写一个parse的函数将url解析器,将url转换成指定的结构
如:将 http://www.a.com?key1=1&key2=2&key1=3&test=4#haha
转换成:
{
protocol: ‘http’,
hostname: ‘www.a.com’,
pathname: ‘/test’,
search: ‘?key1=1&key2=2&key1=3&test=4’,
searchParams: {
key1: [‘1’, ‘2’]
key2: ‘2’,
test: ‘4’
},
hash: ‘#haha’,
}
const case1 = 'http://www.a.com/test?key1=1&key2=2&key1=3&test=4&key1=5#haha'
function parse(url) {
const hash = case1.split('#');
const params = hash[0].split('?');
let paramsList = params[1].split('&');
let searchParams = {}
paramsList.forEach(item => {
const subItems = item.split('=');
const [key, value] = subItems;
if (searchParams[key]) {
// 如果已经存在了,先判断他的值
if (Array.isArray(searchParams[key])) {
// 如果是数组,直接追加
searchParams[key].push(value);
} else {
searchParams[key] = [searchParams[key], value];
}
} else {
searchParams[key] = value;
}
});
const search = params[1];
const httpUrl = params[0].split('//');
const hostUrl = httpUrl[1].split('/');
return {
protocol: httpUrl[0],
hostname: hostUrl[0],
pathname: hostUrl[1],
search,
searchParams,
hash: `#${hash[1]}`
}
}
console.log(parse(case1));
16.[1,1,‘true’,‘true’,true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,‘NaN’, 0, 0, ‘a’, ‘a’,{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}]去重
const arr = [1,1,‘true’,‘true’,true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,‘NaN’, 0, 0, ‘a’, ‘a’,{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}];
去重之后的结果为:
用Object.is(item, items)比较两个值是否相等
<script>
const arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}];
let newArray = [];
function digui(first, second) {
const firstList = Object.keys(first);
const secondList = Object.keys(second);
let isFlag = false;
if (firstList.length !== secondList.length) return false;
if (firstList.length === 0 && secondList.length === 0) return true;
for (let key1 in first) {
for (let key2 in second) {
if (key1 === key2) {
if (Object.prototype.toString.call(first[key1]) === '[object Object]' && Object.prototype.toString.call(second[key2]) === '[object Object]') {
// 如果是对象
return digui(first[key1], second[key2]);
} else {
if (first[key1] === second[key2]) {
isFlag = true
} else {
isFlag= false
}
}
}
}
}
return isFlag;
}
function unique(arr){
// const resultList = Array.from(new Set(arr));
arr.map(item => {
let result = null;
newArray.map(items => {
if (Object.is(item, items)) {
result = true;
return;
}
if (Object.prototype.toString.call(item) === '[object Object]') {
// 如果是对象
if (Object.prototype.toString.call(item) === Object.prototype.toString.call(items)) {
result = digui(item, items);
}
}
})
if (!result) {
newArray.push(item);
}
})
return newArray;
}
console.log(unique(arr));
</script>
17.实现一个获取对象任意属性值的方法,
比如:
const getAttribute = (object, path, defaultValue) => {
}
const obj = {a: {b: {c: 100}}, d: [{f: ‘abc’}]};
getAttribute(obj, ‘a.b.c’, 0) === 100
getAttribute(obj, ‘a.b.e’, ‘default’) === ‘default’
getAttribute(obj, ‘d.0.f’) === ‘abc’
const getAttribute = (object, path, defaultValue) => {
const keysList = path.split('.');
let result = object;
let value = defaultValue;
keysList.map(key => {
if (!isNaN(key)) {
// 如果是数字
result = result[Number(key)];
return;
}
if (result[key]?.constructor === Object) {
result = result[key]
} else if (result[key]?.constructor === Array) {
// 如果值是数组
result = result[key];
} else {
if (result[key]) {
value = result[key];
}
}
})
return value;
}
const obj = { a: { b: { c: 100 } }, d: [{ f: 'abc' }] };
console.log(getAttribute(obj, 'a.b.c', 0));
console.log(getAttribute(obj, 'a.b.e', 'default'));
console.log(getAttribute(obj, 'd.0.f'));
这个题目遇到两次了,第一次是要求如果有值返回值,没有值返回undefined。
const getAttribute = (object, path) => {
const keysList = path.split('.');
let result = object;
let value = undefined;
keysList.map(key => {
if (!isNaN(key)) {
// 如果是数字
result = result[Number(key)];
return;
}
if (result[key]?.constructor === Object) {
result = result[key]
} else if (result[key]?.constructor === Array) {
// 如果值是数组
result = result[key];
} else {
if (result[key]) {
value = result[key];
}
}
})
return value;
}
const obj = {
a: {
aa: {
aaa: 'rang'
}
},
b: [{}, {}, { bb: 'blue' }]
};
console.log(getAttribute(obj, 'a.aa.aaa') === 'rang'); // 返回true
console.log(getAttribute(obj, 'b.2.bb') === 'blue'); // 返回true
console.log(typeof getAttribute(obj, 'c.c.cc') === 'undefined'); // 返回true
console.log(getAttribute(obj, 'a.b.c')); // 返回undefined
18.写一个json格式化代码
参考文章:
https://blog.51cto.com/ohxiaohu/6103652
https://blog.youkuaiyun.com/m0_68634366/article/details/129549935
https://blog.51cto.com/u_16175515/6898954
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<textarea rows="10" cols="100" id="inputBox"></textarea>
<p id="showText" contenteditable="true">
<pre id="myPre" style="width: 100%;height: 500px;overflow: auto;background-color: white;"></pre>
</p>
<!-- <textarea id="showText" rows="15"></textarea> -->
<script>
var textarea = document.querySelector('#inputBox')
textarea.addEventListener('input', function () {
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + 'px';
// var a = JSON.stringify({ "code": "0", "msg": "查询成功", "resultData": [{ "hhrAddress": "南京市建邺区江东中路228号", "hhrBirthDate": 631123200000 }, { "hhrAddress": "北京京市建邺区江东中路666号", "hhrBirthDate": 1545315245 }], "systemId": "" });
let newJSON = JSON.stringify(JSON.parse(textarea.value), null, '\t');
myPre = document.getElementById('myPre');
myPre.innerText = newJSON
})
</script>
</body>
</html>
19. 编写一个函数来查找字符串数组中的最长公共前缀。(字节外包)
只需要从第一个值拆分与后面两个值比较,如果能找到则是公共的,找不到则不是
// 如果不存在公共前缀,返回空字符串 “”
// 示例 1:
// 输入:strs = [“flower”,“flow”,“flight”]
// 输出:“fl”
// 示例 2:
// 输入:strs = [“dog”,“racecar”,“car”]
// 输出:“”
// 解释:输入不存在公共前缀。
function soluction(arr) {
let commonStr = ''; // 把截取的值放入里面
let outStr = '输入不存在公共前缀'; // 输出内容,默认值为不存在
for (let i = 0; i < arr.length; i ++) {
for (let y = 0; y < arr[i].length - 1; y++) {
// console.log(arr[i].slice(0, y + 2)); // 一开始截取两个字符
commonStr = arr[i].slice(0, y + 2);
// 与数组的每一项进行查找
for (let z = 0; z < arr.length; z++) {
// console.log(commonStr, arr[z], arr[z].includes(commonStr))
if (arr[z].includes(commonStr) && i !== z) {
// i !== z不与本身这项比较
outStr = commonStr;
break;
}
}
}
}
return outStr;
}
console.log(soluction(["dog","race","car"]))
20.数字格式化 1234567.0789 -> 1,234,567.0789 的格式化
function fn(num) {
let newNumArray = num.toString().split('.');
const newNum = newNumArray[0];
let str = '';
function digui(num) {
if (num.length < 3) {
str = `${num},${str}`;
return str;
}; // 如果已有长度不足3位,就直接拼接并返回;
// 如果超过三位则进入递归截取后三位,把前面剩下的继续进入递归截取
if (!str) {
// 如果str为空没有值时,则直接赋值最后三个字符
str = num.substring(num.length - 3);
} else {
str = `${num.substring(num.length - 3)},${str}`; // 获取最后三位数,拼接在字符串
}
// num.substring(0, num.length - 3); // 获取除了最后三位数的其他值
digui(num.substring(0, num.length - 3))
}
digui(newNum)
return `${str}.${newNumArray[1]}`;
}
console.log(fn(1234567.0789));
------------------------------------------------------------// 优化,如果尾数也需要格式化。变成1,234,567.0,789-------------------------------------------------
function fn(num) {
let newNumArray = num.toString().split('.');
const newNumStart = newNumArray[0];
const newNumEnd = newNumArray[1];
let obj = {
strStart: '',
strEnd: ''
}
function digui(num, resultStr) {
if (num.length < 3) {
obj[resultStr] = `${num},${obj[resultStr]}`;
return obj[resultStr];
}; // 如果已有长度不足3位,就直接拼接并返回;
// 如果超过三位则进入递归截取后三位,把前面剩下的继续进入递归截取
if (!obj[resultStr]) {
// 如果值为空时,结果就为后三位
obj[resultStr] = `${num.substring(num.length - 3)}`;
} else {
// 如果已经有值的情况下拼接
obj[resultStr] = `${num.substring(num.length - 3)},${obj[resultStr]}`; // 获取最后三位数,拼接在字符串
}
// num.substring(0, num.length - 3); // 获取除了最后三位数的其他值
digui(num.substring(0, num.length - 3), resultStr)
}
for (let i = 0; i < newNumArray.length; i++) { // 把前面和后面的值循环递归获取
if (i === 0) {
digui(newNumStart, 'strStart')
} else {
digui(newNumEnd, 'strEnd')
}
}
// digui(newNumStart, 'strStart') // 这两句调用方法与上面for循环同等
// digui(newNumEnd, 'strEnd')
return `${obj.strStart}.${obj.strEnd}`;
}
console.log(fn(1234567.0789));