目录
1. flex里shrink,grow和basis具体应用
2 promise里的catch
3 作用域和作用域链
4 递归展开嵌套数组
1. flex里shrink,grow和basis具体应用
<style>
.container {
display:flex;
width:600px;
}.div1 {
flex:1 2 500px;
}.div2 {
flex:2 1 400px;
}
</style><div class="container"><div class="div1"></div><div class="div2"></div>
</div>
500px+400px超出 600宽度300px
shrink发挥作用,按照2:1缩小比例
div1缩小 200px,div2缩小100px,最终 都是300px
例子 1:增加容器宽度
.container {display: flex;width: 1000px;
}
.div1 {flex: 1 2 500px;
}
.div2 {flex: 1 1 400px;
}
剩余空间为100px,两者都拓宽50px,宽度分别为550px和450px
例子3:没有 flex-grow
或 flex-shrink
.container {display: flex;width: 1000px;
}
.div1 {flex: 0 0 500px;
}
.div2 {flex: 0 0 400px;
}
这里 flex-grow
和 flex-shrink
都是 0
,这意味着不管容器宽度如何,子元素宽度都固定为 500px
和 400px
。
例子4:div1 div2各自有宽度
.container {display: flex;width: 600px;
}
.div1 {width:400px;flex: 1 2 500px;}
.div2 {width:400px;flex: 2 1 400px;}
以400px+400px,发现超出200px
.div1
的缩小比例为 2/3
,所以它缩小的部分为 200px * (2/3) = 133.33px
。
.div2
的缩小比例为 1/3
,所以它缩小的部分为 200px * (1/3) = 66.67px
。
.div1
的最终宽度:400px - 133.33px = 266.67px
。
.div2
的最终宽度:400px - 66.67px = 333.33px
2 promise里的catch
2.1
多级嵌套的 Promise 链
function fetchData1() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ? resolve('Data 1') : reject('Error 1');}, 1000);});}function fetchData2() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ? resolve('Data 2') : reject('Error 2');}, 1000);});}function fetchData3() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ? resolve('Data 3') : reject('Error 3');}, 1000);});}fetchData1().then((data1) => {console.log(data1);return fetchData2();}).then((data2) => {console.log(data2);return fetchData3();}).then((data3) => {console.log(data3);}).catch((error) => {// console.error('Caught an error:', error);throw Error('apple')}).catch((err)=>{'pine',err})
在promise链中 如果promise出现错误被reject 错误会沿着链向下传播 直到遇到第一个catch为止,链条后续的then处理被跳过 直接进入catch
所以可能的输出是:
Data 1
Data 2
pine Error: apple
哪里出现 pine Error: apple 后续的就会终止
2.2多次重试机制的 Promise
function fetchDataWithRetry(retries = 3) {return new Promise((resolve, reject) => {function attempt() {setTimeout(() => {Math.random() > 0.5 ? resolve('Success') : retries-- > 0 ? attempt() : reject('Failed after retries');}, 1000);}attempt();});}fetchDataWithRetry().then((result) => {console.log(result);}).catch((error) => {console.error('Error:', error);});
2.3 多个并发的 Promise 任务与错误处理
function fetchData(id) {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ? resolve(`Data ${id}`) : reject(`Error from ${id}`);}, 1000);});}Promise.allSettled([fetchData(1), fetchData(2), fetchData(3)]).then((results) => {results.forEach((result) => {if (result.status === 'fulfilled') {console.log('Fulfilled:', result.value);} else {console.error('Rejected:', result.reason);}});});
2.4 结合 async/await 与 try/catch 捕获
function fetchData1() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.3 ? resolve(`Data 1`) : reject(`Error from 1`);}, 1000);});}function fetchData2() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.4 ? resolve(`Data 2`) : reject(`Error from 2`);}, 1000);});}function fetchData3() {return new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.6 ? resolve(`Data 3`) : reject(`Error from 3`);}, 1000);});}async function fetchData() {try {const data1 = await fetchData1();console.log(data1);} catch (error) {console.error('Caught an error during fetch:', error);}try{const data2 = await fetchData2();console.log(data2);} catch (error) {console.error('Caught an error during fetch:', error);}try{const data3 = await fetchData3();console.log(data3);} catch (error) {console.error('Caught an error during fetch:', error);}} fetchData()
一个函数里可以有多个try-catch模块
3 作用域和作用域链
作用域: 函数和变量可见范围
作用域链:当前作用域找不到变量 到上一层找 直到全局也找不到 层层关系
shadowing:局部和外部同名 局部会遮蔽外部
局部变量可以访问外部和全局(任何地方都能访问对象)
利用闭包保存状态
执行上下文:全局,函数
执行栈:先全局执行上下文压入栈里,每次函数调用就新的执行上下文压入栈里,然后执行栈顶 弹出执行上下文
生命周期: 创建:确定this,词法和变量环境;执行:变量赋值 代码执行;回收:弹出执行上下文
js执行有解释和执行阶段,作用域是解释阶段确定的,执行上下文是执行阶段确定的
闭包形成是函数定义 作用域链和执行上下文共同作用
function outer() {const value = 'outer value'; // 外部变量function inner() {const value = 'inner value'; // 内部变量,遮蔽外部变量console.log(value); // 输出 'inner value'}console.log(value); // 输出 'outer value'return inner;}let x = outer();x()
inner函数形成闭包 即使outer已执行完毕还是能访问value,然后保留对value的引用
fn.length
是一个属性,返回函数 fn
的参数个数
function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn(...args);}return function(...args2) {return curried(...args, ...args2);};};
}function multiply(a, b) {return a * b;
}const curriedMultiply = curry(multiply);
console.log(curriedMultiply(2)(3));
4 递归展开嵌套数组
//'abc'->value:'abc'//'[abc[def]]'->{value:'abc',children:{value:'def',children:null}}function digui(str,index){let node={value:'',children:null}while(index.value<str.length){let char=str[index.value++]if(char==='['){node.children=digui(str,index);}else if(char===']')break;else node.value+=char}return node}function yuan(str){let index={value:0}if(str[index.value]==='['){index.value++return digui(str,index)}else return digui(str, index)}let str1='abc'let str2='[abc[def]]'console.log(yuan(str1))console.log(yuan(str2))