js到底new了点啥
在最开始学习js的时候,我看书上写着,创建一个数组,一个对象通常使用new,如下:
1 var arr=new Array(),//arr=[] 2 obj=new Object();//obj={}
到了后来,我们开始进行面向对象的学习的时候就开始遇到下面的代码:
1 function Qwe(id) { 2 this.id = id; 3 } 4 Qwe.prototype.name = 'qwe'; 5 Qwe.prototype.age=18; 6 var asd = new Qwe(2);
有一点基础的同学就可以得知我们按照Qwe的样子制作了一个asd,并且给了他一个独一无二的id为2。在这简单的几个代码中,我们就完成了对一个数组或者对象的创建,而new究竟在其中做了点啥呢?
根据英语的字面意思翻译,new的意思是新的,也就是说创建arr,并且给arr赋值为新的数组(obj同理)。其实不然,我们在new的过程中只是模仿一个模子(Array也好,Object也罢)新建了一个对象,并且继承了我们所使用的模子的一些方法和内容。
1 function Qwe(id) { 2 this.id = id; 3 } 4 Qwe.prototype.name = 'qwe'; 5 Qwe.prototype.age=18; 6 var asd = new Qwe(2); 7 8 asd.id//2 9 asd.name//'qwe' 10 asd.age//18
就拿上面的asd来说,它的id是构造函数Qwe设置的,除此之外所有的属性和方法都是继承自Qwe的原型对象——prototype属性。
如果你上面的没看懂,那我就用通俗的语言来讲解一下。
高中的时候其实很学渣,渣到上课天天玩手机(至于后来奋发图强混进一本院校是后话),当时玩了一款qq家园里面叫《江湖ol》的游戏。当时我玩的那个区是五区,仗着网速好手机好在那个区也算是排行榜前几的玩家。当时情人节搞活动,抽奖送坐骑情情兔,现在看来只不过是一堆可能有规律的乱码而已。因为时间过去很久了,我也无法完全想起所有,大概就是:
情情兔 编号:00001 速度:50 防御:37 敏捷:21 攻击力:37 生命值:500
因为我获得的是当时的全区第一个情情兔,所以我的编号是00001。用现在的眼光来看,无非是以下的样子:
情情兔 = { 编号: 00001, 速度速度: 50, 防御: 37, 敏捷: 21, 攻击力: 37, 生命值: 500, }
当我后来研究我和我朋友的装备的时候,我发现我的天字一号马和朋友的天字n号马的属性居然只有编号的差别!!!那么,无良的同行在制作这个坐骑的时候大概就是改一下编号吧:
1 var 情情兔数组=[];//安置情情兔坐骑 2 for(var i=0;i<1000;i++){ 3 var 情情兔 ; 4 情情兔 = { 5 编号: i,//差别在此 6 速度速度: 50, 7 防御: 37, 8 敏捷: 21, 9 攻击力: 37, 10 生命值: 500, 11 } 12 情情兔数组.push(情情兔); 13 } 14 加载生产(情情兔数组);//制作了大批量的有编号的情情
但是问题是,在这个伪代码中,我们要重复创建1000次的情情兔,然后给它赋值的对象值的属性仅仅有一个是不同的,这样就造成了一定意义上的浪费。作为一个勤(lan)奋(duo)的程序员,这种问题我们应为这样去做:
1 var 情情兔数组=[];//安置情情兔坐骑 2 for(var i=0;i<1000;i++){ 3 var 情情兔 ; 4 情情兔=new 情情兔模板(i); 5 情情兔数组.push(情情兔); 6 } 7 加载生产(情情兔数组);//制作了大批量的有编号的情情
因此,我们可以先创造一个坐骑原型——情情兔模板,在这个里面的prototype呢我们放置所有相同数值的属性为新创建的对象提供可以继承属性的路径或者说目标。我们用new来实现一下:
function 情情兔模板(id){
this.id=id
}
情情兔模板.prototype.速度=50
情情兔模板.prototype.防御=37
情情兔模板.prototype敏捷=21
情情兔模板.prototype攻击力=37
情情兔模板.prototype生命值=500
var 情情兔1=new 情情兔模板(1)
//情情兔1={编号:1,速度速度:50,防御:37,敏捷:21,攻击力:37,生命值:500}
OK,一个简单的情情兔模板就诞生了。
但是到了这里,有的同学就要问了,既然是下面都是属性,那么为什么不直接就写一个LoveRabbit.prototype={速度速度=50,防御=37,敏捷=21,攻击力=37,生命值=500}呢?其实当我们打印很多对象或者别的东西的prototype时候,会发现有一个叫做constructor的属性,字面翻译的意思就是构造函数,这个属性的值呢就是new后面的字样,也就是说,其实我们看到的种种都是一个构造函数,毕竟在js的世界中,后缀是()的大部分都是一个运行的函数。
那么我们就可以猜测了:在这个函数中,一开始呢我们肯定会创建一个新的对象,对象没有prototype属性,只有函数有prototype属性。每个对象的__proto__属性指向自身构造函数的prototype,也就是我们把新制造的对象的__proto__赋值为构造函数的prototype。当然呢,我们会给这个对象新加别的属性。
因此,在上一步的情情兔模板的new的函数中,其实应该是这样的:
function 情情兔模板(id){ var 新情情兔 = {} 新情情兔 .__proto__ = 情情兔模板.prototy'pe 新情情兔 .id= id return 新情情兔 } 情情兔模板.prototype = {
constructor:情情兔模板,//非常重要的一条,因为我们要知道构造函数,也就是来源。
速度速度:50,
防御:37,
敏捷:21,
攻击力:37,
生命值:500
}
在上面我们可以看出区别,new在这个构造函数中做了啥呢:
1.首先,先创建了一个新的对象。
2.然后呢,把构造函数的公共的属性复制了一份给这个新对象,这也就是prototype——原型。
4.接着把私有属性赋赋值,毕竟创建就要造个独一无二的。
3.返回这个新的对象。
在es6中,我们引入了class类这个概念,上面的代码我们可以写为:
1 class 情情兔模型 { 2 constructor(id) { 3 this.编号 = id; 4 this.速度=50; 5 this.防御=37; 6 this.敏捷=21; 7 this.攻击力=37; 8 this.生命值=500; 9 } 10 } 11 var 情情兔=new 情情兔模型(1)
其实,class也是一个语法糖,里面有一个构造函数constructor,原理上是和es5的类似的。
终于,我们就可以愉快地通过new来大批量的创建各种新的对象了。
由此观之,new就是一个语法糖,为了更好地节省代码,来体现程序员的聪(lan)明(duo)。
如果您觉得我的博文有用,请不要吝啬您的赞和关注。如需转载,请标明出处,谢谢。