至简·new关键字

对象实例化是一条必经之路,不然对象 怎么出生,难道他们是从石头缝里蹦出来的吗?
而且它们又不能像现实生物一样papapa…

每种编程语言都有自己实例化对象的方式,js也不例外,基本有下面几种方式。

  • Object.create(null | object | obj.prototype),它的参数可以直接为一个对象,也可以是原型对象,也可以为空。
  • 字面量 就是 var obj = { prop:’’, … method:function(){},… }
  • new关键字,通过new关键配合构造函数

还有工厂模式等,都是大同小异,其实严格来讲,js创建对象的方式就是第一种方式今天的重点不在这里,今天我们要说说new这个关键字。
创建对象是使用new关键字到底干了个什么事呢?这是一个问题

直接上代码:

function ARobot(){
		this.num = 1;
		this.say = function(){
			console.log("我是A类机器人");
		}
	}

	function BRobot(){
		this.num2 = 2;
		this.say2 = function(){
			console.log("我是B类机器人")
		}
	}

	BRobot.prototype = new ARobot();
	BRobot.prototype.num = 3;
	BRobot.prototype.say = function(){
		console.log("我是C类机器人");
	}


	var obj = new BRobot();
	console.log(obj.num);
	obj.say();

如果你知道答案,那基本上可以不用看了。
如果不知道,那还是看看吧

答案:
在这里插入图片描述


不绕弯了,直接说原理吧; 当代码执行到 new BRobot()时,发生了几件事:

1. var obj = Object.create(BRobot.prototype);
2.将构造函数内部的this也指向obj 如果BRobot()有参数,传入参数,构造函数执行。
3. 如果构造函数返回了一个对象,那么new出来的结果就是这个对象。如果构造函数没有返回值,或者返回了一个非对象的值,那么new的结果就是obj对象。通常来说构造函数没有返回值,除非是要覆盖当前正在创建的对象。


OK,来分析分析上面的代码吧。

  1. 首先,我们定义了两个构造函数他们分别负责制造A类机器人和B类机器人,一个ARobot,一个是BRobot,并且它们各自有着各自的属性和方法,睁大眼看仔细,他们属性和方法是不同名的哦。

  2. 然后,我们在实例化对象之前,先做了些小动作。
    来看看这三句:
    BRobot.prototype = new ARobot();
    BRobot.prototype.num = 3;
    BRobot.prototype.say = function(){
    console.log(“我是C类机器人”);
    }
    第一句,用new实例化了一个ARobot()作为BRobot的原型,根据我们之前所说的new所做的事,它将得到一个实例化的ARobot对象,这个对象将替换掉BRobot原来的原型,然后对替换后BRobot的原型修改了num属性和say方法…。

  3. 最后我们重新生产(new)了一个BRobot,然后打印了他的num属性,以及执行了say方法。因为在第2步中,B类型的原型已经被修改,而且值得注意的是,B类型之前是没有sum属性的,也没有say方法(我说过的看仔细哦,看清他们的属性名和方法名,是不同的,emmm…坑B)。
    这里就考察到this了,我们说过new的第二步就是将构造函数中的this指向当前new的对象,会发生什么事呢,在我们对 对象内部的成员进行修改时,this就是指带当前的对象,那么问题来了…当前obj有num2属性和say2方法吗?看清吧…haha,没有,所以当前的obj会怎么办——顺着自己的原型链向上查找,结果发现原型BRobot.prototype上有,那么就会使用,所以最终结果才会是
    在这里插入图片描述
    好了,我做一次修改,就是将BRobot构造函数的num属性和say方法改成与ARobot相同的名字

function BRobot(){
		this.num = 2;
		this.say = function(){
			console.log("我是B类机器人")
		}
	}

结果将会是什么呢?
结果:
在这里插入图片描述
你会发现即使我们对BRobot的原型做了修改也没改变实例化的结果,为什么呢,这也是this的功劳,因为我们修改后,实例化的obj对象,在new操作的第二步中,构造函数内的this指向obj,构造函数本身是有num属性和say方法的所以从第一步创建的对象,会在第二步中被当前构造函数内的属性和方法重新赋值,而原型链上的属性依然是原型链的,并且也已被修改,但是没什么卵用。就如同泥人,先用一个模子固个大体,不同之处再通过构造函数去完成,完成后的泥人有自己的特征,而模子上也有自己的特征。
在这里插入图片描述
可以看到原型已经被修改成了ARobot,并且其内部属性和方法也被修改了。
好了new关键字,就说到这里。

补充:说一说new关键字与字面量声明对象的区别。
先看一个结果:
在这里插入图片描述在这里插入图片描述
可以看到两种创建对象方式所耗的时间不相同,而且差别较大。
为什么会这样,
字面量形式创建对象,强调的是创建对象一个可变的哈希映射
而使用new创建对象,是要调用对应的构造函数,其中存在一个过程,即调用对应名称的构造函数,作用域解析,ESC的入栈出栈。并且还有可能存在类型判断,如果有Object的参数存在,会依据参数进行类型判断,然后根据对应类型,委派内部对应的构造函数,去创建对象。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值