前端面试JS必备基础之深浅拷贝和this指向问题@莫成尘

一:js深拷贝

在JS中,数据类型分为基本数据类型和引用数据类型两种,对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中。深拷贝作用在引用类型上!例如:Object,Array。深拷贝不会拷贝引用类型的引用,而是将引用类型的值全部拷贝一份,形成一个新的引用类型,这样就不会发生引用错乱的问题,使得我们可以多次使用同样的数据,而不用担心数据之间会起冲突
如何实现深拷贝?
1:序列化以及反序列化,JSON.stringify()以及JSON.parse()
let obj = {
    
    
    a: 1,
    b: 2,
    c: 3
}
let objclone = Object.assign({
    
    }, obj);
objclone.b = 5;
console.log(obj.b); // 2
console.log(objclone.b); // 5
2: 递归拷贝 此方法借鉴于老同学前端郝晨光
// 定义一个深拷贝函数  接收目标target参数
		function deepClone(target = '') {
    
    
		    // 定义一个变量
		    let result;
		    // 如果当前需要深拷贝的是一个对象的话
		    if (typeof target === 'object') {
    
    
		    // 如果是一个数组的话
		        if (Array.isArray(target)) {
    
    
		            result = []; // 将result赋值为一个数组,并且执行遍历
		            for (let i in target) {
    
    
		                // 递归克隆数组中的每一项
		                result.push(deepClone(target[i]))
		            }
		         // 判断如果当前的值是null的话;直接赋值为null
		        } else if(target===null) {
    
    
		            result = null;
		         // 判断如果当前的值是一个RegExp对象的话,直接赋值    
		        } else if(target.constructor===RegExp){
    
    
		            result = target;
		        }else {
    
    
		         // 否则是普通对象,直接for in循环,递归赋值对象的所有值
		            result = {
    
    };
		            for (let i in target) {
    
    
		                result[i] = deepClone(target[i]);
		            }
		        }
		     // 如果不是对象的话,就是基本数据类型,那么直接赋值
		    } else {
    
    
		        result = target;
		    }
		     // 返回最终结果
		    return result;
		}
		 let obj = {
    
    
			a: {
    
    
				c: /a/,
				d: undefined,
				b: null
			},
			b: function () {
    
    
				console.log(this.a)
			},
			c: [
				{
    
    
					a: 'c',
					b: /b/,
					c: undefined
				},
				'a',
				3
			]
		}
		let objclone = deepClone(obj);
		console.log(objclone);
3:ES6 新语法   ...展开
		let obj = {
    
     a:10 }
		let objclone = {
    
    ...obj}
		objclone.a = 5
		console.log(obj,objclone)  // 10   5 

this指向问题

js常考点 主要是考察bind,call,apply的使用的区别
相同点:
1:都能改变this指向
2:都能传递参数
3:都能通过方法"."方法名调用

不同点
1:函数名不同
2:参数传递方式不同
3:改变this指向的时机不同(bind在复制时改变,其他两个在调用时改变)
4:参数传递时机不同

举例: 完善以下函数 ,使 f 的 this 指向指定的对象oTarget(题目来源牛客网)

function bindThis(f, oTarget) {
    
    
   
} 
//这是用来调用验证的函数
function() {
    
    
	var r = bindThis(function(a, b) {
    
    
		return this.test + a + b
	}, {
    
    
		test: 2
	})(2, 3);
	return r === 7;
}

答案:

//第一种:
function bindThis(f, oTarget) {
    
    
    return function(){
    
    
        return f.call(oTarget,...arguments)
    }
} //使用call方法 注意arguments对象的参数形式
//第二种:
function bindThis(f, oTarget) {
    
    
    return function(){
    
    
        return f.apply(oTarget,arguments)
    }
} //使用apply方法 
//第三种:
function bindThis(f, oTarget) {
    
    
    return f.bind(oTarget)
}// bind方法  直接绑定this指向

其他想了解的请留言

猜你喜欢

转载自blog.csdn.net/weixin_47821281/article/details/114389905