Javascript对象定义技术,优缺点
Javascript object definition techniques, pros and cons
在Javascript中定义可重用对象的基本方法是什么?我说可重用以排除单例技术,例如直接用对象文字表示法声明变量。我在某个地方看到克罗克福德在他的书中定义了四种这样的方式,但我宁愿不必为了这一点信息而买一本书。
以下是我熟悉的方法:
-
使用
this
,并用new
构建(我认为这被称为经典?)function Foo() { var private = 3; this.add = function(bar) { return private + bar; } } var myFoo = new Foo();
-
使用原型,类似
function Foo() { var private = 3; } Foo.prototype.add = function(bar) { /* can't access private, correct? */ }
-
返回文字,不使用
this
或new
function Foo() { var private = 3; var add = function(bar) { return private + bar; } return { add: add }; } var myFoo = Foo();
我能想到相对较小的变化,这些变化可能在任何重大方面都无关紧要。我缺少什么款式?更重要的是,每种方法的优缺点是什么?有没有推荐的方法可以坚持,或者这是一个偏好和圣战的问题?
使用原型。从构造函数返回特定对象会使它们成为非构造函数,而将方法分配给this
会使继承变得不那么方便。
返回对象文字
优点:
-
如果一个人忘记了
new
,他们仍然会得到这个对象。 -
您可以创建真正的私有变量,因为在构造函数中定义的对象的所有方法都共享其作用域。
缺点:
- 它不是一个真正的构造函数。向其原型中添加某些内容不会更改返回的对象,
new
或不更改new
。CCD_ 9也会产生CCD_
使用prototype
优点:
-
你让构造函数保持整洁。
-
这是JavaScript中的标准方法,所有内置构造函数都将其方法放在原型上。
-
继承变得更容易、更正确;您可以(也应该)使用
Object.create(ParentConstructor.prototype)
而不是new ParentConstructor()
,然后从Constructor
中调用ParentConstructor
。如果你想覆盖一个方法,你可以在原型上完成。 -
您可以在创建对象之后对其进行"修改"。
-
您可以扩展您无法访问的构造函数的原型。
缺点:
-
它可能会变得有点过于冗长,如果你想更改函数的名称,你也必须更改添加到原型中的所有函数。(要么这样,要么将原型定义为一个具有
constructor
兼容属性描述符的大对象文字。) -
它们不共享特定于实例的作用域,因此不能真正拥有私有变量。
在构造函数中分配给this.*
优点:
- 您可以使用闭包,从而使用私有成员变量
缺点:
- 没有鸭子打字;不能用任何旧对象直接从原型调用方法。例如,
Array.prototype.slice.call(collectionLikeObject)
这主要是一个偏好问题。做鸡汤没有一种方法,统一的物体也是一样的。
我不使用这3个,尽管它们都有自己的用途。我使用了一个名为Object:deploy的自定义函数,并像这样使用它。。
var a = { hey: 'hello' },
b = {}.deploy(a);
console.log(b.hey); // 'hello'
使用prototype
对大多数人来说是最好的,因为它是自动滴液的。
function A() {};
A.prototype.hello = "Hey";
var a = new A();
console.log(a.hello); // 'Hey'
A.prototype.hello = "Hello";
console.log(a.hello); // 'Hello'
与流行的观点相反,您可以在prototype
中使用私有变量。
function Hello() {};
(function () {
var greeting = "Hello";
Hello.prototype.greet = function () { return greeting };
}).apply(this);
但即使这是可能的,通常还是做得更好。
function Hello() {};
Hello.prototype.greeting = "Hello";
Hello.prototype.greet = function () { return this.greeting };
第二种方法(原型)与Python等其他语言中的标准类更相似,因为您有一个通用的"原型"对象,所有实例都共享该对象。比较第一种和第二种方法:
- 在方法1中,每次调用"
new Foo()
"时,都会创建一个全新的对象并插入所有方法。这不是很节省时间或空间,因为每个Foo实例都有自己的所有方法表。您可以通过创建两个Foo对象并询问foo1.add == foo2.add
(false)来测试这一点。方法3与此非常相似;我不确定方法1和方法3之间的语义差异(如果有的话)是什么 - 在方法2中,您设置了一个包含所有方法的共享原型对象。如果你问
foo1.add == foo2.add
,你就会明白。这更节省空间和时间。它还允许您在创建实例后向原型中添加更多方法,他们将看到新方法
正如您所说,方法2的问题在于您无法访问私人成员。但是您仍然可以向对象本身添加非私有成员,并使用原型方法访问这些成员:
function Foo() {
this.private = 3;
}
Foo.prototype.add = function(bar) { return this.private + bar }
需要注意的是,foo.private
在外部可见。
原型没有每个对象实例的开销,只有add函数的每个类的开销。这就是我不喜欢另外两种方法的原因。
不要忘记继承。总有一天你会需要的。对于组织继承,最好的方法是组合技术:
function Foo() {
this.array = [1, 2, 3];
this.add = function(bar) { return private + bar; }
}
Foo.prototype.add = function(bar) { }
var myFoo = new Foo();
在构造函数中设置字段有助于避免子对象修改字段。将方法设置为原型比每次在构造函数中这样做更快。
- 用于发现哪个JS/jQuery脚本正在冻结页面的工具或技术
- JavaScript运行时事件循环现有技术
- Ajax登录技术(后端php)
- 什么'这是谷歌分析跟踪代码使用的技术
- 从技术上讲,是否可以在不拥有页面UI的情况下删除页面UI的某些部分
- 主元素属性?(或技术)
- 技术测试HTML中非常奇怪的名称属性
- 最好的技术自上而下RPG风格的网格滚动
- AngularJS可以在没有任何服务器端技术的情况下将文件保存/写入服务器
- 制定基本日期(技术)
- java脚本:交换技术,添加随机文本
- 搜索引擎可爬网应用程序的EmberJS技术堆栈
- window.postMessage与ajax的优缺点
- 在 Web 浏览器中优先下载图像的技术
- 如何选择由 DevExpress constrols 使用 Javascript DOM 技术自动生成的 html “i
- 流星技术/模式,用于等待数据库变量更改,然后在 in 之后执行某些操作
- 最安全的javascript JSON内联技术
- 用JavaScript加密字符串,用RSA技术用PHP解密
- 从服务器和/或客户端加载动态元素的典型技术是什么
- Javascript对象定义技术,优缺点