Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining properties and naming conventions in JavaScript

I've been a good JavaScript programmer and adhered to the coding conventions enlisted by Douglas Crockford. However JavaScript has evolved since then and I believe the naming conventions are now outdated.

For example Crockford said:

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.

However JavaScript now allows you to create non-enumerable properties. Hence it makes sense (at least to me - you're allowed to disagree) to prefix non-enumerable properties with an underbar to indicate that the property is non-enumerable.

Why should you do so?

  1. Because visual feedback is important (scroll down to the readability section in the linked article).
  2. Backwards compatibility. You can filter out properties that begin with an underbar in for in loops.

Let's take another example of what Crockford said:

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.)

As I see it there are two problems with the following convention:

  1. Most JavaScript programmers don't write global variables in all caps. It's just not natural.
  2. JavaScript now allows you to create non-writable properties. Hence it makes sense to use all caps for such properties for the same reasons as I stated above for non-enumerable properties.

All that's well and fine, but what's the real question you ask? Look at the Object.defineProperties function. The problem is that you need to supply a property descriptor for each property you want to define. This is too verbose. For instance:

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

Instead it would be much better if you could simply do:

var o = {}, x = 0;

define(o, {
    E: Math.E,
    get x() {
        return x;
    },
    set x(y) {
        x = y;
    }
});

The define function would be defined as follows:

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

However now you can't make a property non-enumerable, non-configurable or non-writable easily. Hence I modified the define function as follows:

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

Now properties beginning with an underbar are non-enumerable, properties ending with an underbar are non-configurable and data descriptor properties which don't have any lowercase alphabets are non-writable.

So my question is this - is there any way to make properties non-enumerable, non-configurable or non-writable easily while still adhering to Crockford's naming conventions? I know that my own naming conventions have more merits. However I don't want to abandon Crockford's conventions too hastily.

like image 425
Aadit M Shah Avatar asked Jun 28 '13 07:06

Aadit M Shah


People also ask

What are the naming conventions in JavaScript?

Naming ConventionsVariable and function names written as camelCase. Global variables written in UPPERCASE (We don't, but it's quite common) Constants (like PI) written in UPPERCASE.

How do you define naming conventions?

What Does Naming Convention Mean? Naming conventions are general rules applied when creating text scripts for software programming. They have many different purposes, such as adding clarity and uniformity to scripts, readability for third-party applications, and functionality in certain languages and applications.

How do you name a JavaScript function?

A JavaScript function is defined with the function keyword, followed by a name, followed by parentheses (). Function names can contain letters, digits, underscores, and dollar signs (same rules as variables). The parentheses may include parameter names separated by commas: (parameter1, parameter2, ...)


1 Answers

I would suggest not following Crock's teaching word for word.

He does have some good advice, but it's worth taking it with a grain of salt.

For example, the underscore aspect is commonly used in various JS libraries which follow a more classical OOP style of programming. It is true it does not make a function or value truely private, but it tells any users it should be treated as such - that it's not a part of the public interface - in other words, the method could disappear in the next version of the library.

The convention for naming constant-like values is also ALL_CAPS_WITH_UNDERSCORE even though JS didn't actually have constants.

In the end, many JS devs are not purely JS-only and work with other languages too. Conventions like the above should be rather obvious for people like that, and what matters in the end is what's most practical for your project.

like image 61
Jani Hartikainen Avatar answered Oct 16 '22 20:10

Jani Hartikainen