introduction h1>
The
underscore is a JavaScript tool library that provides a full range of functional programming capabilities. It contains many utility functions such as each, Map, Reduce,filter, and so on. While es5,es6 already includes most of these, looking at the source code to see the underlying implementation of these functions will help you gain a deeper understanding of native js
The
underscore is defined as pure functions and supports chained calls to a one-way data source. In the chain of functions, data flows magically from one function to another as if passing through a pipe.
const result = _([1, 2, 3, 4, 5, 6, 7]).chain().map((item) => {return item * 2;}).filter((item) => {
return item > 10;
}).value();
operation process is as follows:
- takes the array as the starting data source, runs _([1, 2, 3, 4, 5, 6, 7]) to generate instance objects, and then calls the method chain on the instance to enable it to chain call.
- runs the map function and multiplies each element of the array by 2 to form a new array. 14], filter out the value of less than 10 li>
- value () method to obtain the final run results [12, 14] li> ul>
the above process shows that the data source enters from the initial port and is passed back layer by layer. Each function will receive the result processed by the previous function and send the result run by itself to the next function. The data flows back like a stream of water as it enters a pipe, forming a streaming call. Next, implement its overall operation mechanism.
source implementation
create constructor
defines the constructor _, if obj is a piece of ordinary data, when running _(obj), this points to window, the result returns the instance object new _(obj), then the object contains the property wrapped, the corresponding value is obj.
(function (global) { function _(obj) { if (obj instanceof _) { return obj; } if (!(this instanceof _)) { return new _(obj); } this.wrapped = obj; } _.prototype.value = function () { return this.wrapped; }; global._ = _; })(window);
implements streaming calls
defines an object allExports, assigns the defined utility functions to the properties of the object, and passes in the mixin function to run
function chain(obj) { const _instance = _(obj); _instance._chain = true; return _instance; } function map(obj, iteratee) {...} function filter(obj, iteratee) {...} const allExports = { chain, map, filter, }; mixin(allExports);
runs the mixin function, and the parameter obj is the allExports defined above. Key is the name of the function,func corresponds to the specific function.
func is not bound directly to the constructor, but to the constructor’s prototype object. As can be seen from here,_(data).chain().map().filter() calls chain,map,filter () during the execution process, it actually calls the function
defined in the mixin mounted on the prototype object
is executed as follows :
- assumption data = [1, 2, 3], _ (data) is the result of instance object {wrapped: [1, 2, 3]} li>
- call instance object chain method, below the running function. The result = [[1, 2, 3]].
- func points to the chain function and adds _chain attribute to the instance object.
- chainResult function determines that the current instance object branch does not support chain calls. If it supports subsequent newly generated instance objects, _chain is added as true. Return the new instance object
- the data of the new instance object is still {wrapped:[1,2,3]}. Func points to the map function. Map function returns result [2,4,6]. ChainResult finds support for chain call run _([2,4,6]) to generate a new instance object
- . At this point, this.wrapped has become [2,4,6]. It can be seen from here that every time a function is run, it will generate new instance object by taking the data processed by the function as parameter, and return this new instance object to continue calling other functions, and generate new instance object again. The new instance object continues to call with the processed data, forming the data flow.
function mixin(obj) { const array = Object.keys(obj); array.forEach((key) => { const func = obj[key]; _.prototype[key] = function () { const result = [this.wrapped]; Array.prototype.push.apply(result, arguments); return chainResult(this, func.apply(_, result)); }; }); } function chainResult(_instance, obj) { return _instance._chain ?_(obj).chain() : obj; }
complete code
(function (global) { function _(obj) { if (obj instanceof _) { return obj; } if (!(this instanceof _)) { return new _(obj); } this.wrapped = obj; } _.prototype.value = function () { return this.wrapped; }; function chain(obj) { const _instance = _(obj); _instance._chain = true; return _instance; } //map函数的简单实现,支持数组和对象 function map(obj, iteratee) { const keys = !Array.isArray(obj) && Object.keys(obj); const len = keys ?keys.length : obj.length; const result = []; for (let i = 0; i < len; i++) { const current_key = keys ?keys[i] : i; result.push(iteratee(obj[current_key])); } return result; } //filter函数的简单实现,,支持数组和对象 function filter(obj, iteratee) { const keys = !Array.isArray(obj) && Object.keys(obj); const len = keys ?keys.length : obj.length; const result = []; for (let i = 0; i < len; i++) { const current_key = keys ?keys[i] : i; if (iteratee(obj[current_key])) { result.push(obj[current_key]); } } return result; } function mixin(obj) { const array = Object.keys(obj); array.forEach((key) => { const func = obj[key]; _.prototype[key] = function () { const result = [this.wrapped]; Array.prototype.push.apply(result, arguments); return chainResult(this, func.apply(_, result)); }; }); } function chainResult(_instance, obj) { return _instance._chain ?_(obj).chain() : obj; } const allExports = { chain, map, filter, }; mixin(allExports); global._ = _; })(window);
div>
Read More:
- Notes on Java IO streaming
- UE4 texture streaming pool over xxmb error
- Vs2013 package deployment error: isdev: error – 6003: an error occurred streaming
- SRS is started normally and there is no screen for streaming. Look at the SRS log and report an error SRS is already running
- R ggplot Error in .Call.graphics(C_palette2, .Call(C_palette2, NULL)): invalid graphics state
- Error in .Call.graphics(C_palette2, .Call(C_palette2, NULL)) : invalid graphics state
- R language – error analysis – error in Call.graphics (C_ palette2, .Call(C_ palette2, NULL)) : invalid graphics state
- Uncaught Error: Call to undefined function mysql_select_db()
- [Qt] error: call to non-static member function without an object argument
- [problem record] objc_ Too many arguments to function call
- How to call stored procedure in Hibernate
- error Expected an assignment or function call and instead saw an expression
- Call unity with lightmap and light probes in shader
- Cannot call the same level library solution in pychar
- Coredata: error: failed to call designed initializer on nsmanagedobject
- PHP Fatal error: Call to a member function query() on a non-object in
- Generating equals/hashCode implementation but without a call to superclass
- Waitpid call return error prompt: no child processes problem
- Fatal error: Call to a member function bind_param() on a non-object in
- Call to a member function fetch_assoc() on a non-object