Javascript对象创建模式 js创建对象的几种方式以及区别
bigegpt 2024-10-19 02:52 76 浏览
Javascript有多种创建对象的方式,新手和老手都可能感到不知所措,不确定应该使用哪种方式。文本将介绍常见的对象常见模式和最佳的实践。
对象字面量:Object Literals
创建对象最简单的方式就是对象字面量。Javascript总是吹嘘能够“无中生有”地创建对象——不需要类、不需要模板、不需要原型——just poof!,一个有方法和数据的对象就出现了。
var o = {
x: 42,
y: 3.14,
f: function() {},
g: function() {}
};
缺点
如果需要在其他地方创建相同类型的对象,将要复制粘贴对象的方法、数据和初始化的代码,导致大量重复代码。需要一种能够批量创建同类型对象的方法,而不仅仅是一个对象。
工厂模式:Factory Functions
这是创建相同结构、接口和实现的对象最简单的方式。而不是直接创建对象字面量,而是将对象字面量作为函数的返回值。这样,如果需要多次或多个地方创建相同类型的对象时只需要调用一个函数:
function thing() {
return {
x: 42,
y: 3.14,
f: function() {},
g: function() {}
};
}
var o = thing();
缺点
这种Javascript对象创建方法可能会导致内存膨胀,因为每一个对象都包含了工厂函数的独立副本。理想情况下,我们希望每个对象只共享其功能的一个副本。
构造函数模式
可以创建特定类型的对象, 类似于Array, Date等原生JS的对象.其实现方法如下:
function Student(name,age){
this.name=name;
this.age=age;
this.myName=function(){
alert(this.name);
};
}
var student1_ = new Student('aaa',15);
var student2_ = new Student('bbb',18);
缺点
每次实例化一个对象都会把构造器里的所有方法重新创建一次,多次创建会造成内存开销增加的问题。
原型链:Prototype Chains
Javascript提供了一种内置的在对象之间共享数据的机制,称为原型链。当访问对象的属性时,它可以通过委托给其他对象来满足该请求。可以利用这一点来修改工厂函数,使它创建的每个对象只包含自己特有的数据,而对其他属性的请求则全部委托给原型链上共有的一个对象:
var thingPrototype = {
f: function() {},
g: function() {}
};
function thing() {
var o = Object.create(thingPrototype);
o.x = 42;
o.y = 3.14;
return o;
}
var o = thing();
事实上,这是一种常见的模式,语言已经内置了对它的支持。不需要创建自己的共享对象(原型对象)。相反,会自动为每个函数创建一个原型对象,可以将共享数据放在那里:
thing.prototype.f = function() {};
thing.prototype.g = function() {};
function thing() {
var o = Object.create(thing.prototype);
o.x = 42;
o.y = 3.14;
return o;
}
var o = thing();
缺点
会导致重复。上述thing函数的第一行和最后一行在每一个“委托原型的工厂函数”中都会重复一次,几乎没有区别。
ES5类:ES5 Classes
可以把那些重复的代码抽出来,放进一个自定义函数里来隔离它们。这个函数会创建一个对象,并与其他某个任意函数(参数函数)的原型建立委托(继承)关系,然后把新创建的对象作为参数,调用这个函数(参数函数),最后返回这个新的对象。
function create(fn) {
var o = Object.create(fn.prototype);
fn.call(o);
return o;
}
// ...
Thing.prototype.f = function() {};
Thing.prototype.g = function() {};
function Thing() {
this.x = 42;
this.y = 3.14;
}
var o = create(Thing);
事实上,这也是一种常见的模式,Javascript有一些内置的支持。create定义的函数实际上是new关键字的基本版本,可以直接替换create为new(构造函数+原型链):
Thing.prototype.f = function() {};
Thing.prototype.g = function() {};
function Thing() {
this.x = 42;
this.y = 3.14;
}
var o = new Thing();
在ES5中,它们是对象创建函数,它将共享数据委托给原型对象,并依赖new关键字来处理重复逻辑。
缺点
冗长和丑陋,实现继承更加冗长和丑陋。
ES6类:ES6 Classes
在ES6的类中,执行相同的操作提供了更清晰的语法:
class Thing {
constructor() {
this.x = 42;
this.y = 3.14;
}
f() {}
g() {}
}
const o = new Thing();
比较
多年以来,Javascript开发者们与原型链的关系总是若即若离,纠缠不清。而今天最有可能遇到的两种创建对象的方式,一种是强烈依赖原型链的class语法,另一种则是完全不依赖原型链的工厂函数语法。这两种风格在性能和功能上有所不同——尽管差别不太大。
性能
今天Javascript引擎已经过如此大量优化,以至于很难通过Javascript代码来推断怎样会比较快。关键在于测量方法。然而有时甚至测量都会让我们失望。通常情况下,每六周发布一次更新的Javascript引擎,有时性能会发生重大变化,我们之前进行的任何测量以及我们根据这些测量做出的任何决定都会立即出现。因此,经验法则是支持最官方和最广泛使用的语法,假设它将受到最严格的审查,并且在大多数时候是最高效的。目前来看class语法最符合这一点,class语法大约比返回字面量的工厂模式快3倍。
特点
随着ES6的发布,类与工厂模式之间曾经存在的几点差异消失了。现在,工厂模式和类都能够强制实现真正的私有数据:
- 工厂模式通过闭包实现
- 类通过weak maps实现
两者都能实现多重继承——工厂模式可以将其他属性混入自己的对象,类也可以将其他属性混入自己的原型,或者通过类工厂,通过代理也能实现。工厂函数和类也都可以在需要的时候返回任意对象,语法也都很简单。
结论
考虑到所有事情,对Javascript对象创建的偏好是使用类语法。它是标准的,它简单而干净,速度快,并且它提供了曾经只有工厂模式才能提供的所有功能
设计模式
本文转载自:https://www.doweb.me/article/146.shtml
相关推荐
- 最全的MySQL总结,助你向阿里“开炮”(面试题+笔记+思维图)
-
前言作为一名编程人员,对MySQL一定不会陌生,尤其是互联网行业,对MySQL的使用是比较多的。对于求职者来说,MySQL又是面试中一定会问到的重点,很多人拥有大厂梦,却因为MySQL败下阵来。实际上...
- Redis数据库从入门到精通(redis数据库设计)
-
目录一、常见的非关系型数据库NOSQL分类二、了解Redis三、Redis的单节点安装教程四、Redis的常用命令1、Help帮助命令2、SET命令3、过期命令4、查找键命令5、操作键命令6、GET命...
- netcore 急速接入第三方登录,不看后悔
-
新年新气象,趁着新年的喜庆,肝了十来天,终于发了第一版,希望大家喜欢。如果有不喜欢看文字的童鞋,可以直接看下面的地址体验一下:https://oauthlogin.net/前言此次带来得这个小项目是...
- 精选 30 个 C++ 面试题(含解析)(c++面试题和答案汇总)
-
大家好,我是柠檬哥,专注编程知识分享。欢迎关注@程序员柠檬橙,编程路上不迷路,私信发送以下关键字获取编程资源:发送1024打包下载10个G编程资源学习资料发送001获取阿里大神LeetCode...
- Oracle 12c系列(一)|多租户容器数据库
-
作者杨禹航出品沃趣技术Oracle12.1发布至今已有多年,但国内Oracle12C的用户并不多,随着12.2在去年的发布,选择安装Oracle12c的客户量明显增加,在接下来的几年中,Or...
- flutter系列之:UI layout简介(flutter-ui-nice)
-
简介对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了。布局的英文名叫做layout,就是用来描述如何将组件进行摆放的一个约束。在flutter中,基本上所有的对象都是wi...
- Flutter 分页功能表格控件(flutter 列表)
-
老孟导读:前2天有读者问到是否有带分页功能的表格控件,今天分页功能的表格控件详细解析来来。PaginatedDataTablePaginatedDataTable是一个带分页功能的DataTable,...
- Flutter | 使用BottomNavigationBar快速构建底部导航
-
平时我们在使用app时经常会看到底部导航栏,而在flutter中它的实现也较为简单.需要用到的组件:BottomNavigationBar导航栏的主体BottomNavigationBarI...
- Android中的数据库和本地存储在Flutter中是怎样实现的
-
如何使用SharedPreferences?在Android中,你可以使用SharedPreferencesAPI来存储少量的键值对。在Flutter中,使用Shared_Pref...
- Flet,一个Flutter应用的实用Python库!
-
▼Flet:用Python轻松构建跨平台应用!在纷繁复杂的Python框架中,Flet宛如一缕清风,为开发者带来极致的跨平台应用开发体验。它用最简单的Python代码,帮你实现移动端、桌面端...
- flutter系列之:做一个图像滤镜(flutter photo)
-
简介很多时候,我们需要一些特效功能,比如给图片做个滤镜什么的,如果是h5页面,那么我们可以很容易的通过css滤镜来实现这个功能。那么如果在flutter中,如果要实现这样的滤镜功能应该怎么处理呢?一起...
- flutter软件开发笔记20-flutter web开发
-
flutterweb开发优势比较多,采用统一的语言,就能开发不同类型的软件,在web开发中,特别是后台式软件中,相比传统的html5开发,更高效,有点像c++编程的方式,把web设计出来了。一...
- Flutter实战-请求封装(五)之设置抓包Proxy
-
用了两年的flutter,有了一些心得,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢~(原创不易,转发请标注来...
- 为什么不在 Flutter 中使用全局变量来管理状态
-
我相信没有人用全局变量来管理Flutter应用程序的状态。毫无疑问,我们的Flutter应用程序需要状态管理包或Flutter的基本小部件(例如InheritedWidget或St...
- Flutter 攻略(Dart基本数据类型,变量 整理 2)
-
代码运行从main方法开始voidmain(){print("hellodart");}变量与常量var声明变量未初始化变量为nullvarc;//未初始化print(c)...
- 一周热门
- 最近发表
-
- 最全的MySQL总结,助你向阿里“开炮”(面试题+笔记+思维图)
- Redis数据库从入门到精通(redis数据库设计)
- netcore 急速接入第三方登录,不看后悔
- 精选 30 个 C++ 面试题(含解析)(c++面试题和答案汇总)
- Oracle 12c系列(一)|多租户容器数据库
- flutter系列之:UI layout简介(flutter-ui-nice)
- Flutter 分页功能表格控件(flutter 列表)
- Flutter | 使用BottomNavigationBar快速构建底部导航
- Android中的数据库和本地存储在Flutter中是怎样实现的
- Flet,一个Flutter应用的实用Python库!
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- linux安装minio (74)
- ubuntuunzip (67)
- vscode使用技巧 (83)
- secure-file-priv (67)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)