题集

484 阅读14分钟
写这篇文章的目的是在于最近在看一些面试题之类的(实在是菜的不行啊,想着没事干的时候就刷题吧,感觉自己不能再放任下去了),但是到处搜集答案看完以后当时懂了,后面就又忘记了,想要再次回顾的话就会比较麻烦,所以就把掘金当成笔记本了,以后想看也会比较方便,有兴趣的小伙伴可以一起哦。

编程题

1.实现一个简单的模板字符串替换

let str='{{name}}很厉害,才{{age}}岁';
let context={name:'小明',age:18};
str.replace(/\{\{(.*?)\}\}/g,(match,key)=>context[key.trim()]);



正则小知识点:

  • 修饰符:i,g,m
  • 方括号:用于查找某个范围内的字符
  • 元字符:是拥有特殊含义的字符,比如\w代表查找单词字符,/W代表查找非单词字符
  • 量词:类似于n+,代表匹配任何包含至少一个 n 的字符串

2.将数组扁平化并取出其中重复数据,最终得到一个升序且不重复的数组

法一:

let arr=[1, 1,[3, 2, [4, 5]]];
Array.from(new Set(arr.flat(3))).sort(function(a,b){
return a-b;
});



法二:

let arr=[1,1, [3, 2, [4, 5]]];
Array.from(new Set(arr.toString().split(','))).sort(function(a,b){
return a-b;
})


知识点:

  • Array.from()
从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例
把set对象变为普通数组
  • new Set

创建set对象,用于数组去重

  • flat

扁平化方法

  • arr.toString()结果位"1,3,2,4,5";
  • sort 方法

其中关于为什么return a-b是升序的问题可参考文章这篇文章:www.cnblogs.com/saifei/p/90…

参考:www.cnblogs.com/wind-lanyan…

3.介绍下深度优先遍历和广度优先遍历,如何实现?

深度优先遍历实现:

法一(递归法):

 let testObj = {
      name: 1,
      children: [
        { name: 2, children: [{ name: 3, children: [{ name: 4 }] }] },
        { name: 5, children: [{ name: 6 }] }
      ]
};
function dfs(obj,result=[]){
result.push(obj.name);
if(obj.children&&obj.children.length){
for(let i=0;i<obj.children.length;i++){
dfs(obj.children[i],result)
}
return result;
}
}
dfs(testObj);


法二(栈写法):

let testObj = {
      name: 1,
      children: [
        { name: 2, children: [{ name: 3, children: [{ name: 4 }] }] },
        { name: 5, children: [{ name: 6 }] }
      ] 
   };
function dfs(obj) {     
 let squese = [],
        result = [];
        squese.push(obj);
        while (squese.length) {
        let obj1 = squese.pop();  
        result.push(obj1.name);       
 if (obj1.children) {
          for (let j = obj1.children.length-1; j >= 0; j--) { 
                   squese.push(obj1.children[j]);
          }
        } 
     } 
     return result; 
   }

dfs(testObj);


广度优先遍历实现:

let testObj = 
{    name: 1, 
     children: [
               { name: 2, children: [{ name: 3, children: [{ name: 4 }] }] },
               { name: 5, children: [{ name: 6 }] }
      ]
};
function bfs(obj){
let result=[],squ=[];
squ.push(obj);
while(squ.length){
[...squ].forEach((item)=>{
squ.shift();
result.push(item.name)
 if(item.children){
 squ.push(...item.children)
 }

})
}
return result;
}
bfs(testObj);


这一题可以参考www.cnblogs.com/zzsdream/p/…blog.csdn.net/weixin_3042…

4.请分别用深度优先思想和广度优先思想实现一个拷贝函数?

深度优先思想实现拷贝:

let testObj = 
{    name: 1, 
     children: [
               { name: 2, children: [{ name: 3, children: [{ name: 4 }] }] },
               { name: 5, children: [{ name: 6 }] }
      ]
};
function getType(obj){
return Object.prototype.toString.call(obj).slice(8,-1);
} 

