javascript - 在 JavaScript 中定义属性和命名约定

标签 javascript coding-style naming-conventions

我一直是一名优秀的 JavaScript 程序员并遵守 coding conventionsDouglas Crockford征募.然而,JavaScript 从那时起就不断发展,我相信命名约定现在已经过时了。

例如克罗克福德说:

Do not use _ (underbar) as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. If privacy is important, use the forms that provide private members. Avoid conventions that demonstrate a lack of competence.

但是 JavaScript 现在允许您创建不可枚举的属性。因此,在不可枚举的属性前加上下划线以表明该属性不可枚举是有意义的(至少对我而言——你可以不同意)。

为什么要这样做?

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

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

Global variables should be in all caps. (JavaScript does not have macros or constants, so there isn't much point in using all caps to signify features that JavaScript doesn't have.)

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

  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));
    };
}());

但是现在您不能轻易地使属性不可枚举不可配置不可写。因此我修改了 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 的惯例。

最佳答案

我建议不要逐字逐句地遵循 Crock 的教学。

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

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

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

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

关于javascript - 在 JavaScript 中定义属性和命名约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17359885/

相关文章:

javascript - 使用 D3.js 和 AngularJS 定制折线图

javascript - UI Bootstrap - 缺少包含实现

java - JSF 表达式语言的代码风格指南

c - c的良好OO命名方案

java - Java 包中的连字符公司名称

c# - 返回任务的命名方法的公认模式是什么?

javascript - typescript 未读取正确的类型

javascript - Backbone.js 使用 native websockets 同步

java - 异常(exception) - 我应该更喜欢日志库而不是 java.util.logging 吗?

scala - 带有大量方法链接的Scala代码的接受/推荐语法是什么?