在Javascript中创建对象的方法有很多种,新手和老手都可能会感到不知所措,不确定使用哪种方法。本文将介绍通用对象的通用模式和最佳实践。
对象字面量:Object Literals对象文字:对象文字
创建对象最简单的方法是对象文字。Javascript总是吹嘘能够无中生有地创建对象——没有类,没有模板,没有原型——噗!,将出现一个包含方法和数据的对象。
var o = { x: 42, y: 3.14, f: function() {}, g: function() {}};
劣势
如果需要在别处创建同类型的对象,那么对象的方法、数据、初始化代码都会被***粘贴,产生大量的重复代码。需要一种方法,能够批量创建相同类型的对象,而不仅仅是一个对象。
工厂模式:工厂功能
这是创建具有相同结构、接口和实现的对象的最简单方法。对象文字被用作函数的返回值,而不是直接创建对象文字。这样,如果需要多次或多处创建同一类型的对象,只需要调用一个函数:
function thing() { return { x: 42, y: 3.14, f: function() {}, g: function() {} };}var o = thing();
劣势
这种Javascript对象创建方法可能会导致内存膨胀,因为每个对象都包含工厂函数的独立副本。理想情况下,我们希望每个对象只共享其功能的一个副本。
构造函数模式
您可以创建特定类型的对象,类似于本地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);
劣势
每次实例化一个对象,都会重新创建构造函数中的所有方法,这样会增加内存开销。
原型链:原型链
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类
您可以提取这些重复的代码,并将它们放入自定义函数中以隔离它们。这个函数会创建一个对象,并与其他某个任意函数(参数函数)的原型建立委托(继承)关系,然后用新创建的对象作为参数调用这个函数(参数函数),最后返回这个新对象。
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类
在ES6类中,执行相同的操作会提供更清晰的语法:
class Thing { constructor() { this.x = 42; this.y = 3.14; } f() {} g() {}}const o = new Thing();
比较
多年来,Javascript开发者和prototype chain的关系一直是密不可分,纠缠不清的。如今,创建对象有两种方式,一种是强烈依赖原型链的类语法,另一种是完全不依赖原型链的工厂函数语法。这两种风格在性能和功能上是不同的——尽管差别不是太大。
表演
如今,Javascript引擎已经优化了很多,很难通过Javascript代码来推断它有多快。关键在于测量方法。然而,有时即使是测量也会让我们失望。通常每六周发布一个更新的Javascript引擎,有时性能会有显著变化。我们之前所做的任何测量以及基于这些测量所做的任何决定都会立即显示出来。因此,经验法则是支持最官方和最广泛使用的语法,假设它将受到最严格的审查,并且在大多数时候是最高效的。目前,类语法是最好的,它比返回文字量的工厂模式快3倍左右。
特性
随着ES6的发布,类和工厂模式之间的一些差异已经消失了。现在,工厂模式和类都可以实施真正的私有数据:
工厂模式通过闭包实现类通过weak ***ps实现
两者都可以实现多重继承——工厂模式可以将其他属性混合到自己的对象中,类也可以将其他属性混合到自己的原型中,或者通过类工厂和代理。工厂函数和类也可以在需要时返回任意对象,语法很简单。
结论
总的来说,Javascript对象创建的首选是使用类语法。它是标准的、简单的、干净的、快速的,并且它提供了曾经只有工厂模式才能提供的所有功能。
本文来自水中明月投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/602612.html