function dfsCopy(obj,arr=[]){
let copyObj={};
 if(getType(obj)=='Object'||getType(obj)=='Array'){
    if(~arr.indexOf(obj)){
    copyObj=arr.indexOf(obj)
    }else{
    arr.push(obj)
    for(let item in obj){
    copyObj[item]=dfsCopy(obj[item],arr)
    }    }
    
}else if(getType(obj)=='Function'){
   copyObj=eval('('+obj.toString()+')')
}else{
   copyObj=obj;
 }
return copyObj;
}

dfsCopy(testObj);


也可这样(只考虑的object喝array类型):

function cloneDeep(target,map = new WeakMap()) {
  if(typeOf taret ==='object'){
     let cloneTarget = Array.isArray(target) ? [] : {};
      
     if(map.get(target)) {
        return target;
    }
     map.set(target, cloneTarget);
     for(const key in target){
        cloneTarget[key] = cloneDeep(target[key], map);
     }
     return cloneTarget
  }else{
       return target
  }
 
}

可参考:https://juejin.cn/post/6844904200917221389

广度优先思想拷贝:后续分享。。。。

5.如何实现一个new?

思路:


function Person(name,age){
this.name=name;
this.age=age;
};
function newObj(){
let obj={};//创建一个对象
let constructor=[].shift.call(arguments);//获取第一个参数Person,也就是构造函数
obj._proto_=constructor.prototype;//使对象能访问Person.prototype的属性
constructor.apply(obj,arguments);//是对象能访问构造函数Person的属性
return obj
}
newObj(Person,'小明',1)


参考文章:

实现new :

www.jianshu.com/p/b325dc4e7…

[].shift.call(arguments): 

blog.csdn.net/Mrceel/arti…

calll,applay:

www.jianshu.com/p/bc541afad…

prototype和_proto_:

segmentfault.com/a/119000001…

juejin.cn/post/684490…

6.请把[A1,A2,B1,B2 ,C1,C2,D1,D2]和[A,B,C,D]合并为[A1,A2,B1,B2 ,C1,C2,D1,D2]?

let a=['A1','A2','B1','B2' ,'C1','C2','D1','D2'],b=['A','B','C','D'];
let ans=[...a,...b].sort((a1,a2)=>(
 a1.codePointAt(0)-a2.codePointAt(0)||a2.length-a1.length
||a1.codePointAt(1)-a2.codePointAt(1)
))


注:ES6 提供了codePointAt()方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点,codePointAt()方法的参数,是字符在字符串中的位置(从 0 开始);

其中‘a’.codePointAt(1)==undefined;

7.改造下面的代码,使之输出0-9,写出你能想到的所有解法?

这里就不上代码了,方法太多,可以看这篇文章blog.csdn.net/weixin_4487…

其中涉及到对Object.create(null)的了解:blog.csdn.net/seafishyls/…

8.使用迭代的方式实现flatten函数?

如:let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

得到 flatten(arr)=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

法一:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]];
function flatten(arr){
let newArr=[];
function flat(arr1){
for(let item of arr1){
  if(Array.isArray(item)){
  flat(item)
  }else{
  newArr.push(item);
  }
}
}
flat(arr);
return newArr;
}
flatten(arr);


法二:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]];
function flatten(arr){
while(arr.some(item=>Array.isArray(item))){
arr=[].concat(...arr);
}
return arr;
}
flatten(arr);


法三:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]];
function flatten(arr){
return arr.reduce((pre,cur)=>Array.isArray(cur)?[...pre,...flatten(cur)]:[...pre,cur],[])
}
flatten(arr);


9.var a=?; if(a==1&&a==2&&a==3){console.log(1)},什么情况下会打印出1?

let a={
i:1,
valueOf:function(){
return this.i++;
}
}
if(a==1&&a==2&&a==3){
console.log(1);
}


参考文章:zhuanlan.zhihu.com/p/110086149segmentfault.com/a/119000001…

segmentfault.com/a/119000000…


特例:


10.实现一个sleep函数,比如sleep(1000)意味着等待1000毫秒,可从Promise、Generator、Async、Await等角度实现?

法一:

