面试中你有被问到-javascript中有几种创建对象的方式吗?
Javascript中,所有事物皆为对象!布尔型,数字型,字符串,日期,数学和正则表达式,数组,函数统统都是对象。所以,学好对象,走遍天下都不怕了!
对象是一种特殊的数据,有属性和方法。通过创建对象,可以代码共享构建出形形色色的实例,从而节省我们开发的时间。那如何创建一个对象呢?有以下四种:
对象字面量(又称为直接量,原始方式)
工厂模式(利用函数创建对象)
构造函数模式(利用类创建对象)
原型模式(利用函数的prototype创建对象)
通过原型+构造函数的方式创建对象
使用 Object.create() 方法
使用 ES6 类
但不管是哪种方式,都万变不离其宗。用句大实话就是,对象就是一个大括号包裹着一些属性和一些方法的集合,无非就是是不是以函数的形式展示。
01
对象字面量
通过对象字面量创建对象有三种形式:
第一种:{}
举例:
第二种:new Object()
举例:
第三种:直接定义
举例:
这三种方式大同小异,我一般习惯用第三种方式,因为简单。
小结:
这三种方式,对象中的方法都是独立的,不能共享。如果创建多个对象,代码冗余现象非常严重。
02
工厂模式
工厂模式是以函数的形式创建对象。
举例:
这种方式其实就是第一种方式加了一层函数的外壳,外加了一些参数,使其可以批量创建对象。无疑,这种方式可以减少代码的冗余。但是这不是完美的,还有一个问题:age这个变量,其实应该是Number类型,如果我不看源码,我是不知道的,在传参的时可能会因随心所欲而出问题。
有没有发现,per1.dreams和per2.dreams,是不相等的,意味着什么?意味着这个方法是不共享的,相同的方法会开辟不同的空间,会浪费空间。
小结:
代码冗余现象有所缓解;
对象属性类型未知,需要看源码;
对象的方法是独立的,不能共享。
TIPS:
“ 工厂模式一定不要忘记最后要把对象return出去!”
03
构造函数模式
构造函数一种特殊的函数,其名称的首字母是大写的,而普通函数名称的首字母小写。与第2种方式的区别就是,不用首先创建一个空对象,往空对象中添加属性和方法,最后再return出去。构造函数里的属性的前缀全部用this代替。this指向的是创建出来的实例。创建对象用new...。
举例:
new在执行时会完成以下四件事:
开辟新的空间存储当时对象;
构造函数中的this指向当前对象;
执行构造函数中的代码,为当前对象添加属性和方法;
返回新对象(所以构造函数中不需要return对象)
小结:
per1和per2同属于同一个constructor;
构造函数里的方法是独立于每个对象的,所以构造函数里的方法不能共享。
相同的方法开辟不同的空间,会造成资源的浪费。
04
原型模式
在讲这种模式前需回顾一下原型链的知识。
每个函数都有一个prototype属性,这个属性指向函数的原型对象;
每个原型都有一个constructor属性,指向关联的构造函数;
_Proto _是每一个子对象(除null外)都会有的一个属性,指向该对象的原型

从上图可以看出来,Person.prototype相当于一个全局对象,只不过这个对象有些特殊,它是与构造函数相关联的。per1以及所有Person的实例都可以继承实例原型的属性或者说,都可以顺着_Proto _这个属性找到实例原型的属性和方法。
举例:
小结:
一眼就看出来的缺点嘛!虽然方法可以共享,但是属性没有灵活性。一旦任何一个实例改变一个属性,所有实例的值都会改变,不符合预期。
05
原型+构造函数模式
顾名思义,这种模式结合了原型和构造函数。构造函数里添加属性,利用原型的原理,在原型里添加方法,使其能共享方法。
举例:
小结:
确实是一个完美的解决方案,既解决了代码的冗余现象可以批量创建对象,又可以共享方法!赞👍!
06
Object.create()方法
Object.create()方法,是JavaScript内置 Object 对象的标准方法。通过Object.create()创建的对象是全局对象Object的实例。这个是对第1种方式的一个拓展。
比如想创建的对象2与之前创建过的对象1的结构等很相似,只是某些属性有些不同,那么对象2就可以以对象1为原型创建对象。
举例:
在控制台,我们可以看到:

为什么console.logg(per1)时,只能看到name的值?因为per1是基于person为原型创建的,其它没有变化的属性必然在其原型链上:

所以能输出per1.sex的属性。:)
小结:
方法是可以共享的噢!
07
ES6类
ES6引入了一种创建JavaScript对象的新语法-class语法。class主法没有给JavaScript添加新的逻辑,本质上是一种语法糖。但体感很好。
举例:
小结:
与传统的构造函数创建的对象一样,per1和per2就是Person的实例,方法并不是共享的。