Back to Underscore

underscore-esm.js

docs/underscore-esm.html

1.13.866.7 KB
Original Source

underscore-esm.js

Underscore.js 1.13.8
https://underscorejs.org
(c) 2009-2026 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
Underscore may be freely distributed under the MIT license.

Current version.

varVERSION='1.13.8';

Establish the root object, window (self) in the browser, global on the server, or this in some virtual machines. We use self instead of window for WebWorker support.

varroot = (typeofself =='object'&& self.self=== self && self) ||
          (typeofglobal=='object'&&global.global===global&&global) ||Function('return this')() ||
          {};

Save bytes in the minified (but not gzipped) version:

varArrayProto=Array.prototype,ObjProto=Object.prototype;varSymbolProto=typeofSymbol!=='undefined'?Symbol.prototype:null;

Create quick reference variables for speed access to core prototypes.

varpush =ArrayProto.push,
    slice =ArrayProto.slice,
    toString =ObjProto.toString,
    hasOwnProperty =ObjProto.hasOwnProperty;

Modern feature detection.

varsupportsArrayBuffer =typeofArrayBuffer!=='undefined',
    supportsDataView =typeofDataView!=='undefined';

All ECMAScript 5+ native function implementations that we hope to use are declared here.

varnativeIsArray =Array.isArray,
    nativeKeys =Object.keys,
    nativeCreate =Object.create,
    nativeIsView = supportsArrayBuffer &&ArrayBuffer.isView;

Create references to these builtin functions because we override them.

var_isNaN =isNaN,
    _isFinite =isFinite;

Keys in IE < 9 that won’t be iterated by for key in ... and thus missed.

varhasEnumBug = !{toString:null}.propertyIsEnumerable('toString');varnonEnumerableProps = ['valueOf','isPrototypeOf','toString','propertyIsEnumerable','hasOwnProperty','toLocaleString'];

The largest integer that can be represented exactly.

varMAX\_ARRAY\_INDEX=Math.pow(2,53) -1;

Some functions take a variable number of arguments, or a few expected arguments at the beginning and then a variable number of values to operate on. This helper accumulates all remaining arguments past the function’s argument length (or an explicit startIndex), into an array that becomes the last argument. Similar to ES6’s “rest parameter”.

functionrestArguments(func, startIndex) {
  startIndex = startIndex ==null? func.length-1: +startIndex;returnfunction() {varlength =Math.max(arguments.length- startIndex,0),
        rest =Array(length),
        index =0;for(; index < length; index++) {
      rest[index] =arguments[index + startIndex];
    }switch(startIndex) {case0:returnfunc.call(this, rest);case1:returnfunc.call(this,arguments[0], rest);case2:returnfunc.call(this,arguments[0],arguments[1], rest);
    }varargs =Array(startIndex +1);for(index =0; index < startIndex; index++) {
      args[index] =arguments[index];
    }
    args[startIndex] = rest;returnfunc.apply(this, args);
  };
}

Is a given variable an object?

functionisObject(obj) {vartype =typeofobj;returntype ==='function'|| (type ==='object'&& !!obj);
}

Is a given value equal to null?

functionisNull(obj) {returnobj ===null;
}

Is a given variable undefined?

functionisUndefined(obj) {returnobj ===void0;
}

Is a given value a boolean?

functionisBoolean(obj) {returnobj ===true|| obj ===false|| toString.call(obj) ==='[object Boolean]';
}

Is a given value a DOM element?

functionisElement(obj) {return!!(obj && obj.nodeType===1);
}

Internal function for creating a toString-based type tester.

functiontagTester(name) {vartag ='[object '+ name +']';returnfunction(obj) {returntoString.call(obj) === tag;
  };
}varisString =tagTester('String');varisNumber =tagTester('Number');varisDate =tagTester('Date');varisRegExp =tagTester('RegExp');varisError =tagTester('Error');varisSymbol =tagTester('Symbol');varisArrayBuffer =tagTester('ArrayBuffer');varisFunction =tagTester('Function');

Optimize isFunction if appropriate. Work around some typeof bugs in old v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).

varnodelist = root.document&& root.document.childNodes;if(typeof/./ !='function'&&typeofInt8Array!='object'&&typeofnodelist !='function') {
  isFunction =function(obj) {returntypeofobj =='function'||false;
  };
}varisFunction$1= isFunction;varhasObjectTag =tagTester('Object');

In IE 10 - Edge 13, DataView has string tag '[object Object]'. In IE 11, the most common among them, this problem also applies to Map, WeakMap and Set. Also, there are cases where an application can override the native DataView object, in cases like that we can’t use the constructor safely and should just rely on alternate DataView checks

varhasDataViewBug = (
      supportsDataView && (!/\[native code\]/.test(String(DataView)) ||hasObjectTag(newDataView(newArrayBuffer(8))))
    ),
    isIE11 = (typeofMap!=='undefined'&&hasObjectTag(newMap));varisDataView =tagTester('DataView');

In IE 10 - Edge 13, we need a different heuristic to determine whether an object is a DataView. Also, in cases where the native DataView is overridden we can’t rely on the tag itself.

functionalternateIsDataView(obj) {returnobj !=null&&isFunction$1(obj.getInt8) &&isArrayBuffer(obj.buffer);
}varisDataView$1= (hasDataViewBug ? alternateIsDataView : isDataView);

Is a given value an array? Delegates to ECMA5’s native Array.isArray.

varisArray = nativeIsArray ||tagTester('Array');

Internal function to check whether key is an own property name of obj.

functionhas$1(obj, key) {returnobj !=null&& hasOwnProperty.call(obj, key);
}varisArguments =tagTester('Arguments');

Define a fallback version of the method in browsers (ahem, IE < 9), where there isn’t any inspectable “Arguments” type.

(function() {if(!isArguments(arguments)) {
    isArguments =function(obj) {returnhas$1(obj,'callee');
    };
  }
}());varisArguments$1= isArguments;

Is a given object a finite number?

functionisFinite$1(obj) {return!isSymbol(obj) &&\_isFinite(obj) && !isNaN(parseFloat(obj));
}

Is the given value NaN?

functionisNaN$1(obj) {returnisNumber(obj) &&\_isNaN(obj);
}

Predicate-generating function. Often useful outside of Underscore.

functionconstant(value) {returnfunction() {returnvalue;
  };
}

Common internal logic for isArrayLike and isBufferLike.

functioncreateSizePropertyCheck(getSizeProperty) {returnfunction(collection) {varsizeProperty =getSizeProperty(collection);returntypeofsizeProperty =='number'&& sizeProperty >=0&& sizeProperty <=MAX\_ARRAY\_INDEX;
  }
}

Internal helper to generate a function to obtain property key from obj.

functionshallowProperty(key) {returnfunction(obj) {returnobj ==null?void0: obj[key];
  };
}

Internal helper to obtain the byteLength property of an object.

vargetByteLength =shallowProperty('byteLength');

Internal helper to determine whether we should spend extensive checks against ArrayBuffer et al.

varisBufferLike =createSizePropertyCheck(getByteLength);

Is a given value a typed array?

vartypedArrayPattern =/\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;functionisTypedArray(obj) {

ArrayBuffer.isView is the most future-proof, so use it when available. Otherwise, fall back on the above regular expression.

returnnativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) :isBufferLike(obj) && typedArrayPattern.test(toString.call(obj));
}varisTypedArray$1= supportsArrayBuffer ? isTypedArray :constant(false);

Internal helper to obtain the length property of an object.

vargetLength =shallowProperty('length');