function sleep(ms){
let dateNow=new Date().getTime();
while(new Date().getTime()-dateNow<=ms){
continue;
}
}
function test(){
console.log(1);
sleep(1000);
console.log(2)
}
test();


法二:

function sleep(ms,callback){
setTimeout(callback,ms)
}
sleep(1000,()=>{
console.log(1)
})


法三:

function sleep(ms){
return new Promise((resolve)=>
setTimeout(resolve,ms)
)
}
sleep(1000).then(()=>{console.log(1)})


法三:

function sleep(ms){
return new Promise((resolve)=>{
setTimeout(resolve,ms)
})
}
async function test(ms){
let res =await sleep(ms);
console.log('test')
return res;
}
test(1000);


function sleep(ms){
yield  new Promise(function(resolve,rejecte){
setTimeout(resolve,ms)
})
}
sleep(1000).next().value.then(()=>{console.log(1)})

参考:blog.csdn.net/qq_36711388…

www.cnblogs.com/yaya-003/p/…

11.实现(5).add(3).minus(2)功能?

例:5+3-2,结果为6

Number.prototype.add=function(num){
return this.valueOf()+num
}
Number.prototype.minus=function(num){
return this.valueOf()-num
} 
console.log((5).add(3).minus(2));


12.冒泡排序如何实现,时间复杂度是多少,还可以如何改进?

改进后的冒泡排序:

function mySort(arr){
for(let i=0;i<arr.length;i++){
let flag=true;
for(let j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
flag=false;
let t=arr[j]
arr[j]=arr[j+1];
arr[j+1]=t;
}
}
if(flag==true){
break;
}
}
return arr;
}
mySort([2,4,6,3,5,8,1])


这里我们加入了标志,flag,如果有一趟排序中没有产生交换的话,那么说明此刻数列以及变成了有序的数列

注比较次数是6+5+4+3+2+1 也就是n(n-1)/2,因此时间复杂度O(N^2)

时间复杂度应是O(n^2),但改进后使最佳情况时为O(n)(顺序不需要改变的情况)

13.某公司1到12月份的销售额存在一个对象里

如下:{1:222,2:123,5:888},请把数据处理为如下结构:

[222,123,null,null,888,null,null,null,null,null,null,null]

法一:

function myFunc(obj){
let arr=[];
for(let i=0;i<12;i++){
if(obj.hasOwnProperty(i+1)){
arr.push(obj[i+1])
}else{
arr.push(null);
}

}
return arr;
}
myFunc({1:222,2:123,5:888})


法二:

Array.from({length:12}).map((item,index)=>{return obj[index+1]?obj[index+1]:null})
//或者
Array.from({length:12},(item,index)=>{return obj[index+1]?(obj[index+1]):null})


Array.from() 可以通过以下方式来创建数组对象:

  • 伪数组对象(拥有一个 length 属性和若干索引属性的任意对象)
  • 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)

Array.from() 方法有一个可选参数 mapFn,让你可以在最后生成的数组上再执行一次 map 方法后再返回。也就是说 Array.from(obj, mapFn, thisArg) 就相当于 Array.from(obj).map(mapFn, thisArg)


14.要求设计lazyMan类,实现以下功能?

例:

 LazyMan('Tony');
 // Hi I am Tony 

 LazyMan('Tony').sleep(10).eat('lunch');
 // Hi I am Tony // 等待了10秒... 
 // I am eating lunch  LazyMan('Tony').eat('lunch').sleep(10).eat('dinner'); 
 // Hi I am Tony // I am eating lunch 
 // 等待了10秒... // I am eating diner

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food'); 
// Hi I am Tony 
// 等待了5秒... 
// I am eating lunch 
// I am eating dinner 
// 等待了10秒... 
// I am eating junk food

 参考:建议www.jianshu.com/p/f1b7cb456…和       muyiy.vip/question/pr…一起看

