【问题标题】:Defining properties and naming conventions in JavaScript在 JavaScript 中定义属性和命名约定
【发布时间】:2013-06-25 22:37:01
【问题描述】:

我一直是一名优秀的 JavaScript 程序员,并遵守 Douglas Crockford 所登记的 coding conventions。然而 JavaScript 从那时起已经发展,我相信命名约定现在已经过时了。

例如克罗克福德说:

不要使用_(下划线)作为名称的第一个字符。它有时用于表示隐私,但实际上并不提供隐私。如果隐私很重要,请使用提供private members 的表格。避免表现出缺乏能力的惯例。

然而,JavaScript 现在允许您创建不可枚举的属性。因此,在不可枚举的属性前面加上一个下划线来表示该属性是不可枚举的,这是有道理的(至少对我来说——你可以不同意)。

为什么要这样做?

  1. 因为visual feedback is important(向下滚动到链接文章中的可读性部分)。
  2. 向后兼容性。您可以过滤掉for in 循环中以下划线开头的属性。

让我们再举一个克罗克福德所说的例子:

全局变量应全部大写。 (JavaScript 没有宏或常量,因此使用全部大写来表示 JavaScript 没有的功能没有多大意义。)

在我看来,以下约定存在两个问题:

  1. 大多数 JavaScript 程序员不会将全局变量全部大写。这不自然。
  2. 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-enumerablenon-configurablenon-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 的约定。

【问题讨论】:

标签: javascript coding-style naming-conventions


【解决方案1】:

我建议不要一字不差地遵循 Crock 的教学。

他确实有一些很好的建议,但值得一提的是。

例如,下划线方面通常用于各种遵循更经典的 OOP 编程风格的 JS 库中。确实,它不会使函数或值真正成为私有,但它告诉任何用户它应该被视为私有 - 它不是公共接口的一部分 - 换句话说,该方法可能会在下一个版本中消失图书馆。

类似常量的值的命名约定也是ALL_CAPS_WITH_UNDERSCORE,即使 JS 实际上没有常量。

最后,许多 JS 开发人员并不是纯粹的 JS,他们也可以使用其他语言。像上面这样的约定对于这样的人来说应该是相当明显的,最终重要的是什么对你的项目最实用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 2015-05-15
    • 2015-11-21
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多