Internal helper to create a simple lookup structure. collectNonEnumProps used to depend on _.contains, but this led to circular imports. emulatedSet is a one-off solution that only works for arrays of strings.

functionemulatedSet(keys) {varhash = {};for(varl = keys.length, i =0; i < l; ++i) hash[keys[i]] =true;return{contains:function(key) {returnhash[key] ===true; },push:function(key) {
      hash[key] =true;returnkeys.push(key);
    }
  };
}

Internal helper. Checks keys for the presence of keys in IE < 9 that won’t be iterated by for key in ... and thus missed. Extends keys in place if needed.

functioncollectNonEnumProps(obj, keys) {
  keys =emulatedSet(keys);varnonEnumIdx = nonEnumerableProps.length;varconstructor = obj.constructor;varproto = (isFunction$1(constructor) && constructor.prototype) ||ObjProto;

Constructor is a special case.

varprop ='constructor';if(has$1(obj, prop) && !keys.contains(prop)) keys.push(prop);while(nonEnumIdx--) {
    prop = nonEnumerableProps[nonEnumIdx];if(propinobj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
      keys.push(prop);
    }
  }
}

Retrieve the names of an object’s own properties. Delegates to ECMAScript 5 ‘s native Object.keys.

functionkeys(obj) {if(!isObject(obj))return[];if(nativeKeys)returnnativeKeys(obj);varkeys = [];for(varkeyinobj)if(has$1(obj, key)) keys.push(key);

Ahem, IE < 9.

if(hasEnumBug)collectNonEnumProps(obj, keys);returnkeys;
}

Is a given array, string, or object empty? An “empty” object has no enumerable own-properties.

functionisEmpty(obj) {if(obj ==null)returntrue;

Skip the more expensive toString-based type checks if obj has no .length.

varlength =getLength(obj);if(typeoflength =='number'&& (isArray(obj) ||isString(obj) ||isArguments$1(obj)
  ))returnlength ===0;returngetLength(keys(obj)) ===0;
}

Returns whether an object has a given set of key:value pairs.

functionisMatch(object, attrs) {var_keys =keys(attrs), length = _keys.length;if(object ==null)return!length;varobj =Object(object);for(vari =0; i < length; i++) {varkey = _keys[i];if(attrs[key] !== obj[key] || !(keyinobj))returnfalse;
  }returntrue;
}

If Underscore is called as a function, it returns a wrapped object that can be used OO-style. This wrapper holds altered versions of all functions added through _.mixin. Wrapped objects may be chained.

function\_$1(obj) {if(objinstanceof_$1)returnobj;if(!(thisinstanceof_$1))returnnew\_$1(obj);this.\_wrapped= obj;
}

_$1.VERSION=VERSION;

Extracts the result from a wrapped and chained object.

_$1.prototype.value=function() {returnthis.\_wrapped;
};

Provide unwrapping proxies for some methods used in engine operations such as arithmetic and JSON stringification.

_$1.prototype.valueOf= _$1.prototype.toJSON= _$1.prototype.value;

_$1.prototype.toString=function() {returnString(this.\_wrapped);
};

Internal function to wrap or shallow-copy an ArrayBuffer, typed array or DataView to a new view, reusing the buffer.

functiontoBufferView(bufferSource) {returnnewUint8Array(
    bufferSource.buffer|| bufferSource,
    bufferSource.byteOffset||0,getByteLength(bufferSource)
  );
}

We use this string twice, so give it a name for minification.

vartagDataView ='[object DataView]';

Perform a deep comparison to check if two objects are equal.

functionisEqual(a, b) {

Keep track of which pairs of values need to be compared. We will be trampolining on this stack instead of using function recursion. (CVE-2026-27601)

vartodo = [{a: a,b: b}];

Initializing stacks of traversed objects for cycle detection.

varaStack = [], bStack = [];

Keep traversing pairs until there is nothing left to compare.

while(todo.length) {varframe = todo.pop();

As a special case, a single true on the todo means that we can unwind the cycle detection stacks.

if(frame ===true) {

Remove the first object from the stack of traversed objects.

aStack.pop();
      bStack.pop();continue;
    }
    a = frame.a;
    b = frame.b;

Identical objects are equal. 0 === -0, but they aren’t identical. See the Harmony egal proposal.

if(a === b) {if(a !==0||1/ a ===1/ b)continue;returnfalse;
    }

null or undefined only equal to itself (strict comparison).

if(a ==null|| b ==null)returnfalse;

NaNs are equivalent, but non-reflexive.

if(a !== a) {if(b !== b)continue;returnfalse;
    }

Exhaust primitive checks

vartype =typeofa;if(type !=='function'&& type !=='object'&&typeofb !='object')returnfalse;

Unwrap any wrapped objects.

if(ainstanceof_$1) a = a.\_wrapped;if(binstanceof_$1) b = b.\_wrapped;

Compare [[Class]] names.

varclassName = toString.call(a);if(className !== toString.call(b))returnfalse;

Work around a bug in IE 10 - Edge 13.

if(hasDataViewBug && className =='[object Object]'&&isDataView$1(a)) {if(!isDataView$1(b))returnfalse;
      className = tagDataView;
    }switch(className) {

These types are compared by value.

case'[object RegExp]':

RegExps are coerced to strings for comparison (Note: ‘’ + /a/i === ‘/a/i’)

case'[object String]':

Primitives and their corresponding object wrappers are equivalent; thus, "5" is equivalent to new String("5").

if(''+ a ===''+ b)continue;returnfalse;case'[object Number]':
      todo.push({a: +a,b: +b});continue;case'[object Date]':case'[object Boolean]':

Coerce dates and booleans to numeric primitive values. Dates are compared by their millisecond representations. Note that invalid dates with millisecond representations of NaN are not equivalent.

if(+a === +b)continue;returnfalse;case'[object Symbol]':if(SymbolProto.valueOf.call(a) ===SymbolProto.valueOf.call(b))continue;returnfalse;case'[object ArrayBuffer]':casetagDataView:

Coerce to typed array so we can fall through.

todo.push({a:toBufferView(a),b:toBufferView(b)});continue;
    }varareArrays = className ==='[object Array]';if(!areArrays &&isTypedArray$1(a)) {varbyteLength =getByteLength(a);if(byteLength !==getByteLength(b))returnfalse;if(a.buffer=== b.buffer&& a.byteOffset=== b.byteOffset)continue;
      areArrays =true;
    }if(!areArrays) {if(typeofa !='object'||typeofb !='object')returnfalse;

Objects with different constructors are not equivalent, but Objects or Arrays from different frames are.

varaCtor = a.constructor, bCtor = b.constructor;if(aCtor !== bCtor && !(isFunction$1(aCtor) && aCtorinstanceofaCtor &&isFunction$1(bCtor) && bCtorinstanceofbCtor)
          && ('constructor'ina &&'constructor'inb)) {returnfalse;
      }
    }

Assume equality for cyclic structures. The algorithm for detecting cyclic structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.

varlength = aStack.length;while(length--) {

Linear search. Performance is inversely proportional to the number of unique nested structures.

if(aStack[length] === a) {

Cycle detected. Break out of the inner loop and continue the outer loop. Step 1:

if(bStack[length] === b)break;returnfalse;
      }
    }

Step 2, use length to verify whether we detected a cycle:

if(length >=0)continue;

Add the first object to the stack of traversed objects.

aStack.push(a);
    bStack.push(b);

Remember to remove them again after the recursion below.

todo.push(true);

Recursively compare objects and arrays.

if(areArrays) {

Compare array lengths to determine if a deep comparison is necessary.

length = a.length;if(length !== b.length)returnfalse;

Deep compare the contents, ignoring non-numeric properties.

while(length--) {
        todo.push({a: a[length],b: b[length]});
      }
    }else{

Deep compare objects.

var_keys =keys(a), key;
      length = _keys.length;

Ensure that both objects contain the same number of properties before comparing deep equality.

if(keys(b).length!== length)returnfalse;while(length--) {

Deep compare each member

key = _keys[length];if(!has$1(b, key))returnfalse;
        todo.push({a: a[key],b: b[key]});
      }
    }
  }

We made it to the end and found no differences.

returntrue;
}

