前端面试题-js
1.对象深浅拷贝
1:为什么需要拷贝
var a=1,
b=a;
a=3;
//此时b是不会被a的改变的
console.log(b);
因为对象赋值的时候赋值的是引用
var a ={
a :1
};
var b=a;
a.a=2;
// 此时会被更改,因为赋值的是引用
console.log(b);
2 :如何实现对象的浅拷贝==引用跟一起变
//浅拷贝;拷贝对象一层
var a ={
a:1,
b:2,
}
function simpleClone(obj) {
var cloneObj = {};
//es3语法实现,语义化不强
for(var i in obj){
cloneObj[i] = obj[i]
}
}
// console.log(Object.keys(obj));
// console.log(Object.values(obj));
// console.log(Object.entries(obj));
// for (var key of Object.keys(obj)) {
// cloneObj[key] = obj[key];
// }
// es6语法
for (var [key,value] of Object.entries(obj)) {
cloneObj[key] = value;
}
return cloneObj;
//es5语法 defineProperty;
Object.getOwnPropertyNames(obj).forEach(function (key){
// cloneObj[key] = obj[key];
var des = Object.getOwnPropertyDescriptor(obj,key)
Object.defineProperty(cloneObj,key,des);
});
return cloneObj;
}
console.log(simpleClone(a))
3、如何实现深拷贝=不跟着变(引用:切断)
1、原生js实现对象的深拷贝:
创建一个对象,将原对象的属性赋到创建的对象上去;
<script>
var obj ={
a:1,
b:{
c:3,
d:{
e:5
}
}
}
//对象里面包含对象,对象赋值存在引用(会跟着变),所以要使用递归,一层层排除对象
function deepClone(obj,cloneObj) {
//如果存在数组
cloneObj[i] = Array.isArray(obj[i]) ? [] :{} ;
for( i in obj) {
if( typeof obj[i] === 'object' && obj[i] !== null ) {
cloneObj[i] ={};
deepClone(obj[i],cloneObj[i]);
}
// 递归的出口:防止死循环
else{
cloneObj[i] = obj[i];
}
}
return cloneObj;
}
var obj1 = deepClone(obj);
// console.log(obj);
obj.b.c = 10;
console.log(obj1);
</script>
2、通过JSON.stringify实现
var obj ={
a:1,
b:{
c:3,
d:{
e:5,
f:[1,2,3,4,5]
}
}
}
//JSON.parse JSON.stringify;
function deepClone(obj){
//把对象转换成字符串
console.log(JSON.stringify(obj));
//把字符串转换成对象
return (Json.parse(JSON.stringify(obj)))
}
var obj1 = deepClone(obj);
// console.log(obj);
obj.b.c = 10;
obj.b.d.f.push(7);
console.log(obj1);
3、使用JQuery-extend实现深拷贝
var obj ={
a:1,
b:{
c:3,
d:{
e:5,
f:[1,2,3,4,5]
}
}
}
//3、使用jQuery中的extend实现深拷贝
console.log($.extend(true,{},obj))
function deepClone(obj) {
return $.extend(true,{},obj)
}
var obj1 = deepClone(obj);
// console.log(obj);
obj.b.c = 10;
obj.b.d.f.push(7);
console.log(obj1);
2.数组去重和排序
去重:
//a.indexof(元素b) 返回为-1:数组a里面没有元素b;
//封装一个去重的函数 unique 独一无二的
function unique(arr) {
var newArr = [];
for (var i=0;i<arr.length;i++) {
if(newArr.indexOf(arr[i]) === -1){
newArr.push(arr[i]);
}
}
return newArr;
}
var demo = unique(["成强","chengqiang","成强"]);
console.log(demo);
排序:
<script>
var arr=[1,5,2,4,9,6,7];
var Newarr=[];
Newarr= arr.sort(function(a,b){
return a-b;//返回的升序
});
console.log(Newarr);
</script>
冒泡排序:
<script> var a= [7,5,1,4,3]; for(var i=0; i<a.length; i++) { for(var j=0;j<a.length-i;j++){ if (a[j]>a[j+1]){ var t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } console.log(a); </script>
2.数组扁平化
//数组的扁平化 let arr = [1,2,[3,[4,[5,6]]]] //要求将数组扁平化处理[1,2,3,4,5,6] //方式一 flat(参数:深度) console.log(arr.flat(Infinity)) //方式二 reduce 方法 let arr1 = [1,2,3,4] let res = arr1.reduce((total,item) => { return total + item },0) console.log(res) // function flatFn(arr){ // return arr.reduce((total,item) => { // return res.concat(Array.isArray(item)?flatFn(item):item) // },[]) // } // console.log(flatFn(arr)) //方式三 数组转成字符串,再将字符串转成数组 function flatfn(arr){ return arr.join(',').split(',').map((item) => { return parseInt(item) }) } console.log(flatfn(arr))
3、堆栈内存+闭包作用域
1、作用域
es6定义变量的方法:let const
子可以访问父级,父级不能访问子集
2、闭包:一个函数和它周围状态的引用捆绑在一起的组合
<script> //1、函数作为返回值(函数内部临近) function test(){ const a =1; return function(){ console.log('a',a); } } const fn = test(); const a =2; fu(); // a=1 //2、函数作为参数(外部临近参数) function test(fn) { const a =1; fn(); } const a =2; function fn(){ console.log('a',a); } test(fn);//a=2 </script>
3、堆和栈(都是内存里面的2大块)
栈:简单数据类型:函数的参数值funciton(a)、简单变量值const a=3;存放的是值;
堆:复杂类型(对象),由程序员释放,若程序员不释放,由垃圾回收机制回收;首先在栈里面存放16进制地址,这个地址指向堆里面的数据;
![image-20210919144856982](/Users/yangmiemiedeliuzhuzhu/Library/Application Support/typora-user-images/image-20210919144856982.png)
4、this的值
this的值是函数执行的时候决定的,不是函数定义时决定
<script> function test(){ console.log("this",this); } test(); test.call({ name: '成强'}); test.apply({ name: '成强'}); class Person { constructor(name,age){ console.log('constrctor里面的this', this); this.name =name; this.age =age; } test (){ console.log('对象方法里面的this ',this) } asyncTest() { console.log(this)//this指向实例对象Person setTimeout(function(){ console.log('setTimeout回调中的this',this); //this指向的window },0) } } const chengqiang= new Person("成强",20); chengqiang.test(); </script>