js对象的创建对象模式和继承模式(上)---构建对象模式

简介: js对象的创建对象模式和继承模式(上)---构建对象模式

前言

      ECMAScript与其他面向对象语言不同的是,它没有类的概念,因此它的对象也和基于类的语言中的对象有所不同,深入理解js的对象是每个前端工程师的基本素养,本文将就创建对象模式的方面对对象进行介绍


正文

      我们可以通过Object构造函数或对象字面量构建对象,但是使用同一个接口创建很多对象时候,会产生大量重复代码,下面将介绍解决这个问题的各种模式


工厂模式

      其实就是用函数来封装创建对象的细节来实现复用,但这样不能直接获得对象的类型

640.png

构造函数模式

      自定义构造函数来定义一个类型的自定义对象类型的属性和方法来实现定义的复用

640.png

       构造函数模式和工厂模式还是有着很大的区别的:

  • 没有显式地创建对象
  • 直接将属性和方法赋值给了this对象,这个this对象对指向新创建的对象
  • 没有return实例

      构造函数与其他函数不同的是,它的调用需要用过new操作符,如果不使用New操作符,则this会指向window对象640.png


      构造函数虽然好用,但是有个比较大的缺点,会将每个方法都在实例上重复创建。事实上,创建多个完成同个任务的Function实例是没有必要的,所以我建议大家将函数的定义转移到函数外面来解决这个问题

640.png


原型模式

      我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,原型是什么,这里我就不再复述了,不懂的同学可以Bing或者谷歌,或者查看我后面写的关于原型的博客章节

像之前的写法一样,通过原型把创建对象的操作封装在函数中就是原型模式

640.png

   特别的是,通过这种方法创建的新的对象,在修改属性的过程中,只会修改到实例的属性,而不会影响到原型

640.png

      当然,这种最初始的写法是不优雅的,在上面的例子中每为Person创建一个属性,就需要写一次Person.prototype,产生了大量的不必要输入,常见的写法可以用一个包含所有属性和方法的字面量去重写prototype

640.png

     这里要注意constructor属性,在默认情况下,所有原型对象都会自动获取一个constructor属性,这个属性是一个指向prototype属性所在函数的指针。如果在重写prototype的过程中忘记对constructor属性赋值,就没办法再通过constructor确认对象那个的类型

640.png

      可以看到在原型忘记赋值constructor以后,Person定义的对象与Person之间的连接就断开了,没办法再用instanceof获取到他们的关系

      同时由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能立刻从实例上反映出来–即使是先创建640.png了实例后修改原型也照样如此。


      可以看到即使在per创建之后再修改原型,仍然会影响到per,这就是原型的动态性,原型的获取是一次搜索,而不是静态的,会随时变化

      但是对原型的重写就不一样了,要注意的是,原型修改为另一个对象就等于切断了构造函数与最初原型的联系,实例中的指针只指向原型,不指向构造函数

640.png

      可以看到重写以后,Person指向的原型就不再是最初的原型,而per对象也不会再指向Person的原型,重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系,它们引用的仍然是最初的原型

      原型模式省略了构造函数传递初始化参数的环节,有一个致命的问题,引用对象的属性会被所有实例共享

640.png

      可以看到对per1的friends修改会共享给per2,因为数组的修改并不会修改它的别人对它的引用,所以在原型上修改,意味着所有的对象都会共享这个对象的修改


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

      之前介绍了工厂模式,构造函数模式和原型模式,都有它们的优势和缺陷,那么这里将介绍目前在ECMAScript使用最广泛,认同度最高的一种创建自定义类型的方法

      构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。这样一来,每个实例都会有自己的一份实例属性的副本,但是同时又共享着对方法的引用,最大限度地节省了内存。

640.png

       这样避免了构造函数方法需要创建多个重复Function实例的问题,又可以避免原型模式导致的非共享的引用属性共享给所有对象的问题


ES6 类

      ES6中引用了类的对象,后面我会在专门的章节介绍ES6中类的部分,所以这里卖个关子,感兴趣的同学可以看我后面关于ES6类的介绍


小结

      1、构造函数模式定义的类型的方法会因为this的关系导致不同的作用域链和标识符解析,所以即使是一样机制的同名函数却不相等

      2、原型模式定义的引用类型的属性会在所有的对象中共享

      3、构造函数适合定义实例属性,而原型模式适合定义方法和需要共享的属性,结合使用是认同度最高的写法

      小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!

目录
相关文章
|
6天前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可以是任意类型且有序,与对象的字符串或符号键不同;Set存储唯一值,无重复。两者皆可迭代,支持for...of循环。Map有get、set、has、delete等方法,Set有add、delete、has方法。示例展示了Map和Set的基本操作。
18 3
|
19天前
|
前端开发 JavaScript
使用JavaScript实现复杂功能:构建一个自定义的拖拽功能
使用JavaScript实现复杂功能:构建一个自定义的拖拽功能
|
19天前
|
JavaScript
JS 获取对象数据类型的键值对的键与值
JS 获取对象数据类型的键值对的键与值
|
29天前
|
JavaScript 前端开发
Math对象:JavaScript中的数学工具
Math对象:JavaScript中的数学工具
27 1
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(三)
深入JS面向对象(原型-继承)
30 0
|
22天前
|
JavaScript 算法
原生JS完成“一对一、一对多”矩形DIV碰撞检测、碰撞检查,通过计算接触面积(重叠覆盖面积)大小来判断接触对象DOM
原生JS完成“一对一、一对多”矩形DIV碰撞检测、碰撞检查,通过计算接触面积(重叠覆盖面积)大小来判断接触对象DOM
|
1天前
|
JavaScript 前端开发
JavaScript DOM 文档对象模型(获取、改变html元素)
JavaScript DOM 文档对象模型(获取、改变html元素)
|
8天前
|
JavaScript 前端开发 开发者
JavaScript中的错误处理:try-catch语句与错误对象
【4月更文挑战第22天】JavaScript中的错误处理通过try-catch语句和错误对象实现。try块包含可能抛出异常的代码,catch块捕获并处理错误,finally块则无论是否出错都会执行。错误对象提供关于错误的详细信息,如类型、消息和堆栈。常见的错误类型包括RangeError、ReferenceError等。最佳实践包括及时捕获错误、提供有用信息、不忽略错误、利用堆栈信息和避免在finally块中抛错。
|
12天前
|
JavaScript 前端开发
JavaScript BOM 浏览器对象模型
JavaScript BOM 浏览器对象模型
|
12天前
|
JavaScript 前端开发 API
JavaScript DOM 文档对象模型
JavaScript DOM 文档对象模型