Retrieve all the enumerable property names of an object.

functionallKeys(obj) {if(!isObject(obj))return[];varkeys = [];for(varkeyinobj) keys.push(key);

Ahem, IE < 9.

if(hasEnumBug)collectNonEnumProps(obj, keys);returnkeys;
}

Since the regular Object.prototype.toString type tests don’t work for some types in IE 11, we use a fingerprinting heuristic instead, based on the methods. It’s not great, but it’s the best we got. The fingerprint method lists are defined below.

functionie11fingerprint(methods) {varlength =getLength(methods);returnfunction(obj) {if(obj ==null)returnfalse;

Map, WeakMap and Set have no enumerable keys.

varkeys =allKeys(obj);if(getLength(keys))returnfalse;for(vari =0; i < length; i++) {if(!isFunction$1(obj[methods[i]]))returnfalse;
    }

If we are testing against WeakMap, we need to ensure that obj doesn’t have a forEach method in order to distinguish it from a regular Map.

returnmethods !== weakMapMethods || !isFunction$1(obj[forEachName]);
  };
}

In the interest of compact minification, we write each string in the fingerprints only once.

varforEachName ='forEach',
    hasName ='has',
    commonInit = ['clear','delete'],
    mapTail = ['get', hasName,'set'];

Map, WeakMap and Set each have slightly different combinations of the above sublists.

varmapMethods = commonInit.concat(forEachName, mapTail),
    weakMapMethods = commonInit.concat(mapTail),
    setMethods = ['add'].concat(commonInit, forEachName, hasName);varisMap = isIE11 ?ie11fingerprint(mapMethods) :tagTester('Map');varisWeakMap = isIE11 ?ie11fingerprint(weakMapMethods) :tagTester('WeakMap');varisSet = isIE11 ?ie11fingerprint(setMethods) :tagTester('Set');varisWeakSet =tagTester('WeakSet');

Retrieve the values of an object’s properties.

functionvalues(obj) {var_keys =keys(obj);varlength = _keys.length;varvalues =Array(length);for(vari =0; i < length; i++) {
    values[i] = obj[_keys[i]];
  }returnvalues;
}

Convert an object into a list of [key, value] pairs. The opposite of _.object with one argument.

functionpairs(obj) {var_keys =keys(obj);varlength = _keys.length;varpairs =Array(length);for(vari =0; i < length; i++) {
    pairs[i] = [_keys[i], obj[_keys[i]]];
  }returnpairs;
}

Invert the keys and values of an object. The values must be serializable.

functioninvert(obj) {varresult = {};var_keys =keys(obj);for(vari =0, length = _keys.length; i < length; i++) {
    result[obj[_keys[i]]] = _keys[i];
  }returnresult;
}

Return a sorted list of the function names available on the object.

functionfunctions(obj) {varnames = [];for(varkeyinobj) {if(isFunction$1(obj[key])) names.push(key);
  }returnnames.sort();
}

An internal function for creating assigner functions.

functioncreateAssigner(keysFunc, defaults) {returnfunction(obj) {varlength =arguments.length;if(defaults) obj =Object(obj);if(length <2|| obj ==null)returnobj;for(varindex =1; index < length; index++) {varsource =arguments[index],
          keys =keysFunc(source),
          l = keys.length;for(vari =0; i < l; i++) {varkey = keys[i];if(!defaults || obj[key] ===void0) obj[key] = source[key];
      }
    }returnobj;
  };
}

Extend a given object with all the properties in passed-in object(s).

varextend =createAssigner(allKeys);

Assigns a given object with all the own properties in the passed-in object(s). (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)

varextendOwn =createAssigner(keys);

Fill in a given object with default properties.

vardefaults =createAssigner(allKeys,true);

Create a naked function reference for surrogate-prototype-swapping.

functionctor() {returnfunction(){};
}

An internal function for creating a new object that inherits from another.

functionbaseCreate(prototype) {if(!isObject(prototype))return{};if(nativeCreate)returnnativeCreate(prototype);varCtor=ctor();Ctor.prototype= prototype;varresult =newCtor;Ctor.prototype=null;returnresult;
}

Creates an object that inherits from the given prototype object. If additional properties are provided then they will be added to the created object.

functioncreate(prototype, props) {varresult =baseCreate(prototype);if(props)extendOwn(result, props);returnresult;
}

Create a (shallow-cloned) duplicate of an object.

functionclone(obj) {if(!isObject(obj))returnobj;returnisArray(obj) ? obj.slice() :extend({}, obj);
}

Invokes interceptor with the obj and then returns obj. The primary purpose of this method is to “tap into” a method chain, in order to perform operations on intermediate results within the chain.

functiontap(obj, interceptor) {interceptor(obj);returnobj;
}

Normalize a (deep) property path to array. Like _.iteratee, this function can be customized.

functiontoPath$1(path) {returnisArray(path) ? path : [path];
}
_$1.toPath = toPath$1;

Internal wrapper for _.toPath to enable minification. Similar to cb for _.iteratee.

functiontoPath(path) {return_$1.toPath(path);
}

Internal function to obtain a nested property in obj along path.

functiondeepGet(obj, path) {varlength = path.length;for(vari =0; i < length; i++) {if(obj ==null)returnvoid0;
    obj = obj[path[i]];
  }returnlength ? obj :void0;
}

Get the value of the (deep) property on path from object. If any property in path does not exist or if the value is undefined, return defaultValue instead. The path is normalized through _.toPath.

functionget(object, path, defaultValue) {varvalue =deepGet(object,toPath(path));returnisUndefined(value) ? defaultValue : value;
}

Shortcut function for checking if an object has a given property directly on itself (in other words, not on a prototype). Unlike the internal has function, this public version can also traverse nested properties.

functionhas(obj, path) {
  path =toPath(path);varlength = path.length;for(vari =0; i < length; i++) {varkey = path[i];if(!has$1(obj, key))returnfalse;
    obj = obj[key];
  }return!!length;
}

Keep the identity function around for default iteratees.

functionidentity(value) {returnvalue;
}

Returns a predicate for checking whether an object has a given set of key:value pairs.

functionmatcher(attrs) {
  attrs =extendOwn({}, attrs);returnfunction(obj) {returnisMatch(obj, attrs);
  };
}

Creates a function that, when passed an object, will traverse that object’s properties down the given path, specified as an array of keys or indices.

functionproperty(path) {
  path =toPath(path);returnfunction(obj) {returndeepGet(obj, path);
  };
}

Internal function that returns an efficient (for current engines) version of the passed-in callback, to be repeatedly applied in other Underscore functions.

functionoptimizeCb(func, context, argCount) {if(context ===void0)returnfunc;switch(argCount ==null?3: argCount) {case1:returnfunction(value) {returnfunc.call(context, value);
    };

The 2-argument case is omitted because we’re not using it.

case3:returnfunction(value, index, collection) {returnfunc.call(context, value, index, collection);
    };case4:returnfunction(accumulator, value, index, collection) {returnfunc.call(context, accumulator, value, index, collection);
    };
  }returnfunction() {returnfunc.apply(context,arguments);
  };
}

