JavaScript原型,深克隆和浅克隆的区别

原型对象

        在JavaScript中,我们创建一个函数A(就是声明一个函数), 那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象( 即:prototype的属性的值是这个对象 )。这个对象B就是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性 constructor 指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。

代码:

			function Person(){
				
			}
			function Animal(grander,age){
				this.grander = grander;
				this.age = age;
			}
			Person.prototype.plainProp = 'hi';
			Person.prototype.objectProp = {'age':20};
			
			var a = new Person();
			var b = new Person();
			//浅克隆
			var c = new Animal('male',5);
			var d = c;
			d.grander = 'female';
			//深克隆一
			var e = new Animal('male',5);
			var f = JSON.parse(JSON.stringify(e));
			//深克隆二
			var g = new Animal('male',{type:'older',age:5});
			var h = deepclone(g);
			h.age.type = 'younger';
			//递归方法
			function deepclone(object){
				var result;
				if(isObject(object)=='Object')
					result = {};
				else if (isObject(object)=='Array')
					result = [];
				else
					return object;
				for(var key in object){
					var copy = object[key]
					if(isObject(copy)=='Object')
						result[key] = deepclone(copy);
					else if(isObject(copy)=='Array')
						result[key] = deepclone(copy);
					else
						result[key] = copy;
				}
				return result;
			}
			//判断对象,基本类型,数组
			function isObject(object){
				var result = Object.prototype.toString.call(object).slice(8,-1);
				return result;
			}
			g.grander = 'female';			
			a.plainProp = 'hello';
			a.objectProp.age = 100;
			console.log(a.objectProp);//'100'
			console.log(b.objectProp);//'100'----修改错误
			//原型替换
			a.objectProp= {'age':200};			
			console.log(a.plainProp);//'hello'
			console.log(b.plainProp);//'hi'
			console.log(a.objectProp);//'20'
			console.log(b.objectProp);//'200'
			b.objectProp.age = 300;
			console.log(a.objectProp);//'20' ----原型替换
			console.log(b.objectProp);//'300'
			
			console.log(a.hasOwnProperty('plainProp'))//'true'
			console.log(b.hasOwnProperty('objectProp'))//'false'
			console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
			console.log(c.grander)//'female'
			console.log(d.grander)//'female'
			console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
			console.log(e.grander)//'male'
			console.log(f.grander)//'female'
			console.log('==============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
			console.log(g.age.type)//'older'
			console.log(h.age.type)//'younger'

构造对象是发生了什么?


  1. 从上面的图示中可以看到,创建p1对象虽然使用的是Person构造函数,但是对象创建出来之后,这个p1对象其实已经与Person构造函数没有任何关系了,p1对象的[[ prototype ]]属性指向的是Person构造函数的原型对象。
  2. 如果使用new Person()创建多个对象,则多个对象都会同时指向Person构造函数的原型对象。
  3. 我们可以手动给这个原型对象添加属性和方法,那么p1,p2,p3…这些对象就会共享这些在原型中添加的属性和方法。
  4. 如果我们访问p1中的一个属性name,如果在p1对象中找到,则直接返回。如果p1对象中没有找到,则直接去p1对象的[[prototype]]属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则继续向上找原型的原型—原型链。 后面再讲)。
  5. 如果通过p1对象添加了一个属性name,则p1对象来说就屏蔽了原型中的属性name。 换句话说:在p1中就没有办法访问到原型的属性name了。
  6. 通过p1对象只能读取原型中的属性name的值,而不能修改原型中的属性name的值。 p1.name = “李四”; 并不是修改了原型中的值,而是在p1对象中给添加了一个属性name。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值