class tClass{
constructor(name){
this.taskList=[];
this.name=name;
console.log('Hi I am '+name);
setTimeout(()=>{
this.next()//这个必须有,否则不会继续执行
},0)

}
eat(str){
const fn=()=>{
console.log('I am eating '+str);
this.next()
}
this.taskList.push(fn)
return this;
}
sleepFirst(ts){
const fn=()=>{setTimeout(()=>{
this.next();
},ts*1000)
}
this.taskList.unshift(fn);//需要在eat之前执行,因此unshift到eat放入之前
return this;
}sleep(ts){
const fn=()=>{setTimeout(()=>{
this.next();
},ts*1000)
}
this.taskList.push(fn)
return this;
}  next(){
  const fn=this.taskList.shift();
  fn&&fn();
  }
}

function lazyMan(name){ return new tClass(name)};
lazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')


思路:函数按照执行顺序放入taskList数组,执行的时候按照队列的方法先进先出。

15.给定两个数组,写一个方法来计算它们的交集?

例如:给定nums1=[1,2,2,1],nums2=[2,2],返回[2,2]

答案:参考segmentfault.com/a/119000001…

function intersect(nums1,nums2){
let pos1=0;
let pos2=0;
let nums3=[];
while(pos1<nums1.length&&pos2<nums2.length){
if(nums1[pos1]==nums2[pos2]){
nums3.push(nums1[pos1]);
pos1++;
pos2++;

}else if(nums1[pos1]<nums2[pos2]){
pos1++;
}else{
pos2++;
}

}
return nums3;
}
intersect([1,2,2,1],[2,2]);


16.如何设计实现无缝轮播?

17.随机生成一个长度为10的整数类型的数组,例如[2,10,3,4,5,11,10,11,20],将其排列成一个新数组,要求新数组形式如下,列入[[2,3,4,5],[10,11],[20]]?

参考:www.jianshu.com/p/823a2f2f0…

理解一:把现有数组按区间来分,以10位为单位区分,比如10以内的一组,10-20之间的一组,20-30之间的一组,以此类推;

let arr=[2,10,3,4,5,11,10,11,20];
function changeArr(arr){
let result=[];
arr.forEach((item,index)=>{
let key=parseInt(item/10);
if(Array.isArray(result[key])&&!result[key].includes(item)){
result[key].push(item);
}else{
result[key]=[];
result[key].push(item)
}

})
return result;

}
changeArr(arr);


理解二:把现有数组如果是连续的放一组,不连续的单独放

let arr=[2,10,3,4,5,11,10,11,20];
function changeArr(arr){
         let newArr=arr.sort((x,y)=>{
         return x-y;
         })
         let result=[];
         let j=0;
  for(let i=0;i<newArr.length;i++){
while(i<arr.length-1&&(newArr[i]+1==newArr[i+1]||newArr[i]==newArr[i+1])){
i+=1;

  }
result.push(newArr.slice(j,i+1))

j=i+1;
}
result=result.map((item)=>{
return Array.from(new Set(item))
})
return result;
}
changeArr(arr);


18.如何把一个字符串的大小写取反,(大写变小写,小写变大写),例如‘AbC’编程‘aBc'?

'abCd'.replace(/[a-zA-Z]/g,function(a){
return /[a-z]/.test(a)?a.toUpperCase():a.toLowerCase()
})


19.实现一个字符串匹配算法,从长度为n的字符串S中,查找是否存在字符串T,T的长度是m,若存在返回所在的位置?

function find(S,T){
if(S.length<T.length) return -1;
for(let i=0;i<S.length;i++){
if(S.slice(i,i+T.length)==T){
return i;
}
}

}
find('abcde','cd');


可参考:github.com/Advanced-Fr…

20.使用JavaScript Proxy实现简单数据绑定?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>proxy</title>
</head>
<body>
  <h1>使用Proxy 和 Reflect 实现双向数据绑定</h1>
  <input type="text" id="input">
  <h2>您输入的内容是: <i id="txt"></i></h2>
  <script>
    //获取dom元素
    let oInput = document.getElementById("input");
    let oTxt = document.getElementById("txt");
 
    //初始化代理对象
    let obj = {};
    //给obj增加代理对象
    let newProxy = new Proxy(obj, {
      get: (target, key, recevier) => {
        return Reflect.get(target, key, recevier);
      },
      set: (target, key, value, recevier) => {
        //监听newProxy是否有新的变化
        if (key == "text") {
          oTxt.innerHTML = value;
        }
        //将变化反射回原有对象
        return Reflect.set(target, key, value, recevier);
      }
    })
    //监听input输入事件
    oInput.addEventListener("keyup", (e) => {
      //修改代理对象的值
      newProxy.text = e.target.value;
    })
  </script>