An internal function to generate callbacks that can be applied to each element in a collection, returning the desired result — either _.identity, an arbitrary callback, a property matcher, or a property accessor.

functionbaseIteratee(value, context, argCount) {if(value ==null)returnidentity;if(isFunction$1(value))returnoptimizeCb(value, context, argCount);if(isObject(value) && !isArray(value))returnmatcher(value);returnproperty(value);
}

External wrapper for our callback generator. Users may customize _.iteratee if they want additional predicate/iteratee shorthand styles. This abstraction hides the internal-only argCount argument.

functioniteratee(value, context) {returnbaseIteratee(value, context,Infinity);
}
_$1.iteratee = iteratee;

The function we call internally to generate a callback. It invokes _.iteratee if overridden, otherwise baseIteratee.

functioncb(value, context, argCount) {if(_$1.iteratee !== iteratee)return_$1.iteratee(value, context);returnbaseIteratee(value, context, argCount);
}

Returns the results of applying the iteratee to each element of obj. In contrast to _.map it returns an object.

functionmapObject(obj, iteratee, context) {
  iteratee =cb(iteratee, context);var_keys =keys(obj),
      length = _keys.length,
      results = {};for(varindex =0; index < length; index++) {varcurrentKey = _keys[index];
    results[currentKey] =iteratee(obj[currentKey], currentKey, obj);
  }returnresults;
}

Predicate-generating function. Often useful outside of Underscore.

functionnoop(){}

Generates a function for a given object that returns a given property.

functionpropertyOf(obj) {if(obj ==null)returnnoop;returnfunction(path) {returnget(obj, path);
  };
}

Run a function n times.

functiontimes(n, iteratee, context) {varaccum =Array(Math.max(0, n));
  iteratee =optimizeCb(iteratee, context,1);for(vari =0; i < n; i++) accum[i] =iteratee(i);returnaccum;
}

Return a random integer between min and max (inclusive).

functionrandom(min, max) {if(max ==null) {
    max = min;
    min =0;
  }returnmin +Math.floor(Math.random() * (max - min +1));
}

A (possibly faster) way to get the current timestamp as an integer.

varnow =Date.now||function() {returnnewDate().getTime();
};

Internal helper to generate functions for escaping and unescaping strings to/from HTML interpolation.

functioncreateEscaper(map) {varescaper =function(match) {returnmap[match];
  };

Regexes for identifying a key that needs to be escaped.

varsource ='(?:'+keys(map).join('|') +')';vartestRegexp =RegExp(source);varreplaceRegexp =RegExp(source,'g');returnfunction(string) {
    string = string ==null?'':''+ string;returntestRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
  };
}

Internal list of HTML entities for escaping.

varescapeMap = {'&':'&amp;','\<':'&lt;','\>':'&gt;','"':'&quot;',"'":'&#x27;','`':'&#x60;'};

Function for escaping strings to HTML interpolation.

var_escape =createEscaper(escapeMap);

Internal list of HTML entities for unescaping.

varunescapeMap =invert(escapeMap);

Function for unescaping strings from HTML interpolation.

var_unescape =createEscaper(unescapeMap);

By default, Underscore uses ERB-style template delimiters. Change the following template settings to use alternative delimiters.

vartemplateSettings = _$1.templateSettings = {evaluate:/\<%([\s\S]+?)%\>/g,interpolate:/\<%=([\s\S]+?)%\>/g,escape:/\<%-([\s\S]+?)%\>/g};

When customizing _.templateSettings, if you don’t want to define an interpolation, evaluation or escaping regex, we need one that is guaranteed not to match.

varnoMatch =/(.)^/;

Certain characters need to be escaped so that they can be put into a string literal.

varescapes = {"'":"'",'\\':'\\','\r':'r','\n':'n','\u2028':'u2028','\u2029':'u2029'};varescapeRegExp =/\\|'|\r|\n|\u2028|\u2029/g;functionescapeChar(match) {return'\\'+ escapes[match];
}

In order to prevent third-party code injection through _.templateSettings.variable, we test it against the following regular expression. It is intentionally a bit more liberal than just matching valid identifiers, but still prevents possible loopholes through defaults or destructuring assignment.

varbareIdentifier =/^\s\*(\w|\$)+\s\*$/;

JavaScript micro-templating, similar to John Resig’s implementation. Underscore templating handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. NB: oldSettings only exists for backwards compatibility.

functiontemplate(text, settings, oldSettings) {if(!settings && oldSettings) settings = oldSettings;
  settings =defaults({}, settings, _$1.templateSettings);

Combine delimiters into one regular expression via alternation.

varmatcher =RegExp([
    (settings.escape|| noMatch).source,
    (settings.interpolate|| noMatch).source,
    (settings.evaluate|| noMatch).source].join('|') +'|$','g');

Compile the template source, escaping string literals appropriately.

varindex =0;varsource ="\_\_p+='";
  text.replace(matcher,function(match, escape, interpolate, evaluate, offset) {
    source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
    index = offset + match.length;if(escape) {
      source +="'+\n((\_\_t=("+escape+"))==null?'':\_.escape(\_\_t))+\n'";
    }elseif(interpolate) {
      source +="'+\n((\_\_t=("+ interpolate +"))==null?'':\_\_t)+\n'";
    }elseif(evaluate) {
      source +="';\n"+ evaluate +"\n\_\_p+='";
    }

Adobe VMs need the match returned to produce the correct offset.

returnmatch;
  });
  source +="';\n";varargument = settings.variable;if(argument) {

Insure against third-party code injection. (CVE-2021-23358)

if(!bareIdentifier.test(argument))thrownewError('variable is not a bare identifier: '+ argument
    );
  }else{

If a variable is not specified, place data values in local scope.

source ='with(obj||{}){\n'+ source +'}\n';
    argument ='obj';
  }

  source ="var \_\_t,\_\_p='',\_\_j=Array.prototype.join,"+"print=function(){\_\_p+=\_\_j.call(arguments,'');};\n"+
    source +'return \_\_p;\n';varrender;try{
    render =newFunction(argument,'\_', source);
  }catch(e) {
    e.source= source;throwe;
  }vartemplate =function(data) {returnrender.call(this, data, _$1);
  };

Provide the compiled source as a convenience for precompilation.

template.source='function('+ argument +'){\n'+ source +'}';returntemplate;
}

Traverses the children of obj along path. If a child is a function, it is invoked with its parent as context. Returns the value of the final child, or fallback if any child is undefined.

