面向对象 - 传址与传值 / 操作符

传址与传值 / 操作符

上一篇的 继承 中说到 原型链继承
原型链继承过来就会破坏原先的构造函数结构(复杂数据类型拷贝只是引用地址)
我们需要原有结构时,就不能再使用了

传址与传值

传值和传址实际上都是拷贝复制,只是复制的效果不同

简单数据类型 - 传值
深拷贝:
复制详细的数据与内存空间,不影响被复制的数据;
针对当前对象的数据的所有引用结构都拷贝一份,数据在内存中是独立的。
若属性是引用类型,如果进行更改,不会影响拷贝的原对象属性。

    let a = 10;
    let b = a;
    b = 20;
    console.log(a)
    console.log(b)

复杂数据类型 - 传址
浅拷贝:
只是引用地址与原数据共用内存,节省内存,互相影响
只针对当前对象的属性进行拷贝,若当前对象的属性是引用类型时,这个不考虑,不进行拷贝。
若属性是引用类型,拷贝后引用的是地址,如果进行更改,会影响拷贝的原对象属性。

    let GroundPa = {
        name:"谨慎",
        age:"70"
    }    
    let Pa = GroundPa;
            
    Pa.name = "小心"
    console.log(Pa)
    console.log(GroundPa)
解决复杂数据类型浅拷贝的问题

方法一:

  • 通过JSON数据转换
    let father = {
		name:"玉",
        sex:"男",
        age:"50",
        text:undefined,
        fun:function(){
            console.log("学习,出人头地")
        }
	}
	let fa = JSON.parse(JSON.stringify(father))
    fa.name = "秦";
    console.log(father)
    console.log(fa)
  • 弊端:
    会丢失function 和 undefind的 数据

方法二:

  • 分解为 简单数据
    进行深拷贝
    返回新的对象
	function deep(obj){
		let newObj = Array.isArray(obj)?[]:{};
        //  for-in 会遍历对象和原型上 和 原型链的属性和方法
        //  但是我们作深拷贝的时候,是不需要原型或者原型链上的属性和方法的
        for(let key in obj){
            //  判断是否是对象自身的内容,如果是,才去做深拷贝
            if(obj.hasOwnProperty(key)){
            //  判断是否是对象(也就是复杂的数据类型)
				if(typeof obj[key] === "object"){
                //  如果内部依然有更深层的对象
                //  那么还需要按照原有步骤,再循环检测一遍
                     newObj[key] = deep(obj[key]);
                 }else{//   如果不是,只是简单数据类型
                     newObj[key] = obj[key]
                 }
             }
		}
        //最后,我们将检测赋值后的新对象返回,以此达成新内存的目的
        return newObj;
	}
操作符

以下面的代码为例

	function Animal(){
		this.name = "join";
	}
	Animal.prototype.sex = "男";
	Animal.prototype.eat = function(){
		console.log("我正在吃好吃的");
	}
	var animal = new Animal();
	animal.age = 19;
	animal.sex = "男";
			
	function Son(){
		Animal.call(this);
		this.a = 10;
		this.s ="s";
		this.fn= ()=>{
			console.log("我是一个孩子");
		}
	}
	Son.prototype.score = "90";
	Son.prototype.shopping = function(){
		console.log("我是来逛街的");
    }
        
    Son.prototype = deepCopy(Animal.prototype);
    Son.prototype.constructor = Son;
  • instanceof
    判断一个实例对象 是否是某个函数的实例
	// 对象名 instanceof 函数名
    var a1 = new Animal();
    var s1 = new Son();
    console.log(a1);
    console.log(s1);
    console.log(s1 instanceof Son);
	console.log(s1 instanceof Animal);
  • isPrototypeof( )
    只要是原型链中出现过的原型,都可以说是该原型链所产生的原型,返回true
	// 原型名.isPrototypeOf(对象名)
	// 会从s1开始沿着原型链逐层向上找,看看有没有一个叫Son.prototype的
	console.log(Son.prototype.isPrototypeOf(s1));
  • hasOwnProperty( )
    用来检测当前对象中是否有该属性, 返回值为布尔类型
    不会检查原型和原型链上的内容
    只会去查找构造函数中的内容
	// 对象名.hasOwnProperty("属性/方法名");
	console.log(s1.hasOwnProperty("fn"));
  • delete
    用来删除属性
    delete s1.name;
  • in
    检查该对象是否包含指定属性
    这个属性可以是对象的直接属性
    也可以是prototype继承而来的属性
    但是原型自身的属性/方法不行(原型链继承,重构原型,覆盖掉了)
    console.log("a" in s1);
	console.log("name" in s1);
	console.log("eat" in s1);
	console.log("score" in s1);
	console.log(s1.score);
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值