## Heads up!

[Please update][update] to version 3.0.1 or later, a critical bug was fixed in that version.

## Usage

```js
const set = require('{%= name %}');

const obj = {};
set(obj, 'a.b.c', 'd');

console.log(obj);
//=> { a: { b: { c: 'd' } } }
```

### Params

Signature:

```js
set(object, property_path, value[, options]);
```

- `object` **{Object}**: The object to set `value` on
- `path` **{String|Symbol|Array}**: The [path](#object-paths) of the property to set.
- `value` **{any}**: The value to set on `obj[prop]`
- `options` **{Object}**: See all [available options](#options)

### Object paths

You may pass a string, symbol, or array of strings or symbols. By default, when a string is passed this library will split the string on `.` or a [custom separator](#options-separator) It's useful to pass an array


### Escaping

**Escaping with backslashes**

Prevent set-value from splitting on a dot by prefixing it with backslashes:

```js
console.log(set({}, 'a\\.b.c', 'd'));
//=> { 'a.b': { c: 'd' } }

console.log(set({}, 'a\\.b\\.c', 'd'));
//=> { 'a.b.c': 'd' }
```

## Options

### options.preservePaths

Do not split properties that include a `/`. By default, set-value assumes that properties with a `/` are not intended to be split. This option allows you to disable default behavior.

Note that this option cannot be used if `options.separator` is set to `/`.

**Type**: `boolean`

**Default**: `true`

**Example**

```js
console.log(set({}, 'https://github.com', true));
//=> { 'https://github.com': true }

console.log(set({}, 'https://github.com', true, { preservePaths: false }));
//=> { 'https://github': { com: true } }
```

### options.separator

Custom separator to use for splitting object paths.

**Type**: `string`

**Default**: `.`

**Example**

```js
console.log(set(obj, 'auth/userpass/users/bob', '*****', { separator: '/' }));
//=> { auth: { userpass: { users: { bob: '*****' } } } }
```

### options.split

Custom `.split()` function to use.


### options.merge

Allows you to update plain object values, instead of overwriting them.

**Type**: `boolean|function` - A custom `merge` function may be defined if you need to deep merge. Otherwise, when `merge` is `true`, a shallow merge will be performed by `Object.assign()`.

**Default**: `undefined`

**Example**

```js
const obj = { foo: { bar: { baz: 'qux' } } };
set(obj, 'foo.bar.fez', 'zzz', { merge: true });
//=> { foo: { bar: { baz: 'qux', fez: 'zzz' } } }
```

## Benchmarks

Benchmarks were run on a MacBook Pro 2.5 GHz Intel Core i7, 16 GB 1600 MHz DDR3.

```
{%= include("./benchmark/stats.md") %}
```

### Running the benchmarks

Clone this library into a local directory:

```sh
$ git clone https://github.com/jonschlinkert/set-value.git
```

Then install devDependencies and run benchmarks:

```sh
$ npm install && node benchmark
```

## Comparisons to other libs, or _"the list of shame"_

These are just a few of the duplicate libraries on NPM.

- [bury][] fails all of the tests. I even wrapped it to have it return the object instead of the value, but with all of that work it still fails the vast majority of tests.
- [deep-get-set][] fails 22 of 26 unit tests.
- [deep-object][] fails 25 of 26 unit tests, completely butchered given objects.
- [deep-property][] fails 17 of 26 unit tests.
- [deep-set][] fails 13 of 26 unit tests.
- [deephas][] fails 17 of 26 unit tests.
- [dot-prop][] fails 9 of 26 unit tests.
- [dot2val][] fails 17 of 26 unit tests.
- [es5-dot-prop][] fails 15 of 26 unit tests.
- [getsetdeep][] fails all unit tests due to `this` being used improperly in the methods. I was able to patch it by binding the (plain) object to the methods, but it still fails 17 of 26 unit tests.
- [lodash.set][] fails 11 of 26 unit tests.
- [object-path-set][] fails 12 of 26 unit tests.
- [object-path][] fails 16 of 26 unit tests.
- [object-set][] fails 13 of 26 unit tests.
- [set-nested-prop][] fails 24 of 26 unit tests.
- [setvalue][] (this library is almost identical to a previous version of this library)
- Many dozens of others

**Others that do the same thing, but use a completely different API**

- [deep-set-in][]
- [set-deep][]
- [set-deep-prop][]
- [bury][]
- Many dozens of others


## History

### v3.0.0

- Added support for a custom `split` function to be passed on the options.
- Removed support for splitting on brackets, since a [custom function][split-string] can be passed to do this now.

### v2.0.0

- Adds support for escaping with double or single quotes. See [escaping](#escaping) for examples.
- Will no longer split inside brackets or braces. See [bracket support](#bracket-support) for examples.

If there are any regressions please create a [bug report](../../issues/new). Thanks!
