JS中对象合并、值的浅拷贝与深拷贝、以及对象中this指针

对象合并

回顾一下数组以及字符串合并使用concat方法

//声明字符串和数组
var str1 = '这是第一个字符串',
    str2 = '这是第二个字符串',
    arr1 = [1,2,3],
    arr2 = [4,5,6];
//字符串1和2相拼接
var str = str1.concat(str2);
console.log(str);
//数组1和数组2相拼接
var arr = arr1.concat(arr2);
console.log(arr);

当然使用此方法讲字符串与数组拼接也是可行的,这里就不再演示了。

而对象的合并则需要用到另一个方法 

Object.assign(target,sources)在这里 target指目标对象(也就是添加后被返回的对象),sources指源对象(也就是要拿去加入目标对象的,源对象可以是多个)

//创建多个对象
var obj1 = {'name':'张三'},
    obj2 = {'gender':'男'},
    obj3 = {'hobby':'打球'};
//合并多个对象
var obj = Object.assign({},obj1,obj2,obj3);//这里使用了一个空对象为目标对象
console.log(obj);

值得拷贝(浅拷贝、深拷贝)

值拷贝的一个原理

依次去除对象属性的值进行赋值

在对对象值得拷贝时,对象的值可能是一个基本类型,也可能是一个引用类型,那么就可能涉及到一个问题,如果对拷贝后得到的对象中引用类型的值进行修改,那么原对象内引用类型的值可能会随之一起改变,而我们并不想原对象改变,那么就涉及到 浅拷贝  与  深拷贝 ,这也正是浅拷贝与深拷贝区别之处(浅拷贝原对象引用类型的值会随拷贝对象中修改而改变,深拷贝则不会)。

浅拷贝

 如何实现浅拷贝

1.通过for-in实现

       

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//使用for-in实现浅拷贝
var obj1 = {}
for(let key in obj){
    obj1[key] = obj[key];
}
console.log(obj1);

 

 

2.通过Object.assign方法实现浅拷贝

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//浅拷贝
var obj1 = Object.assign({},obj);
console.log(obj1);

 

可以看到已经成功拷贝了一个obj1,'hobby'的值为一个数组。此时我们来验证修改obj1数组中内容原对象obj是否会改变。

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//浅拷贝
var obj1 = Object.assign({},obj);
console.log(obj1);
//这里我们直接使用第二种方法获得的obj1 来进行验证
obj1.hobby[0] = '看电视';
console.log(obj1.hobby);
console.log(obj.hobby);

 我们可以看到原对象obj中数组的内容也被改变了

深拷贝

 1.通过for-in加递归实现

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//进行深拷贝
function copy(obj){
    var obj1 = obj instanceof Array ? [] : {};//声明一个新对象obj1,如果obj为对象则obj1为一个空对象,如果obj为数组则obj1为一个空数组
    //for-in遍历obj
    for(let key in obj){
        //判断遍历出来的值为引用还是基本类型,如果是基本类型传入函数中再进行一次知道得出的值都为基本类型
        obj1[key] = typeof obj[key] === 'object' ? copy(obj[key]) : obj[key];
    }
    return obj1;
}
copy(obj);

2.通过JSON方法实现(此方法拷贝时,对象中的方法function会被自动舍弃)

 

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//进行深拷贝
var str = JSON.stringify(obj);
var obj1 = JSON.parse(str);
console.log(obj1);

 此时我们来验证修改obj1数组中内容原对象obj是否会改变。

//创建一个obj对象
var obj = {
    'name':'张三',
    'gender':'男',
    'hobby':['打球','游泳']
}
//进行深拷贝
var str = JSON.stringify(obj);
var obj1 = JSON.parse(str);
console.log(obj1);
//修改obj1中hobby内的内容
obj1.hobby[0] = '打羽毛球';
console.log(obj1.hobby);
console.log(obj.hobby);

我们可以看到,原obj并没有因为obj1中的hobby改变而改变。 

this指针

1.属性事件中,在标签中调用事件函数

<button id='button' onclick='fn()'>按钮</button>

<script>
    function fn(){
        console.log(this);
    }
</script>

可以看到未传入参数时this是指向全局对象window 的

<body>
	<button id='button' onclick='fn(this)'>按钮</button>
</body>
<script type="text/javascript">
	function fn(that) {
		console.log(that);
	}
</script>

 

传入参数之后this指向的是调用这个函数的标签

2.onclick事件中的this 【先获取标签元素】

<body>
	<button id='button'>按钮</button>
</body>
<script type="text/javascript">
	var button = document.getElementById('button');
	button.onclick = function(){
		console.log(this);
	}
</script>

 

可以看到this指向的是调用这个点击函数的 button标签

3.构造函数中的this 

//创建一个构造函数
function Person(name,gender){
	this.name = name;
	this.gender = gender;
}
//创建一个构造函数的实例
var one = new Person('张三','男');
console.log(one);

可以看到this指向当前这个实例 

4.原型上方法中的this

//在原型链上添加一个方法
Array.prototype.myself = function(){
	console.log(this);
}
//定义一个数组
var arr = [1,2,3,4];
//调用自己设定的方法
arr.myself();

 

可以看到this指向当前调用这个方法的数组

5.对象方法中的this

//创建一个对象
var obj = {
	'name':'张三',
	'gender':'男',
	'sayName':function(){
	console.log(this.name);
    }
}
//obj调用sayName中的方法
obj.sayName();

 

可以看到此时this就是指向这个obj本身,也就是调用这个方法的obj本身

结论:谁调用方法,this就指向谁 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值