包详细信息

sort-keys

sindresorhus50.5mMIT6.0.0

Sort the keys of an object

sort, object, keys, key

自述文件

sort-keys

Sort the keys of an object

Useful to get a deterministically ordered object, as the order of keys can vary between engines.

Install

npm install sort-keys

Usage

import sortKeys from 'sort-keys';

sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}

sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}

sortKeys({b: [{b: 0, a: 0}], a: 0}, {deep: true});
//=> {a: 0, b: [{a: 0, b: 0}]}

sortKeys({c: 0, a: 0, b: 0}, {
    compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}

sortKeys([{b: 0, a: 2}], {deep: true});
//=> [{a: 2, b: 0}]

Advanced Usage with context

The deep and ignoreKeys options can receive a context object with detailed information about the current key being processed:

// Ignore private keys only at root level
sortKeys(data, {
    ignoreKeys: ({key, depth}) => key.startsWith('_') && depth === 0
});

// Deep process only up to 3 levels, skip config paths
sortKeys(data, {
    deep: ({path, depth}) => depth < 3 && !path.includes('config')
});

// Complex path-based logic
sortKeys(data, {
    deep: ({path}) => !(path[0] === 'user' && path[1] === 'cache'),
    ignoreKeys: ({path, key}) => (path.length === 1 && path[0] === 'metadata') || key.startsWith('_')
});

API

sortKeys(object, options?)

Returns a new object with sorted keys.

Property descriptors are preserved, including accessors (get/set), and getters are not invoked or deep-processed. Circular references are supported and preserved.

object

Type: object | Array

When it's an object:

  • Only plain objects are deeply processed.
  • Only enumerable own string keys are considered; symbol and non-enumerable properties are ignored.

When it's an array:

  • Array order is unchanged; holes in sparse arrays are preserved.
  • Elements may be deep-processed if deep enables it.
  • Extra enumerable properties on arrays are ignored.

options

Type: object

compare

Type: Function

Compare function for sorting keys.

If omitted, remaining keys are sorted using the platform's default string sort.

sortKeys(object, {
    compare: (a, b) => b.localeCompare(a) // Reverse alphabetical
});
deep

Type: boolean | Function\ Default: false

Recursively sort keys, including keys of objects inside arrays.

Only plain objects are sorted; other object types are left as-is. For arrays, deep processing applies to their elements.

When a boolean:

  • true: Deep process all nested objects and arrays.
  • false: Only sort keys at the current level.

When a function, it receives a context object and should return true to enable deep processing for that specific key-value pair:

sortKeys(data, {
    deep: ({key, value, path, depth}) => {
        // Only deep process up to 2 levels
        if (depth >= 2) {
            return false;
        }

        // Skip deep processing of large arrays for performance
        if (Array.isArray(value) && value.length > 100) {
            return false;
        }

        // Skip config objects entirely
        if (path.includes('config')) {
            return false;
        }

        return true;
    }
});
ignoreKeys

Type: string[] | Function\ Default: []

Keys to ignore when sorting. Ignored keys will appear first in their original order, followed by the sorted keys. Remaining keys are sorted by compare, or by default string sort if compare is not provided.

Can be an array of key names:

sortKeys({c: 0, _private: 1, a: 0, b: 0}, {ignoreKeys: ['_private']});
//=> {_private: 1, a: 0, b: 0, c: 0}

Or a function that receives a context object:

sortKeys(data, {
    ignoreKeys: ({key, value, path, depth}) => {
        // Ignore private keys at root level
        if (key.startsWith('_') && depth === 0) {
            return true;
        }

        // Ignore metadata keys in user objects
        if (path[0] === 'user' && key === 'metadata') {
            return true;
        }

        // Ignore empty objects
        if (typeof value === 'object' && Object.keys(value).length === 0) {
            return true;
        }

        return false;
    }
});

Note: ignoreKeys only affects the ordering of object keys; it does not control deep processing, and array indices are not sorted or filtered. To prevent deep processing of specific values, use the deep function option.

Context object

When using functions for deep or ignoreKeys, they receive a context object with:

  • key (string): The current key being processed.
  • value (any): The value associated with the current key.
  • path (string[]): The full path to this key as an array of elements (for example, ['user', 'profile', 'name']). Array indices are stringified (for example, ['items', '0', 'title']).
  • depth (number): The current nesting depth (0 for root level).

Path examples

const data = {
    user: {
        profile: {
            name: 'John'
        }
    },
    items: [
        {title: 'Item 1'},
        {title: 'Item 2'}
    ]
};

// Paths generated during processing (as arrays):
// ['user'] (depth: 0)
// ['user', 'profile'] (depth: 1)
// ['user', 'profile', 'name'] (depth: 2)
// ['items'] (depth: 0)
// ['items', '0'] (depth: 1)
// ['items', '0', 'title'] (depth: 2)
// ['items', '1'] (depth: 1)
// ['items', '1', 'title'] (depth: 2)

Note: path is an array of elements with stringified array indices (for example, ['items', '0', 'title']). If your key names include dots or special characters, this representation remains unambiguous.