</body>
</html>
 

21.旋转数组算法题?

给定一个数组,将数组中的元素向右一定k个位置,其中k是非负数

//法一:
let arr=[1,2,3,4,5,6];
function test(arr,k){
let k1=k%arr.length;
return arr.slice(arr.length-k1).concat(arr.slice(0,arr.length-k1));

}
test(arr,2);

//法二:
var rotate = function(nums,k) {
    for(var i = 0;i<k;i++){
        nums.unshift(nums.pop());
    };
return nums;
};
rotate([1,2,3,4,5,6],2)



22.打印出1-10000之间的所有对称数 例如121,1331等?

笨方法。。。。:

function test(num){
let result=[];
for(let k=11;k<=num;k++){
let i=k.toString();
let len=i.length/2;
let arr1=i.slice(0,len);
let arr2=i.slice(len);
if(i.length%2==1){
arr2=arr2.slice(1)
}
arr2=arr2.split('').reverse().join('');
if(arr2==arr1){
result.push(i)
}
}
return result;
}
test(10000)


法二:

function test(num){
let len=num.toString().length/2;
let len1=+((num+'').slice(0,len))+1
        let result=[];
        for(let i=1;i<=len1;i++){
       
        let a=i.toString()+i.toString().split('').reverse().join('');
        if(+a<=num){
        result.push(a)
        }
        for(let k=0;k<10;k++){
        let b=i.toString()+k.toString()+i.toString().split('').reverse().join('');
          if(+b<=num){
          result.push(b);
          }
        }

       }
       return result;
        }
test(10000)


23.算法题(移动0),给定一个数组nums,编写一个函数将所有的0移动到数组的末尾,同时保持非0元素的相对顺序?

说明:

          必须在原数组上啊哦做,不能拷贝额外的数组

          尽量减少操作次数

function test(nums){
let len=nums.length;
let j=0;
for(let i=0;i<len-j;i++){
if(nums[i]==0){
nums.push(0);
nums.splice(i,1);
i--;
j++;
}
}
return nums;
}
test([1,2,3,0,4,0,0,5])


24.实现一个add函数,满足以下功能?

add(1);//1 
add(1)(2);//3
add(1)(2)(3);//6
add(1)(2,3);//6
add(1,2)(3);//6
add(1,2,3);//6

function add(){
let args=[].slice.apply(arguments);
function fn(){

return add(...args.concat([].slice.apply(arguments)));
//或者 return add.apply(null,args.concat([].sice.apply(arguments)))
}
fn.toString=function(){ //或者重写fn.valueOf方法也能改变函数的隐式转换结果
return args.reduce((x,y)=>{
return x+y;
})
}
return fn;
};
add(1);//1 
add(1)(2);//3
add(1)(2)(3);//6
add(1)(2,3);//6
add(1,2)(3);//6
add(1,2,3);//6


ps:找了很多关于这个题的文章,以下这篇大神写的比较详细易懂

并且尤其是这句解决了我关于为什么要使用add.apply的疑虑


参考:blog.csdn.net/hemister/ar…

25.算法题之两数之和?

给定一个整数数组和一个目标值,找出数字居中和为目标值的两个数。

你可以假定每个输入只对应一种答案,且同样的元素不能被重复利用。

法一:

//一趟哈希表:
function test(nums,target){
let map={};
for(let i=0;i<nums.length;i++){
if(target-nums[i] in map){
return [target-nums[i],nums[i]]
}else{
map[nums[i]]=i;
}
}
}
test([2,3,5,4,7],7)


法二:两次for循环

26.在输入框如何判断输入的是一个正确的网址?

function isUrl(url){
try{
new URL(url);
return ture;
}catch(err){
return false;
}
}

