我最近一直在深入研究JavaScript以完全理解语言,并且有一些我似乎无法找到答案的唠叨问题(特别是处理面向对象的编程)。
假设以下代码:
function TestObject()
{
this.fA = function()
{
// do stuff
}
this.fB = testB;
function testB()
{
// do stuff
}
}
TestObject.prototype = {
fC : function
{
// do stuff
}
}
函数fA
和fB
之间有什么区别?他们的范围和潜在能力是否完全相同?它只是惯例还是技术上更好或更合适的一种方式?
如果在任何给定时间只有一个对象的实例,那么为原型添加一个函数,例如fC
是否值得?这样做有什么好处吗?原型只在处理对象或继承的许多实例时才真正有用吗?
技术上什么是"适当的"以我上面的方式或每次调用TestObject.prototype.functionName = function(){}
的方式向原型添加方法的方法?
我希望尽可能保持我的JavaScript代码干净和可读,但我也非常感兴趣的是对象的正确约定在语言中。我来自Java和PHP背景,我试图不对JavaScript如何工作做任何假设,因为我知道它与基于原型的非常不同。
答案 0 :(得分:6)
函数fA和fB之间有什么区别
在实践中,没有。函数表达式(fA)和函数声明(fB)之间的主要区别在于创建函数时(声明的函数在执行任何代码之前可用,而函数表达式在表达式实际执行之前不可用)。您可能会偶然发现与function expressions相关的各种怪癖。
在这个例子中,我使用函数表达式,只是因为声明一个函数表达式,然后分配结果似乎有点抽象。但这两种方法都没有“正确”或“错误”。
如果在任何给定时间只有一个对象的实例,那么将原型中的函数添加到fC中是否值得?
没有。几乎所有继承的人都发现普通对象通常更简单,因此“更好”。原型继承对于修补内置对象非常方便(例如,在缺少的情况下添加Array.prototype.each)。
从技术上讲,将方法添加到原型中的“正确”方法是什么......
没有一个。用一些其他对象替换默认原型似乎有点浪费,但是分配由文字创建的对象可能更整洁,更容易阅读顺序分配。对于一个或两个作业,我会使用:
Constructor.prototype.method = function(){…}
但是对于很多方法我会使用对象文字。有些甚至使用经典的扩展功能,并执行:
myLib.extend(Constructor.prototype, {
method: function(){…}
});
如果已经定义了一些方法,那么这对于添加方法很有用。
看看一些图书馆并决定你喜欢什么,一些混合搭配。做任何适合特定情况的事情,通常只需要获得足够的代码就可以看起来一样,那么无论你选择什么模式,它都会看起来很整洁。
答案 1 :(得分:3)
fA
和fB
实际上是相同的,这只是一个惯例问题。
如果只有一个对象的实例,我甚至不会使用构造函数,而只是一个对象文字,例如:
var o = {
fA: function () { ... },
fB: function () { ... },
fC: function () { ... }
};
至于将它添加到实例或原型中,如果你只有一个实例,那么实例比将它添加到原型稍微更有效,但正如我所说的那样,使用文字代替。
我避免在构造函数中声明函数,因为构造函数的每次调用都会创建表示每个函数的新对象。这些对象不是很大,如果创建了很多对象,它们往往会相加。如果可以将函数移动到原型,那么这样做会更有效。
至于添加原型,我赞成
TestObject.prototype.functionName = function () { };
风格,但这是一个偏好的问题。我喜欢上述内容,因为无论是扩展原型还是创建初始原型,它看起来都是一样的。
答案 2 :(得分:0)
我回答第一部分:没有区别,当你声明函数不是变量时,它的声明在块中上升,所以
...
func();
...
function func () { ... }
等于
var func = function () { ... };
...
func();
...
所以你的代码
function TestObject () {
this.fA = function() { // do stuff };
this.fB = testB;
function testB() { // do stuff }
}
等于
function TestObject () {
var testB = function () { // do stuff };
this.fA = function () { // do stuff };
this.fB = testB;
}
答案 3 :(得分:0)
还有任何明确的JavaScript样式指南或文档 关于JavaScript如何在低级别运行?
该死的javascript程序员不应该错过"Professional JavaScript for Web Developers"。这本书很精彩,深入探讨。它解释了对象,类仿真,函数,范围等等。它也是一个JS参考。
从技术上讲,什么是添加方法的“正确”方法 原型我上面的方式或打电话 TestObject.prototype.functionName = function(){}每次?
至于定义类的方法,我建议看看各种JS MVC框架(如Spine.js,它是轻量级的)。您不需要全部,只需要类仿真库。这样做的主要原因是JS没有类的概念,而是纯粹由对象和原型组成。另一方面,可以完美地模拟类(请不要模仿,因为它是缺少的东西)。因为这需要程序员的一些规则,所以最好有一个类仿真库来完成这项工作并使代码更清晰。
程序员应该期望类仿真库的标准方法是:
// define a new Class
var AClass = Class.create({
// Object members (aka prototype),
// usually an initialize() method is called if it is defined
// as the "constructor" function when a class object is created
}, {
// Static members
});
// create a child class that inherits methods and attributes from parent
var ChildClass = AClass.extend({
// Child object members
},{
// Child static members
});
AClass.include({
// Object amendments (aka mixin), methods and attributes
// to be injected to the class object
},{
// Statics amendments, methods and attributes to be
// injected as class static members
});
// check object type
var aObj = new AClass();
aObj instanceof AClass; // true
aObj instanceof ChildClass; // false
var cObj = new ChildClass();
cObj instanceof AClass; // true
cObj instanceof ChildClass; // true