functionresult(obj, path, fallback) {
  path =toPath(path);varlength = path.length;if(!length) {returnisFunction$1(fallback) ? fallback.call(obj) : fallback;
  }for(vari =0; i < length; i++) {varprop = obj ==null?void0: obj[path[i]];if(prop ===void0) {
      prop = fallback;
      i = length;// Ensure we don't continue iterating.}
    obj =isFunction$1(prop) ? prop.call(obj) : prop;
  }returnobj;
}

Generate a unique integer id (unique within the entire client session). Useful for temporary DOM ids.

varidCounter =0;functionuniqueId(prefix) {varid = ++idCounter +'';returnprefix ? prefix + id : id;
}

Start chaining a wrapped Underscore object.

functionchain(obj) {varinstance =\_$1(obj);
  instance.\_chain=true;returninstance;
}

Internal function to execute sourceFunc bound to context with optional args. Determines whether to execute a function as a constructor or as a normal function.

functionexecuteBound(sourceFunc, boundFunc, context, callingContext, args) {if(!(callingContextinstanceofboundFunc))returnsourceFunc.apply(context, args);varself =baseCreate(sourceFunc.prototype);varresult = sourceFunc.apply(self, args);if(isObject(result))returnresult;returnself;
}

Partially apply a function by creating a version that has had some of its arguments pre-filled, without changing its dynamic this context. _ acts as a placeholder by default, allowing any combination of arguments to be pre-filled. Set _.partial.placeholder for a custom placeholder argument.

varpartial =restArguments(function(func, boundArgs) {varplaceholder = partial.placeholder;varbound =function() {varposition =0, length = boundArgs.length;varargs =Array(length);for(vari =0; i < length; i++) {
      args[i] = boundArgs[i] === placeholder ?arguments[position++] : boundArgs[i];
    }while(position <arguments.length) args.push(arguments[position++]);returnexecuteBound(func, bound,this,this, args);
  };returnbound;
});

partial.placeholder= _$1;

Create a function bound to a given object (assigning this, and arguments, optionally).

varbind =restArguments(function(func, context, args) {if(!isFunction$1(func))thrownewTypeError('Bind must be called on a function');varbound =restArguments(function(callArgs) {returnexecuteBound(func, bound, context,this, args.concat(callArgs));
  });returnbound;
});

Internal helper for collection methods to determine whether a collection should be iterated as an array or as an object. Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094

varisArrayLike =createSizePropertyCheck(getLength);

Internal implementation of a flatten function.

functionflatten$1(input, depth, strict) {if(!depth && depth !==0) depth =Infinity;

We will be avoiding recursive calls because this could be exploited to cause a stack overflow (CVE-2026-27601). Instead, we “trampoline” on an explicit stack.

varoutput = [], idx =0, i =0, length =getLength(input) ||0, stack = [];while(true) {if(i >= length) {if(!stack.length)break;varframe = stack.pop();
      i = frame.i;
      input = frame.v;
      length =getLength(input);continue;
    }varvalue = input[i++];if(stack.length>= depth) {
      output[idx++] = value;
    }elseif(isArrayLike(value) && (isArray(value) ||isArguments$1(value))) {

Flatten current level of array or arguments object.

stack.push({i: i,v: input});
      i =0;
      input = value;
      length =getLength(input);
    }elseif(!strict) {
      output[idx++] = value;
    }
  }returnoutput;
}

Bind a number of an object’s methods to that object. Remaining arguments are the method names to be bound. Useful for ensuring that all callbacks defined on an object belong to it.

varbindAll =restArguments(function(obj, keys) {
  keys =flatten$1(keys,false,false);varindex = keys.length;if(index <1)thrownewError('bindAll must be passed function names');while(index--) {varkey = keys[index];
    obj[key] =bind(obj[key], obj);
  }returnobj;
});

Memoize an expensive function by storing its results.

functionmemoize(func, hasher) {varmemoize =function(key) {varcache = memoize.cache;varaddress =''+ (hasher ? hasher.apply(this,arguments) : key);if(!has$1(cache, address)) cache[address] = func.apply(this,arguments);returncache[address];
  };
  memoize.cache= {};returnmemoize;
}

Delays a function for the given number of milliseconds, and then calls it with the arguments supplied.

vardelay =restArguments(function(func, wait, args) {returnsetTimeout(function() {returnfunc.apply(null, args);
  }, wait);
});

Defers a function, scheduling it to run after the current call stack has cleared.

vardefer =partial(delay, _$1,1);

Returns a function, that, when invoked, will only be triggered at most once during a given window of time. Normally, the throttled function will run as much as it can, without ever going more than once per wait duration; but if you’d like to disable the execution on the leading edge, pass {leading: false}. To disable execution on the trailing edge, ditto.

functionthrottle(func, wait, options) {vartimeout, context, args, result;varprevious =0;if(!options) options = {};varlater =function() {
    previous = options.leading===false?0:now();
    timeout =null;
    result = func.apply(context, args);if(!timeout) context = args =null;
  };varthrottled =function() {var_now =now();if(!previous && options.leading===false) previous = _now;varremaining = wait - (_now - previous);
    context =this;
    args =arguments;if(remaining <=0|| remaining > wait) {if(timeout) {clearTimeout(timeout);
        timeout =null;
      }
      previous = _now;
      result = func.apply(context, args);if(!timeout) context = args =null;
    }elseif(!timeout && options.trailing!==false) {
      timeout =setTimeout(later, remaining);
    }returnresult;
  };

  throttled.cancel=function() {clearTimeout(timeout);
    previous =0;
    timeout = context = args =null;
  };returnthrottled;
}

When a sequence of calls of the returned function ends, the argument function is triggered. The end of a sequence is defined by the wait parameter. If immediate is passed, the argument function will be triggered at the beginning of the sequence instead of at the end.

functiondebounce(func, wait, immediate) {vartimeout, previous, args, result, context;varlater =function() {varpassed =now() - previous;if(wait > passed) {
      timeout =setTimeout(later, wait - passed);
    }else{
      timeout =null;if(!immediate) result = func.apply(context, args);

This check is needed because func can recursively invoke debounced.

if(!timeout) args = context =null;
    }
  };vardebounced =restArguments(function(\_args) {
    context =this;
    args = _args;
    previous =now();if(!timeout) {
      timeout =setTimeout(later, wait);if(immediate) result = func.apply(context, args);
    }returnresult;
  });

  debounced.cancel=function() {clearTimeout(timeout);
    timeout = args = context =null;
  };returndebounced;
}

Returns the first function passed as an argument to the second, allowing you to adjust arguments, run code before and after, and conditionally execute the original function.

functionwrap(func, wrapper) {returnpartial(wrapper, func);
}

Returns a negated version of the passed-in predicate.

functionnegate(predicate) {returnfunction() {return!predicate.apply(this,arguments);
  };
}

Returns a function that is the composition of a list of functions, each consuming the return value of the function that follows.

functioncompose() {varargs =arguments;varstart = args.length-1;returnfunction() {vari = start;varresult = args[start].apply(this,arguments);while(i--) result = args[i].call(this, result);returnresult;
  };
}

Returns a function that will only be executed on and after the Nth call.

functionafter(times, func) {returnfunction() {if(--times <1) {returnfunc.apply(this,arguments);
    }
  };
}

Returns a function that will only be executed up to (but not including) the Nth call.

functionbefore(times, func) {varmemo;returnfunction() {if(--times >0) {
      memo = func.apply(this,arguments);
    }if(times <=1) func =null;returnmemo;
  };
}

Returns a function that will be executed at most one time, no matter how often you call it. Useful for lazy initialization.

varonce =partial(before,2);

Returns the first key on an object that passes a truth test.

functionfindKey(obj, predicate, context) {
  predicate =cb(predicate, context);var_keys =keys(obj), key;for(vari =0, length = _keys.length; i < length; i++) {
    key = _keys[i];if(predicate(obj[key], key, obj))returnkey;
  }
}

Internal function to generate _.findIndex and _.findLastIndex.

functioncreatePredicateIndexFinder(dir) {returnfunction(array, predicate, context) {
    predicate =cb(predicate, context);varlength =getLength(array);varindex = dir >0?0: length -1;for(; index >=0&& index < length; index += dir) {if(predicate(array[index], index, array))returnindex;
    }return-1;
  };
}

Returns the first index on an array-like that passes a truth test.

varfindIndex =createPredicateIndexFinder(1);

Returns the last index on an array-like that passes a truth test.

varfindLastIndex =createPredicateIndexFinder(-1);

Use a comparator function to figure out the smallest index at which an object should be inserted so as to maintain order. Uses binary search.

functionsortedIndex(array, obj, iteratee, context) {
  iteratee =cb(iteratee, context,1);varvalue =iteratee(obj);varlow =0, high =getLength(array);while(low < high) {varmid =Math.floor((low + high) /2);if(iteratee(array[mid]) < value) low = mid +1;elsehigh = mid;
  }returnlow;
}

Internal function to generate the _.indexOf and _.lastIndexOf functions.

functioncreateIndexFinder(dir, predicateFind, sortedIndex) {returnfunction(array, item, idx) {vari =0, length =getLength(array);if(typeofidx =='number') {if(dir >0) {
        i = idx >=0? idx :Math.max(idx + length, i);
      }else{
        length = idx >=0?Math.min(idx +1, length) : idx + length +1;
      }
    }elseif(sortedIndex && idx && length) {
      idx =sortedIndex(array, item);returnarray[idx] === item ? idx : -1;
    }if(item !== item) {
      idx =predicateFind(slice.call(array, i, length), isNaN$1);returnidx >=0? idx + i : -1;
    }for(idx = dir >0? i : length -1; idx >=0&& idx < length; idx += dir) {if(array[idx] === item)returnidx;
    }return-1;
  };
}

Return the position of the first occurrence of an item in an array, or -1 if the item is not included in the array. If the array is large and already in sort order, pass true for isSorted to use binary search.

varindexOf =createIndexFinder(1, findIndex, sortedIndex);

Return the position of the last occurrence of an item in an array, or -1 if the item is not included in the array.

varlastIndexOf =createIndexFinder(-1, findLastIndex);

Return the first value which passes a truth test.

functionfind(obj, predicate, context) {varkeyFinder =isArrayLike(obj) ? findIndex : findKey;varkey =keyFinder(obj, predicate, context);if(key !==void0&& key !== -1)returnobj[key];
}

Convenience version of a common use case of _.find: getting the first object containing specific key:value pairs.

functionfindWhere(obj, attrs) {returnfind(obj,matcher(attrs));
}

The cornerstone for collection functions, an each implementation, aka forEach. Handles raw objects in addition to array-likes. Treats all sparse array-likes as if they were dense.

functioneach(obj, iteratee, context) {
  iteratee =optimizeCb(iteratee, context);vari, length;if(isArrayLike(obj)) {for(i =0, length = obj.length; i < length; i++) {iteratee(obj[i], i, obj);
    }
  }else{var_keys =keys(obj);for(i =0, length = _keys.length; i < length; i++) {iteratee(obj[_keys[i]], _keys[i], obj);
    }
  }returnobj;
}

Return the results of applying the iteratee to each element.

functionmap(obj, iteratee, context) {
  iteratee =cb(iteratee, context);var_keys = !isArrayLike(obj) &&keys(obj),
      length = (_keys || obj).length,
      results =Array(length);for(varindex =0; index < length; index++) {varcurrentKey = _keys ? _keys[index] : index;
    results[index] =iteratee(obj[currentKey], currentKey, obj);
  }returnresults;
}

Internal helper to create a reducing function, iterating left or right.

functioncreateReduce(dir) {

Wrap code that reassigns argument variables in a separate function than the one that accesses arguments.length to avoid a perf hit. (#1991)

varreducer =function(obj, iteratee, memo, initial) {var_keys = !isArrayLike(obj) &&keys(obj),
        length = (_keys || obj).length,
        index = dir >0?0: length -1;if(!initial) {
      memo = obj[_keys ? _keys[index] : index];
      index += dir;
    }for(; index >=0&& index < length; index += dir) {varcurrentKey = _keys ? _keys[index] : index;
      memo =iteratee(memo, obj[currentKey], currentKey, obj);
    }returnmemo;
  };returnfunction(obj, iteratee, memo, context) {varinitial =arguments.length>=3;returnreducer(obj,optimizeCb(iteratee, context,4), memo, initial);
  };
}

Reduce builds up a single result from a list of values, aka inject, or foldl.

varreduce =createReduce(1);

The right-associative version of reduce, also known as foldr.

varreduceRight =createReduce(-1);

Return all the elements that pass a truth test.

functionfilter(obj, predicate, context) {varresults = [];
  predicate =cb(predicate, context);each(obj,function(value, index, list) {if(predicate(value, index, list)) results.push(value);
  });returnresults;
}

Return all the elements for which a truth test fails.

functionreject(obj, predicate, context) {returnfilter(obj,negate(cb(predicate)), context);
}

Determine whether all of the elements pass a truth test.

functionevery(obj, predicate, context) {
  predicate =cb(predicate, context);var_keys = !isArrayLike(obj) &&keys(obj),
      length = (_keys || obj).length;for(varindex =0; index < length; index++) {varcurrentKey = _keys ? _keys[index] : index;if(!predicate(obj[currentKey], currentKey, obj))returnfalse;
  }returntrue;
}

Determine if at least one element in the object passes a truth test.

functionsome(obj, predicate, context) {
  predicate =cb(predicate, context);var_keys = !isArrayLike(obj) &&keys(obj),
      length = (_keys || obj).length;for(varindex =0; index < length; index++) {varcurrentKey = _keys ? _keys[index] : index;if(predicate(obj[currentKey], currentKey, obj))returntrue;
  }returnfalse;
}

Determine if the array or object contains a given item (using ===).

functioncontains(obj, item, fromIndex, guard) {if(!isArrayLike(obj)) obj =values(obj);if(typeoffromIndex !='number'|| guard) fromIndex =0;returnindexOf(obj, item, fromIndex) >=0;
}

Invoke a method (with arguments) on every item in a collection.

varinvoke =restArguments(function(obj, path, args) {varcontextPath, func;if(isFunction$1(path)) {
    func = path;
  }else{
    path =toPath(path);
    contextPath = path.slice(0, -1);
    path = path[path.length-1];
  }returnmap(obj,function(context) {varmethod = func;if(!method) {if(contextPath && contextPath.length) {
        context =deepGet(context, contextPath);
      }if(context ==null)returnvoid0;
      method = context[path];
    }returnmethod ==null? method : method.apply(context, args);
  });
});

Convenience version of a common use case of _.map: fetching a property.

functionpluck(obj, key) {returnmap(obj,property(key));
}

Convenience version of a common use case of _.filter: selecting only objects containing specific key:value pairs.

functionwhere(obj, attrs) {returnfilter(obj,matcher(attrs));
}

Return the maximum element (or element-based computation).

functionmax(obj, iteratee, context) {varresult = -Infinity, lastComputed = -Infinity,
      value, computed;if(iteratee ==null|| (typeofiteratee =='number'&&typeofobj[0] !='object'&& obj !=null)) {
    obj =isArrayLike(obj) ? obj :values(obj);for(vari =0, length = obj.length; i < length; i++) {
      value = obj[i];if(value !=null&& value > result) {
        result = value;
      }
    }
  }else{
    iteratee =cb(iteratee, context);each(obj,function(v, index, list) {
      computed =iteratee(v, index, list);if(computed > lastComputed || (computed === -Infinity&& result === -Infinity)) {
        result = v;
        lastComputed = computed;
      }
    });
  }returnresult;
}

Return the minimum element (or element-based computation).

functionmin(obj, iteratee, context) {varresult =Infinity, lastComputed =Infinity,
      value, computed;if(iteratee ==null|| (typeofiteratee =='number'&&typeofobj[0] !='object'&& obj !=null)) {
    obj =isArrayLike(obj) ? obj :values(obj);for(vari =0, length = obj.length; i < length; i++) {
      value = obj[i];if(value !=null&& value < result) {
        result = value;
      }
    }
  }else{
    iteratee =cb(iteratee, context);each(obj,function(v, index, list) {
      computed =iteratee(v, index, list);if(computed < lastComputed || (computed ===Infinity&& result ===Infinity)) {
        result = v;
        lastComputed = computed;
      }
    });
  }returnresult;
}

Safely create a real, live array from anything iterable.

varreStrSymbol =/[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;functiontoArray(obj) {if(!obj)return[];if(isArray(obj))returnslice.call(obj);if(isString(obj)) {

Keep surrogate pair characters together.

returnobj.match(reStrSymbol);
  }if(isArrayLike(obj))returnmap(obj, identity);returnvalues(obj);
}

Sample n random values from a collection using the modern version of the Fisher-Yates shuffle. If n is not specified, returns a single random element. The internal guard argument allows it to work with _.map.

functionsample(obj, n, guard) {if(n ==null|| guard) {if(!isArrayLike(obj)) obj =values(obj);returnobj[random(obj.length-1)];
  }varsample =toArray(obj);varlength =getLength(sample);
  n =Math.max(Math.min(n, length),0);varlast = length -1;for(varindex =0; index < n; index++) {varrand =random(index, last);vartemp = sample[index];
    sample[index] = sample[rand];
    sample[rand] = temp;
  }returnsample.slice(0, n);
}

Shuffle a collection.

functionshuffle(obj) {returnsample(obj,Infinity);
}

Sort the object’s values by a criterion produced by an iteratee.

functionsortBy(obj, iteratee, context) {varindex =0;
  iteratee =cb(iteratee, context);returnpluck(map(obj,function(value, key, list) {return{value: value,index: index++,criteria:iteratee(value, key, list)
    };
  }).sort(function(left, right) {vara = left.criteria;varb = right.criteria;if(a !== b) {if(a > b || a ===void0)return1;if(a < b || b ===void0)return-1;
    }returnleft.index- right.index;
  }),'value');
}

An internal function used for aggregate “group by” operations.

functiongroup(behavior, partition) {returnfunction(obj, iteratee, context) {varresult = partition ? [[], []] : {};
    iteratee =cb(iteratee, context);each(obj,function(value, index) {varkey =iteratee(value, index, obj);behavior(result, value, key);
    });returnresult;
  };
}

Groups the object’s values by a criterion. Pass either a string attribute to group by, or a function that returns the criterion.

vargroupBy =group(function(result, value, key) {if(has$1(result, key)) result[key].push(value);elseresult[key] = [value];
});

Indexes the object’s values by a criterion, similar to _.groupBy, but for when you know that your index values will be unique.

varindexBy =group(function(result, value, key) {
  result[key] = value;
});

Counts instances of an object that group by a certain criterion. Pass either a string attribute to count by, or a function that returns the criterion.

varcountBy =group(function(result, value, key) {if(has$1(result, key)) result[key]++;elseresult[key] =1;
});

Split a collection into two arrays: one whose elements all pass the given truth test, and one whose elements all do not pass the truth test.

varpartition =group(function(result, value, pass) {
  result[pass ?0:1].push(value);
},true);

Return the number of elements in a collection.

functionsize(obj) {if(obj ==null)return0;returnisArrayLike(obj) ? obj.length:keys(obj).length;
}

Internal _.pick helper function to determine whether key is an enumerable property name of obj.

functionkeyInObj(value, key, obj) {returnkeyinobj;
}

Return a copy of the object only containing the allowed properties.

varpick =restArguments(function(obj, keys) {varresult = {}, iteratee = keys[0];if(obj ==null)returnresult;if(isFunction$1(iteratee)) {if(keys.length>1) iteratee =optimizeCb(iteratee, keys[1]);
    keys =allKeys(obj);
  }else{
    iteratee = keyInObj;
    keys =flatten$1(keys,false,false);
    obj =Object(obj);
  }for(vari =0, length = keys.length; i < length; i++) {varkey = keys[i];varvalue = obj[key];if(iteratee(value, key, obj)) result[key] = value;
  }returnresult;
});

Return a copy of the object without the disallowed properties.

varomit =restArguments(function(obj, keys) {variteratee = keys[0], context;if(isFunction$1(iteratee)) {
    iteratee =negate(iteratee);if(keys.length>1) context = keys[1];
  }else{
    keys =map(flatten$1(keys,false,false),String);
    iteratee =function(value, key) {return!contains(keys, key);
    };
  }returnpick(obj, iteratee, context);
});

Returns everything but the last entry of the array. Especially useful on the arguments object. Passing n will return all the values in the array, excluding the last N.

functioninitial(array, n, guard) {returnslice.call(array,0,Math.max(0, array.length- (n ==null|| guard ?1: n)));
}

Get the first element of an array. Passing n will return the first N values in the array. The guard check allows it to work with _.map.

functionfirst(array, n, guard) {if(array ==null|| array.length<1)returnn ==null|| guard ?void0: [];if(n ==null|| guard)returnarray[0];returninitial(array, array.length- n);
}

Returns everything but the first entry of the array. Especially useful on the arguments object. Passing an n will return the rest N values in the array.

functionrest(array, n, guard) {returnslice.call(array, n ==null|| guard ?1: n);
}

Get the last element of an array. Passing n will return the last N values in the array.

functionlast(array, n, guard) {if(array ==null|| array.length<1)returnn ==null|| guard ?void0: [];if(n ==null|| guard)returnarray[array.length-1];returnrest(array,Math.max(0, array.length- n));
}

Trim out all falsy values from an array.

functioncompact(array) {returnfilter(array,Boolean);
}

Flatten out an array, either recursively (by default), or up to depth. Passing true or false as depth means 1 or Infinity, respectively.

functionflatten(array, depth) {returnflatten$1(array, depth,false);
}

Take the difference between one array and a number of other arrays. Only the elements present in just the first array will remain.

vardifference =restArguments(function(array, rest) {
  rest =flatten$1(rest,true,true);returnfilter(array,function(value){return!contains(rest, value);
  });
});

Return a version of the array that does not contain the specified value(s).

varwithout =restArguments(function(array, otherArrays) {returndifference(array, otherArrays);
});

Produce a duplicate-free version of the array. If the array has already been sorted, you have the option of using a faster algorithm. The faster algorithm will not work with an iteratee if the iteratee is not a one-to-one function, so providing an iteratee will disable the faster algorithm.

functionuniq(array, isSorted, iteratee, context) {if(!isBoolean(isSorted)) {
    context = iteratee;
    iteratee = isSorted;
    isSorted =false;
  }if(iteratee !=null) iteratee =cb(iteratee, context);varresult = [];varseen = [];for(vari =0, length =getLength(array); i < length; i++) {varvalue = array[i],
        computed = iteratee ?iteratee(value, i, array) : value;if(isSorted && !iteratee) {if(!i || seen !== computed) result.push(value);
      seen = computed;
    }elseif(iteratee) {if(!contains(seen, computed)) {
        seen.push(computed);
        result.push(value);
      }
    }elseif(!contains(result, value)) {
      result.push(value);
    }
  }returnresult;
}

Produce an array that contains the union: each distinct element from all of the passed-in arrays.

varunion =restArguments(function(arrays) {returnuniq(flatten$1(arrays,true,true));
});

Produce an array that contains every item shared between all the passed-in arrays.

functionintersection(array) {varresult = [];varargsLength =arguments.length;for(vari =0, length =getLength(array); i < length; i++) {varitem = array[i];if(contains(result, item))continue;varj;for(j =1; j < argsLength; j++) {if(!contains(arguments[j], item))break;
    }if(j === argsLength) result.push(item);
  }returnresult;
}

Complement of zip. Unzip accepts an array of arrays and groups each array’s elements on shared indices.

functionunzip(array) {varlength = (array &&max(array, getLength).length) ||0;varresult =Array(length);for(varindex =0; index < length; index++) {
    result[index] =pluck(array, index);
  }returnresult;
}

Zip together multiple lists into a single array – elements that share an index go together.

varzip =restArguments(unzip);

Converts lists into objects. Pass either a single array of [key, value] pairs, or two parallel arrays of the same length – one of keys, and one of the corresponding values. Passing by pairs is the reverse of _.pairs.

functionobject(list, values) {varresult = {};for(vari =0, length =getLength(list); i < length; i++) {if(values) {
      result[list[i]] = values[i];
    }else{
      result[list[i][0]] = list[i][1];
    }
  }returnresult;
}

Generate an integer Array containing an arithmetic progression. A port of the native Python range() function. See the Python documentation.

functionrange(start, stop, step) {if(stop ==null) {
    stop = start ||0;
    start =0;
  }if(!step) {
    step = stop < start ? -1:1;
  }varlength =Math.max(Math.ceil((stop - start) / step),0);varrange =Array(length);for(varidx =0; idx < length; idx++, start += step) {
    range[idx] = start;
  }returnrange;
}

Chunk a single array into multiple arrays, each containing count or fewer items.

functionchunk(array, count) {if(count ==null|| count <1)return[];varresult = [];vari =0, length = array.length;while(i < length) {
    result.push(slice.call(array, i, i += count));
  }returnresult;
}

Helper function to continue chaining intermediate results.

functionchainResult(instance, obj) {returninstance.\_chain?\_$1(obj).chain() : obj;
}

Add your own custom functions to the Underscore object.

functionmixin(obj) {each(functions(obj),function(name) {varfunc = _$1[name] = obj[name];
    _$1.prototype[name] =function() {varargs = [this.\_wrapped];
      push.apply(args,arguments);returnchainResult(this, func.apply(_$1, args));
    };
  });return_$1;
}

Add all mutator Array functions to the wrapper.

each(['pop','push','reverse','shift','sort','splice','unshift'],function(name) {varmethod =ArrayProto[name];
  _$1.prototype[name] =function() {varobj =this.\_wrapped;if(obj !=null) {
      method.apply(obj,arguments);if((name ==='shift'|| name ==='splice') && obj.length===0) {deleteobj[0];
      }
    }returnchainResult(this, obj);
  };
});

Add all accessor Array functions to the wrapper.

each(['concat','join','slice'],function(name) {varmethod =ArrayProto[name];
  _$1.prototype[name] =function() {varobj =this.\_wrapped;if(obj !=null) obj = method.apply(obj,arguments);returnchainResult(this, obj);
  };
});

Named Exports

varallExports = {\_\_proto\_\_:null,VERSION:VERSION,restArguments: restArguments,isObject: isObject,isNull: isNull,isUndefined: isUndefined,isBoolean: isBoolean,isElement: isElement,isString: isString,isNumber: isNumber,isDate: isDate,isRegExp: isRegExp,isError: isError,isSymbol: isSymbol,isArrayBuffer: isArrayBuffer,isDataView: isDataView$1,isArray: isArray,isFunction: isFunction$1,isArguments: isArguments$1,isFinite: isFinite$1,isNaN: isNaN$1,isTypedArray: isTypedArray$1,isEmpty: isEmpty,isMatch: isMatch,isEqual: isEqual,isMap: isMap,isWeakMap: isWeakMap,isSet: isSet,isWeakSet: isWeakSet,keys: keys,allKeys: allKeys,values: values,pairs: pairs,invert: invert,functions: functions,methods: functions,extend: extend,extendOwn: extendOwn,assign: extendOwn,defaults: defaults,create: create,clone: clone,tap: tap,get: get,has: has,mapObject: mapObject,identity: identity,constant: constant,noop: noop,toPath: toPath$1,property: property,propertyOf: propertyOf,matcher: matcher,matches: matcher,times: times,random: random,now: now,escape: _escape,unescape: _unescape,templateSettings: templateSettings,template: template,result: result,uniqueId: uniqueId,chain: chain,iteratee: iteratee,partial: partial,bind: bind,bindAll: bindAll,memoize: memoize,delay: delay,defer: defer,throttle: throttle,debounce: debounce,wrap: wrap,negate: negate,compose: compose,after: after,before: before,once: once,findKey: findKey,findIndex: findIndex,findLastIndex: findLastIndex,sortedIndex: sortedIndex,indexOf: indexOf,lastIndexOf: lastIndexOf,find: find,detect: find,findWhere: findWhere,each: each,forEach: each,map: map,collect: map,reduce: reduce,foldl: reduce,inject: reduce,reduceRight: reduceRight,foldr: reduceRight,filter: filter,select: filter,reject: reject,every: every,all: every,some: some,any: some,contains: contains,includes: contains,include: contains,invoke: invoke,pluck: pluck,where: where,max: max,min: min,shuffle: shuffle,sample: sample,sortBy: sortBy,groupBy: groupBy,indexBy: indexBy,countBy: countBy,partition: partition,toArray: toArray,size: size,pick: pick,omit: omit,first: first,head: first,take: first,initial: initial,last: last,rest: rest,tail: rest,drop: rest,compact: compact,flatten: flatten,without: without,uniq: uniq,unique: uniq,union: union,intersection: intersection,difference: difference,unzip: unzip,transpose: unzip,zip: zip,object: object,range: range,chunk: chunk,mixin: mixin,'default': _$1};

Default Export

Add all of the Underscore functions to the wrapper object.

var_ =mixin(allExports);

Legacy Node.js API.

_.\_= _;

ESM Exports

exportdefault_;export{VERSION, after, everyasall, allKeys, someasany, extendOwnasassign, before, bind, bindAll, chain, chunk, clone, mapascollect, compact, compose, constant, contains, countBy, create, debounce, defaults, defer, delay, findasdetect, difference, restasdrop, each, _escapeasescape, every, extend, extendOwn, filter, find, findIndex, findKey, findLastIndex, findWhere, first, flatten, reduceasfoldl, reduceRightasfoldr, eachasforEach, functions, get, groupBy, has, firstashead, identity, containsasinclude, containsasincludes, indexBy, indexOf, initial, reduceasinject, intersection, invert, invoke, isArguments$1asisArguments, isArray, isArrayBuffer, isBoolean, isDataView$1asisDataView, isDate, isElement, isEmpty, isEqual, isError, isFinite$1asisFinite, isFunction$1asisFunction, isMap, isMatch, isNaN$1asisNaN, isNull, isNumber, isObject, isRegExp, isSet, isString, isSymbol, isTypedArray$1asisTypedArray, isUndefined, isWeakMap, isWeakSet, iteratee, keys, last, lastIndexOf, map, mapObject, matcher, matcherasmatches, max, memoize, functionsasmethods, min, mixin, negate, noop, now, object, omit, once, pairs, partial, partition, pick, pluck, property, propertyOf, random, range, reduce, reduceRight, reject, rest, restArguments, result, sample, filterasselect, shuffle, size, some, sortBy, sortedIndex, restastail, firstastake, tap, template, templateSettings, throttle, times, toArray, toPath$1astoPath, unzipastranspose, _unescapeasunescape, union, uniq, uniqasunique, uniqueId, unzip, values, where, without, wrap, zip };

sourceMappingURL=underscore-esm.js.map