27.实现convert方法,把原始list转换成树形结构,要求尽可能降低时间复杂度?

参考文章blog.csdn.net/u012193330/…

28.实现模糊搜素的关键词高亮显示?

<!DOCTYPE html>
<html lang="z-cn">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Search highlight</title>
    <style>
      b {
        color: red;
      }
      li {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <input id="ipt" type="text" />
    <section>
      <ul id="container"></ul>
    </section>
  </body>
  <script>
    const container = document.getElementById("container");
    const ipt = document.getElementById("ipt");
    //节流
    function throttle(_func_) {
      let run = true;
      return function() {
        if (!run) return;
        run = false;
        setTimeout(() => {
          _func_.apply(this, arguments);
          run = true;
        }, 300);
      };
    }
    //缓存,并且必须是一个闭包,不然没法缓存
    function memorize(fn) {
      const cache = new Map();
      return (name) => {
        if (!name) {
          container.innerHTML = "";
          return;
        }
        if (cache.get(name)) {
          container.innerHTML = cache.get(name);
          return;
        }
        //没有缓存过则处理模板字符串并且添加缓存
        const res = fn.call(fn, name).join("");
        cache.set(name, res);
        container.innerHTML = res;
      };
    }

    function handleInput(value) {
      const reg = new RegExp(`\(${value}\)`);
      const search = data.reduce((res, cur) => {
        if (reg.test(cur)) {
          //以下两个正常匹配参考https://www.cnblogs.com/xzdm/p/12566114.html
          const match = RegExp.$1;
          res.push(`<li>${cur.replace(match, "<b>$&</b>")}</li>`);
        }
        return res;
      }, []);
      return search;
    }
    const data = [
      "济南大明湖",
      "济南大明湖公园",
      "济南大明湖饭店",
      "济南大酒店",
      "济南趵突泉"
    ];
    const memorizeInput = memorize(handleInput);
    ipt.addEventListener(
      "input",
      throttle((e) => {
        memorizeInput(e.target.value);
      })
    );
  </script>
</html>

正则知识点参考:www.cnblogs.com/xzdm/p/1256…

全文参考:www.jianshu.com/p/693cfc7ac…

29.已知数据格式,实现一个fn找出链条中所有的父级id?

const data2 = [{    id: '1',    name: 'test1',    children: [        {            id: '11',            name: 'test11',            children: [                {                    id: '111',                    name: 'test111'                },                {                    id: '112',                    name: 'test112'                }            ]        },        {            id: '12',            name: 'test12',            children: [                {                    id: '121',                    name: 'test121'                },                {                    id: '122',                    name: 'test122'                }            ]        }    ]}];
function test(data,value){
let res=[];
function dfs(arr,temp=[]){
for(let i=0;i<arr.length;i++){
if(arr[i].children){
temp.push(arr[i].id)
dfs(arr[i].children,temp)
}else{
if(arr[i].id==value){
res=temp;
return;
}
}
}
}
dfs(data);
return res
}
test(data2,122);


参考:blog.csdn.net/yang1507140…

30.给定两个大小为m和n的有序数组nums1和nums2。请找出这两个有序数组的中位数。要求算法的 时间复杂度为O(log(m+n))?

//示例1:
nums1=[1,3];
nums2=[2]
//中位数是2.0
示例2:
nums1=[1,2];
nums2=[3,4];
//中位数是(2+3)/2=2.5

let nums1=[1,2],nums2=[3,4];
function test(nums1,nums2){

for(let i=0;i<nums2.length;i++){
nums1.push(nums2[i])
}
nums1.sort((a,b)=>{
return a-b
})
if(nums1.length%2==0){
return (nums1[nums1.length/2]+nums1[nums1.length/2-1])/2
}else{
return nums1[nums1.length-1/2]
}

}
test(nums1,nums2);


参考:blog.csdn.net/weixin_3377…

哈哈,终于更新到第30个题了,还有30个题要更新,先复习几天前面的题喽

31.模拟实现一个深拷贝,并考虑对象相互引用以及Symbol拷贝的情况?