我一直是一名优秀的 JavaScript 程序员,并遵守Douglas Crockford制定的编码约定。然而 JavaScript 从那时起已经发展,我相信命名约定现在已经过时了。
例如,克罗克福德说:
不要使用
_
(下划线)作为名称的第一个字符。它有时用于表示隐私,但实际上并不提供隐私。如果隐私很重要,请使用提供私人成员的表格。避免表现出缺乏能力的惯例。
然而,JavaScript 现在允许您创建不可枚举的属性。因此,在不可枚举的属性前面加上一个下划线来表示该属性是不可枚举的,这是有道理的(至少对我来说——你可以不同意)。
为什么要这样做?
- 因为视觉反馈很重要(向下滚动到链接文章中的可读性部分)。
- 向后兼容性。
for in
您可以过滤掉循环中以下划线开头的属性。
让我们再举一个克罗克福德所说的例子:
全局变量应全部大写。(JavaScript 没有宏或常量,所以使用全部大写来表示 JavaScript 没有的特性没有多大意义。)
在我看来,以下约定存在两个问题:
- 大多数 JavaScript 程序员不会全部大写全局变量。这不自然。
- JavaScript 现在允许您创建不可写的属性。因此,出于与上述不可枚举属性相同的原因,对此类属性使用所有大写字母是有意义的。
这一切都很好,但你问的真正问题是什么?看Object.defineProperties
功能。问题是您需要为要定义的每个属性提供属性描述符。这太冗长了。例如:
var o = {}, x = 0;
Object.defineProperties(o, {
E: {
value: Math.E,
enumerable: true,
configurable: true
}
x: {
enumerable: true,
configurable: true,
get: function () {
return x;
},
set: function (y) {
x = y;
}
}
});
相反,如果您可以简单地执行以下操作会更好:
var o = {}, x = 0;
define(o, {
E: Math.E,
get x() {
return x;
},
set x(y) {
x = y;
}
});
该define
函数将定义如下:
var define = (function () {
var defineProperty = Object.defineProperty;
var has = Function.call.bind(Object.hasOwnProperty);
var getDescriptorOf = Object.getOwnPropertyDescriptor;
return function (obj, props) {
for (var key in props)
if (has(props, key))
defineProperty(obj, key,
getDescriptorOf(props, key));
};
}());
non-enumerable
但是,现在您无法non-configurable
或non-writable
轻松地创建属性。因此,我将define
函数修改如下:
var define = (function () {
var defineProperty = Object.defineProperty;
var has = Function.call.bind(Object.hasOwnProperty);
var getDescriptorOf = Object.getOwnPropertyDescriptor;
return function (obj, props) {
for (var key in props) {
if (has(props, key)) {
var descriptor = getDescriptorOf(props, key);
if (key.charAt(0) === "_")
descriptor.enumerable = false;
if (key.charAt(key.length - 1) === "_")
descriptor.configurable = false;
if (has(descriptor, "value") && key === key.toUpperCase())
descriptor.writable = false;
defineProperty(obj, key, descriptor);
}
}
};
}());
现在以下划线开头的属性是不可枚举的,以下划线结尾的属性是不可配置的,并且没有任何小写字母的数据描述符属性是不可写的。
所以我的问题是——有没有办法让属性变得不可枚举、不可配置或不可写,同时仍然遵守 Crockford 的命名约定?我知道我自己的命名约定有更多优点。但是我不想太仓促地放弃 Crockford 的约定。