JavaScript考核
一.深浅拷贝
首先浅拷贝和深拷贝只针对引用类型
浅拷贝:拷贝的是地址
常见方法:
1.拷贝对象:Object.assgin() / 展开运算符{...obj}拷贝对象
2.拷贝数组:Array.prototype.concat()或者[...arr]
如果是简单数据类型拷贝值,引用数据类型拷贝的是地址(简单理解:如果是单层对象,没问题,如果有多层就有问题)
const obj = {uname: 'pink',age: 19}const o = { ...obj }console.log(o)const o = {}Object.assign(o, obj)
const obj = {uname: 'pink',age: 18}//拷贝函数const o = {}function deepCopy(newObj, oldObj) {for (let k in oldObj) {//k 属性名 oldObj[k] 属性值newObj[k] = oldObj[k]}}deepCopy(o, obj)
深拷贝:拷贝的是对象,不是地址
常见方法:
1.通过递归实现深拷贝
const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}//拷贝函数const o = {}function deepCopy(newObj, oldObj) {for (let k in oldObj) {//一定先处理数组问题,再处理对象问题,因为本质上数组也属于对象//处理数组的问题if (oldObj[k] instanceof Array) {newObj[k] = []//k 索引号 oldObj[k] 乒乓球 足球deepCopy(newObj[k], oldObj[k])} else if (oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k], oldObj[k])} else {//k 属性名 oldObj[k] 属性值newObj[k] = oldObj[k]}}}deepCopy(o, obj)
2.lodash/cloneDeep
//需要先引入lodash库
<script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}//语法:_.cloneDeep(要被克隆的对象)const o = _.cloneDeep(obj)console.log(o)</script>
3.通过JSON.stringify()实现
<script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = JSON.parse(JSON.stringify(obj))console.log(o)
</script>
二.代码输出题
Promise.resolve().then(() => {return new Error('error!!!')}).then(res => {console.log("then: ", res)}).catch(err => {console.log("catch: ", err)})
输出:then: Error: error!!!
解释:Promise.resolve()创建一个状态为resolved的 Promise,接着调用第一个.then()方法返回一个Error对象,在 Promise 链中,返回一个非 Promise 值(包括Error对象)不会触发拒绝(rejection),而是会将这个值传递给下一个.then()方法
function createCounter() {let count = 0; // 私有变量function counter() {count++;return count;}return counter;}// 测试代码const firstCounter = createCounter();console.log(firstCounter());console.log(firstCounter());const secondCounter = createCounter();console.log(secondCounter());console.log(firstCounter());
输出:1 2 1 3
解释:两个计时器他们分别有自己独立的闭包,里面的count是私有变量
闭包 = 内层函数 + 外层函数的变量
async function async1 () {console.log('async1 start');await new Promise(resolve => {console.log('promise1')})console.log('async1 success');return 'async1 end'}console.log('script start')async1().then(res => console.log(res))console.log('script end')
输出:script start
async1 start
promise1
script end
解释:先执行同步代码,再调用async1,在async1函数中await后面的剩余代码被包装成微任务放入微任务队列,但由于Promise是pending状态,所以这个微任务暂时不执行。继续执行外面的同步代码,同步代码执行完毕后检查微任务队列
await new Promise(resolve => {await new Promise(resolve => {console.log('promise1')})console.log('async1 success');return 'async1 end'})
这段代码不执行是因为await会暂停async函数执行,等待后面的Promise解决。如果Promise永远不resolve/reject,就永远保持pending状态,导致await后面的代码永远不会执行