js中的创建对象几种方式

1.最简单的方式就是创建一个Object的实例,再为它添加属性和方法

2.使用对象字面量模式

3.工厂模式

虽然Object构造函数或对象字面量都可以创建单个对象,但是缺点很明显:使用同一个接口创建对象,会产生大量重复代码。

使用工厂模式,抽象了创建对象的具体过程,用函数来封装以特定接口创建对象的细节

工厂模式解决了创建多个相似对象的问题,但却没有解决对象识别的问题,无法知道对象的类型(我们知道person1和person2都是Object的实例,因为所有对象均继承Object,但是思考一下,person1和person2这种相同结构的对象是否可以和其他对象有所区分呢?)

4.构造函数模式

像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中,此外我们也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法

和工厂模式的createPerson对比一下:

             1.没有显示的创建对象

             2.直接把属性和方法赋给了this对象

             3.没有return语句

             4.构造函数名首字母默认大写

使用new操作符创建Person的新实例,会经历以下4个步骤(new关键字是具体如何工作,在另一篇文章中分析)

             1.创建一个新对象

             2.将构造函数的作用域赋给新对象

             3.执行构造函数中的代码(为这个新对象添加属性)

             4.返回新对象

实例的constructor属性最初是用来标识对象类型的,默认指向该对象的构造函数(constructor并不是实例的对象,而是构造函数原型对象上的,实例是通过_proto_原型链访问的,可以修改,所以不建议使用)

可以使用instanceof操作符判断更可靠一些

创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型,这就是构造函数模式胜过工厂模式的地方

而构造函数存在的主要问题,就是每个方法都要在每个实例上创建一遍,虽然名字一样,但是并不是同一个Function实例。函数也是对象,所以上面的构造函数也可以这么写

这种完成同样任务的Function实例完全没必要在实例中多次创建(new会占用堆内存),利用原型模式可以解决

5.原型模式

创建的每个函数都有一个prototype原型属性,这个属性是个指针,指向原型对象,这个原型对象可以包含由特定类型的实例共享的属性和方法。

注意这里的写法,对比一下

第一种写法我们将Person.prototype设置为等于一个以对象字面量形式创建的新对象,本质上是重写了默认的prototype对象,所以constructor属性不再指向Person构造函数了,这也是前面提到的:判断实例的类型最好不要使用constructor。那constructor会指向谁呢?测试一下发现,指向了Object构造函数

如果constructor的值很重要,可以特意设置回适当的值

原型模式中也存在一些很明显的问题:所有实例默认情况下都将取得相同的属性值,对于函数来说很合适,值类型的属性倒也可以,通过设置实例属性可以覆盖原型链上的属性,不会影响其他实例,但是引用类型的属性,就很有问题了

Person原型对象上有值类型health和引用类型friends数组,给person1实例添加health属性覆盖原型上的health后,并没有影响person2的health属性,但是当改变person1的friends后,person2的friends也发生了改变。

6.组合使用构造函数模式和原型模式

构造函数用于定义实例属性,而原型模式用于定义方法和共享属性

猜你喜欢

转载自blog.csdn.net/liu_jun_tao/article/details/81142448