README.md (6827B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # Copy 22 23 > Copy or deep clone a value to an arbitrary depth. 24 25 <section class="usage"> 26 27 ## Usage 28 29 ```javascript 30 var copy = require( '@stdlib/utils/copy' ); 31 ``` 32 33 #### copy( value\[, level] ) 34 35 Copy or deep clone an input `value` to an arbitrary depth. The function accepts both `objects` and `primitives`. 36 37 ```javascript 38 // Primitives... 39 var out = copy( 'beep' ); 40 // returns 'beep' 41 42 // Objects... 43 var value = [ 44 { 45 'a': 1, 46 'b': true, 47 'c': [ 1, 2, 3 ] 48 } 49 ]; 50 out = copy( value ); 51 // returns [ { 'a': 1, 'b': true, 'c': [ 1, 2, 3 ] } ] 52 53 var bool = ( value[0].c === out[0].c ); 54 // returns false 55 56 // Error object... 57 var err1 = new TypeError( 'beep' ); 58 59 var err2 = copy( err1 ); 60 // returns <TypeError> 61 ``` 62 63 The default behavior returns a **full** deep copy of any `object`. To limit the copy depth, set the `level` option. 64 65 ```javascript 66 var value = [ 67 { 68 'a': 1, 69 'b': true, 70 'c': [ 1, 2, 3 ] 71 } 72 ]; 73 74 // Trivial case => return the same reference 75 var out = copy( value, 0 ); 76 // returns [ { 'a': 1, 'b': true, 'c': [ 1, 2, 3 ] } ] 77 78 var bool = ( value[0] === out[0] ); 79 // returns true 80 81 // Shallow copy: 82 out = copy( value, 1 ); 83 84 bool = ( value === out ); 85 // returns false 86 87 bool = ( value[0] === out[0] ); 88 // returns true 89 90 // Deep copy: 91 out = copy( value, 2 ); 92 93 bool = ( value[0] === out[0] ); 94 // returns false 95 96 bool = ( value[0].c === out[0].c ); 97 // returns true 98 ``` 99 100 </section> 101 102 <!-- /.usage --> 103 104 <section class="notes"> 105 106 ## Notes 107 108 - List of **supported** values/types: 109 110 - `undefined` 111 - `null` 112 - `boolean`/`Boolean` 113 - `string`/`String` 114 - `number`/`Number` 115 - `function` 116 - `Object` 117 - `Date` 118 - `RegExp` 119 - `Set` 120 - `Map` 121 - [`Error`][mdn-error] 122 - [`URIError`][mdn-uri-error] 123 - [`ReferenceError`][mdn-reference-error] 124 - [`SyntaxError`][mdn-syntax-error] 125 - [`RangeError`][mdn-range-error] 126 - [`EvalError`][mdn-eval-error] 127 - [`TypeError`][mdn-type-error] 128 - [`System Error`][node-system-error] (Node.js) 129 - `Array` 130 - `Int8Array` 131 - `Uint8Array` 132 - `Uint8ClampedArray` 133 - `Init16Array` 134 - `Uint16Array` 135 - `Int32Array` 136 - `Uint32Array` 137 - `Float32Array` 138 - `Float64Array` 139 - `Buffer` ([Node.js][node-buffer]) 140 141 - List of **unsupported** values/types: 142 143 - `DOMElement`: to copy DOM elements, use `element.cloneNode()`. 144 - `Symbol` 145 - `WeakMap` 146 - `WeakSet` 147 - `Blob` 148 - `File` 149 - `FileList` 150 - `ImageData` 151 - `ImageBitmap` 152 - `ArrayBuffer` 153 154 - The implementation **can** handle circular references. 155 156 - If a `Number`, `String`, or `Boolean` object is encountered, the value is cloned as a **primitive**. This behavior is intentional. The implementation is opinionated in wanting to **avoid** creating `numbers`, `strings`, and `booleans` via the `new` operator and a constructor. 157 158 - For `objects`, the implementation **only** copies `enumerable` keys and their associated property descriptors. 159 160 - The implementation **only** checks whether basic `Objects`, `Arrays`, and class instances are `extensible`, `sealed`, and/or `frozen`. 161 162 - `functions` are **not** cloned; their reference is copied. 163 164 - The implementation supports custom [`error`][mdn-error] types which are [`Error`][mdn-error] instances (e.g., ES2015 subclasses). 165 166 - Support for copying class instances is inherently **fragile**. Any instances with privileged access to variables (e.g., within closures) cannot be cloned. This stated, basic copying of class instances is supported. Provided an environment which supports ES5, the implementation is greedy and performs a deep clone of any arbitrary class instance and its properties. The implementation assumes that the concept of `level` applies only to the class instance reference, but not to its internal state. 167 168 <!-- eslint-disable no-underscore-dangle --> 169 170 ```javascript 171 function Foo() { 172 this._data = [ 1, 2, 3, 4 ]; 173 this._name = 'bar'; 174 return this; 175 } 176 177 var foo1 = new Foo(); 178 var foo2 = copy( foo1 ); 179 180 var bool = ( foo1._name === foo2._name ); 181 // returns true 182 183 bool = ( foo1._data === foo2._data ); 184 // returns false 185 186 bool = ( foo1._data[0] === foo2._data[0] ); 187 // returns true 188 ``` 189 190 </section> 191 192 <!-- /.notes --> 193 194 <section class="examples"> 195 196 ## Examples 197 198 <!-- eslint no-undef: "error" --> 199 200 ```javascript 201 var randu = require( '@stdlib/random/base/randu' ); 202 var Int32Array = require( '@stdlib/array/int32' ); 203 var copy = require( '@stdlib/utils/copy' ); 204 205 var arr = [ 206 { 207 'x': new Date(), 208 'y': [ randu(), randu() ], 209 'z': new Int32Array( [ 1, 2, 3, 4 ] ), 210 'label': 'Beep' 211 }, 212 { 213 'x': new Date(), 214 'y': [ randu(), randu() ], 215 'z': new Int32Array( [ 3, 1, 2, 4 ] ), 216 'label': 'Boop' 217 } 218 ]; 219 220 // Perform a full deep copy: 221 var out = copy( arr ); 222 223 var bool = ( arr[ 0 ] === out[ 0 ] ); 224 // returns false 225 226 bool = ( arr[ 1 ].y === out[ 1 ].y ); 227 // returns false 228 229 // Perform a shallow copy: 230 out = copy( arr, 1 ); 231 232 bool = ( arr[ 0 ] === out[ 0 ] ); 233 // returns true 234 235 bool = ( arr[ 1 ].z === out[ 1 ].z ); 236 // returns true 237 ``` 238 239 </section> 240 241 <!-- /.examples --> 242 243 <section class="links"> 244 245 [mdn-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error 246 247 [mdn-type-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError 248 249 [mdn-syntax-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError 250 251 [mdn-range-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError 252 253 [mdn-reference-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError 254 255 [mdn-uri-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError 256 257 [mdn-eval-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError 258 259 [node-system-error]: https://nodejs.org/api/errors.html#errors_class_system_error 260 261 [node-buffer]: http://nodejs.org/api/buffer.html 262 263 </section> 264 265 <!-- /.links -->