JavaScript Code Reading

The parse function parses a query string from a URL.

Here’s a quick preview of the concepts.

  • Functions
  • Objects
  • Array destructuring
function parse(query, options) {
    options = Object.assign({
        decode: true,
        sort: true,
        arrayFormat: 'none',
        arrayFormatSeparator: ',',
        parseNumbers: false,
        parseBooleans: false
    }, options);

    validateArrayFormatSeparator(options.arrayFormatSeparator);

    const formatter = parserForArrayFormat(options);

    // Create an object with no prototype
    const ret = Object.create(null);

    if (typeof query !== 'string') {
        return ret;
    }

    // Remove ? or # or & at the beginning of the string
    query = query.trim().replace(/^[?#&]/, '');

    if (!query) {
        return ret;
    }

    for (const param of query.split('&')) {
        if (param === '') {
            continue;
        }

        // make=Ford, key = make, value = Ford
        let [key, value] = splitOnFirst(options.decode ? param.replace(/\+/g, ' ') : param, '=');

        // Missing `=` should be `null`:
        // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
        value = value === undefined ? null : ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? value : decode(value, options);
        formatter(decode(key, options), value, ret);
    }

    for (const key of Object.keys(ret)) {
        const value = ret[key];
        if (typeof value === 'object' && value !== null) {
            for (const k of Object.keys(value)) {
                value[k] = parseValue(value[k], options);
            }
        } else {
            ret[key] = parseValue(value, options);
        }
    }

    if (options.sort === false) {
        return ret;
    }

    return (options.sort === true ? Object.keys(ret).sort() : Object.keys(ret).sort(options.sort)).reduce((result, key) => {
        const value = ret[key];
        if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) {
            // Sort object keys, not values
            result[key] = keysSorter(value);
        } else {
            result[key] = value;
        }

        return result;
    }, Object.create(null));
}
function parse(query, options) { ... }

The first thing we have is the function. This function is written using a function declaration. Functions written using function declarations are hoisted to the top of the file and can be used anywhere. If you created this function on line 100, you could use it on line 10 because it’s hoisted to the top. If you created this function using a variable, you wouldn’t be able to use it before it’s declared.

const parse = function (query, options) { ... }

This function has two parameters, but we don’t know what they are. They could be objects, strings, functions, numbers, or anything. One clue is the name of the variable. The name of the first parameter is query. The first parameter could be the query string from the URL. The second parameter is named options.

options = Object.assign({
    decode: true,
    sort: true,
    arrayFormat: 'none',
    arrayFormatSeparator: ',',
    parseNumbers: false,
    parseBooleans: false
}, options);

We can see the options parameter is being used in the first block of code. From this block of code, we can guess that the options parameter is an object, null, or undefined.

Object.assign({ ... }, options);

Object.assign combines two objects.

{
        decode: true,
        sort: true,
        arrayFormat: 'none',
        arrayFormatSeparator: ',',
        parseNumbers: false,
        parseBooleans: false
    }

The first object is hard coded . The second object is whatever options is. The properties in the second object will override the properties in the first object if the properties share the same name. This is a great way to have default properties.

validateArrayFormatSeparator(options.arrayFormatSeparator);

We’re calling a function named validateArrayFormatSeparator and passing it one argument. By default, we can see that options.arrayFormatSeparator is a comma. The