我的代码中有很多函数都使用了以下结构:
options = {"param1": "yes", "param2" : "no"}
在JS中,由于它是一种动态语言,我不需要“定义”这个结构。
但是当我知道该结构有一组固定字段时,为了清晰起见,将其集中声明是否是最佳实践?同样适用于在类的本地数据成员中使用。是否最好在构造函数或其他集中方式中初始化所有这些数据成员(以便更清晰)?
我知道我可以在注释中做到这一点,但来自静态语言,我想知道JavaScript风格是什么。
我的代码中有很多函数都使用了以下结构:
options = {"param1": "yes", "param2" : "no"}
var
。 :-)如果没有,你就会陷入隐式全局变量的恐怖。)
除了清晰明了之外,没有真正的约定。对于我来说,“清晰明了”意味着以下几点:
将所有var
语句放在作用域的开头,因为它们本来就在那里。
如果某些内容具有不会经常更改的重要结构,请尽早使用对象文字(如您所做)进行分配。
但是,“清晰明了”对不同的人意味着不同的事情。
对于类中的本地数据成员的使用也是一样。在构造函数或其他集中方式中初始化所有这些属性是否是最佳实践(以便清晰明了)?
是的,在构造函数中初始化所有特定于实例的属性。对象可能不需要其自己的副本的属性可以驻留在原型上:
function Foo(bar) {
this.bar = bar;
this.baz = [];
}
Foo.prototype.datum = 42;
在这里,通过new Foo("x")
创建的对象将获得它自己的属性bar
,其值为"x"
,它自己的属性baz
,其值为[]
,以及一个继承的属性datum
,其值为42
。将这些初始化放在构造函数和其旁边的原型中有助于明确。
通常情况下,如果您使用函数定义,您可以做更多的事情,以矩形为例。
function Rectangle(width, height){
this.width = width;
this.height = height;
};
Rectangle.prototype.width = 0;
Rectangle.prototype.height = 0;
Rectangle.prototype.getArea = function(){
return this.height * this.width;
}
var rect = new Rectangle(100, 50);
console.log(rect.width);
console.log(rect.height);
console.log(rect.getArea());
采用这种方法,一些集成开发环境支持自动完成,并且您可以操作内在对象方法,例如.toString等。如果您觉得您的需求可能会扩展,最好采用这种做法,但是关于性能基准测试还不太确定,这取决于您想要采用多高的“最佳实践”。
如果你将options
作为参数传递给函数调用,通常的处理方式是让你的函数在可能的情况下拥有所有参数的默认值,然后在你想要指定选项的地方将一个对象字面量传递到函数中。
例如,如果myFunction
有选项color
、size
和material
,则分配尽可能多的默认值(例如,默认color
为red
,默认size
为large
,默认material
为cotton
)。然后当你调用myFunction()
时,除非你这样调用它,否则默认值将应用:
myFunction({color:'blue', material:'suede'});
这里唯一保留的默认值将是大小。
这就是jQuery和许多其他库处理选项的方式。
定义类的方式有很多种。
// serves as a constructor
function MyClass(name, id) {
// init members.
// this.members are public members
this.Name = name;
this.Id = id;
// this is a private member available only in constructor
var something = 0;
this.DoSomething = function () {
// your method
// here you also can use something here as you have access.
}
}
MyClass.prototype = {
// This also another way to define your methods
"SomeMethod": function (input) {
// Do something
// you don't have access to private members in constructor.
}
}
如果您需要更多的面向对象编程功能
function AnotherClass (input) {
// private field
var someNumber = 0;
// get accessor
this.getSomeNumber = function() {
return someNumber;
}
this.setSomeNumber = function(value) {
if (typeof value != "number" || value != value)
throw new Error("Your value must be a number");
someNumber = value;
}
}
var MyThirdClass = (function() {
var instanceCount = 0;
function _Constructor() {
this.Name = "";
instanceCount++;
}
_Constructor.getInstanceCount = function() {
return instanceCount;
}
return _Constructor;
})();
最后,您可以按照以下方式使用它们
var myClass = new MyClass("Foo", 1);
myClass.Name = "Bar";
myClass.DoSomething();
var thirdClass = new MyThirdClass();
var thirdClassAnotherInstance = new MyThirdClass();
alert(MyThirdClass.getInstanceCount());
这可能对你的情况来说有些过度,但如果你想的话,你可以创建一个构造函数,用于获取和设置特定的私有变量。这个特定的函数还会在设置之前检查设置的值是否为数字。
var Options = function(p1, p2){
var _param1, _param2;
this.get_param1 = function(){
return _param1;
};
this.get_param2 = function(){
return _param2;
};
this.set_param1 = function(v){
if (typeof(v) === 'number') {
_param1 = v;
return _param1;
} else {
return false;
}
};
this.set_param2 = function(v){
if (typeof(v) === 'number') {
_param2 = v;
return _param2;
} else {
return false;
}
};
this.set_param1(p1);
this.set_param2(p2);
return this;
};
使用方法如下:
var options = new Options(1, 2);
options._param1; // => undefined
options.get_param1(); // => 1
options.get_param2(); // => 2
options.set_param1(3);
options.get_param1(); // => 3
options.set_param1('fail');
options.get_param1(); // => 3
这是一个非常严格的实现,但可能是你正在寻找的。