Enumerable provides a large set of useful methods for enumerations, that is, objects that act as collections of values. It is a cornerstone of Prototype.
Enumerable is what we like to call a module: a consistent set of methods intended not for independent use, but for mixin: incorporation into other objects that "fit" with it.
Quite a few objects, in Prototype, mix Enumerable in already. the most visible cases are Array and Hash, but you'll find it in less obvious spots as well, such as in ObjectRange and varous DOM-or AJAX-related objects.
The short term above indicates that Enumerable is the cornerstone of the Prototype framework, and Enumerable is not used independently. In Prototype, other objects mix the methods in Enumerable, in this way, you can apply the Enumerable method to these objects. Such objects include Array, Hash, ObjectRange, and DOM and AJAX-related objects.
I personally understand that Enumerable is equivalent to the abstract class concept in C ++. Other classes can inherit from this class and implement the abstract method "_ each" in Enumerable, and can overwrite other methods, however, Enumerable itself cannot be instantiated, but can only instantiate its subclass.
The following describes how to use Enumerable to write your own classes:
Copy codeThe Code is as follows:
Var YourObject = Class. create ();
Object. extend (YourObject. prototype, Enumerable); Object. extend (YourObject. prototype ,{
Initialize: function (){
// With whatever constructor arguments you need
// Your construction code
},
_ Each: function (iterator ){
// Your iteration code, invoking iterator at every turn
},
// Your other methods here, including Enumerable overrides
});
It can be seen that the most important thing is to implement the _ each method. The initialize method is equivalent to the constructor. If you do not need any external parameters, You can omit them. Below I write a class that generates random number arrays, which is very simple and has many imperfections. Here we only use it for Demonstration:
Copy codeThe Code is as follows:
// Create the RandomArray class
Var RandomArray = Class. create ();
// Mixin Enumerable
Object. extend (RandomArray. prototype, Enumerable );
// Implement _ each and the required Method
Object. extend (RandomArray. prototype ,{
Initialize: function (min, max, count ){
This. min = min;
This. max = max;
This. count = count;
This. _ numbers = [];
This. _ createRandomArray ();
},
_ Each: function (iterator ){
Var index = this. count;
While (index --> 0 ){
Iterator (this. _ numbers [index]);
}
},
// Generate a random number Array
_ CreateRandomArray: function (){
Var index = 0;
While (index <this. count ){
Var random = Math. round (Math. random () * (this. max-this.min) + this. min );
If (this. include (random )){
Continue;
}
This. _ numbers [index ++] = random;
}
},
Include: function (number ){
Return this. _ numbers. indexOf (number )! =-1;
}
});
Var obj = new RandomArray (4,19, 5 );
// Alert (obj. size ());
Alert (obj. entries ());
Take a look at the source code of Enumerable, and then learn each of the Methods:
Copy codeThe Code is as follows:
Var $ break = {};
Var Enumerable = (function (){
// Traverse each data
Function each (iterator, context ){
Var index = 0;
Try {
This. _ each (function (value ){
Iterator. call (context, value, index ++ );
});
} Catch (e ){
If (e! = $ Break) throw e;
}
Return this;
}
// Divide the data into N groups, with each group having a number. The last group may be smaller than the number.
Function eachSlice (number, iterator, context ){
Var index =-number, slices = [], array = this. toArray ();
If (number <1) return array;
While (index + = number) <array. length)
Slices. push (array. slice (index, index + number ));
Return slices. collect (iterator, context );
}
// Test whether all data meets a certain condition
Function all (iterator, context ){
Iterator = iterator | Prototype. K;
Var result = true;
This. each (function (value, index ){
Result = result &&!! Iterator. call (context, value, index );
If (! Result) throw $ break;
});
Return result;
}
// Check whether any data meets a certain condition
Function any (iterator, context ){
Iterator = iterator | Prototype. K;
Var result = false;
This. each (function (value, index ){
If (result = !! Iterator. call (context, value, index ))
Throw $ break;
});
Return result;
}
// You can perform any operations on all the data and return an array of results.
Function collect (iterator, context ){
Iterator = iterator | Prototype. K;
Var results = [];
This. each (function (value, index ){
Results. push (iterator. call (context, value, index ));
});
Return results;
}
// Search for the first data that meets a certain condition and return it, which is equivalent to the alias of the find method.
Function detect (iterator, context ){
Var result;
This. each (function (value, index ){
If (iterator. call (context, value, index )){
Result = value;
Throw $ break;
}
});
Return result;
}
// Search for all data that meets a certain condition and return results
Function findAll (iterator, context ){
Var results = [];
This. each (function (value, index ){
If (iterator. call (context, value, index ))
Results. push (value );
});
Return results;
}
// Filter all data based on the filter condition, locate the data that meets the filter condition, and return the result
// Filter is a string or regular expression.
Function grep (filter, iterator, context ){
Iterator = iterator | Prototype. K;
Var results = [];
If (Object. isString (filter ))
Filter = new RegExp (RegExp. escape (filter ));
This. each (function (value, index ){
If (filter. match (value ))
Results. push (iterator. call (context, value, index ));
});
Return results;
}
// Check whether a certain data is contained
Function include (object ){
If (Object. isFunction (this. indexOf ))
If (this. indexOf (object )! =-1) return true;
Var found = false;
This. each (function (value ){
If (value = object ){
Found = true;
Throw $ break;
}
});
Return found;
}
// Similar to the eachSlice method, if the number of the last element group is insufficient, use the fillWith parameter.
Function inGroupsOf (number, fillWith ){
FillWith = Object. isUndefined (fillWith )? Null: fillWith;
Return this. eachSlice (number, function (slice ){
While (slice. length <number) slice. push (fillWith );
Return slice;
});
}
// Perform a continuous operation on all data to accumulate or accumulate data.
Function inject (memo, iterator, context ){
This. each (function (value, index ){
Memo = iterator. call (context, memo, value, index );
});
Return memo;
}
// Execute a method on all data
Function invoke (method ){
Var args = $ A (arguments). slice (1 );
Return this. map (function (value ){
Return value [method]. apply (value, args );
});
}
// Find the maximum value in the data
Function max (iterator, context ){
Iterator = iterator | Prototype. K;
Var result;
This. each (function (value, index ){
Value = iterator. call (context, value, index );
If (result = null | value> = result)
Result = value;
});
Return result;
}
// Find the minimum value in the data
Function min (iterator, context ){
Iterator = iterator | Prototype. K;
Var result;
This. each (function (value, index ){
Value = iterator. call (context, value, index );
If (result = null | value <result)
Result = value;
});
Return result;
}
// Split all data into two parts. The first group is the data that meets a certain condition, and the second group is the data that does not meet the condition.
Function partition (iterator, context ){
Iterator = iterator | Prototype. K;
Var trues = [], falses = [];
This. each (function (value, index ){
(Iterator. call (context, value, index )?
Trues: falses). push (value );
});
Return [trues, falses];
}
// Retrieve the property value of all data and return the result
Function pluck (property ){
Var results = [];
This. each (function (value ){
Results. push (value [property]);
});
Return results;
}
// Locate the data that does not meet a certain condition
Function reject (iterator, context ){
Var results = [];
This. each (function (value, index ){
If (! Iterator. call (context, value, index ))
Results. push (value );
});
Return results;
}
// Sort all data based on a condition
Function sortBy (iterator, context ){
Return this. map (function (value, index ){
Return {
Value: value,
Criteria: iterator. call (context, value, index)
};
}). Sort (function (left, right ){
Var a = left. criteria, B = right. criteria;
Return a <B? -1: a> B? 1: 0;
}). Pluck ('value ');
}
// Array representation of returned data
Function toArray (){
Return this. map ();
}
// Basically, the two groups of data are put together for some operations.
Function zip (){
Var iterator = Prototype. K, args = $ A (arguments );
If (Object. isFunction (args. last ()))
Iterator = args. pop ();
Var collections = [this]. concat (args). map ($ );
Return this. map (function (value, index ){
Return iterator (collections. pluck (index ));
});
}
Function size (){
Return this. toArray (). length;
}
// Returns the string representation of the Enumerable object.
Function inspect (){
Return '# <Enumerable:' + this. toArray (). inspect () + '> ';
}
Return {
Each: each,
EachSlice: eachSlice,
All: all,
Every: all,
Any: any,
Some: any,
Collect: collect,
Map: collect,
Detect: detect,
FindAll: findAll,
Select: findAll,
Filter: findAll,
Grep: grep,
Include: include,
Member: include,
InGroupsOf: inGroupsOf,
Inject: inject,
Invoke: invoke,
Max: max,
Min: min,
Partition: partition,
Pluck: pluck,
Reject: reject,
SortBy: sortBy,
ToArray: toArray,
Entries: toArray,
Zip: zip,
Size: size,
Inspect: inspect,
Find: detect
};
})();
The following describes how Enumerable provides:
All
Any
Collect
Detect
Each
EachSlice
Entries
Find
FindAll
Grep
InGroupsOf
Include
Inject
Invoke
Map
Max
Member
Min
Partition
Pluck
Reject
Select
Size
SortBy
ToArray
Zip
All method:
Determines whether all the elements are boolean-equivalent to true, either directly or through computation by the provided iterator.
Basically, the each method is called to check whether each data meets the iterator condition. If one of them does not meet the condition, the $ break exception is thrown and the exception is caught in the each method. Pay attention '!! ', You can convert some objects into the corresponding bool value:
!! {} True
!! [] True
!! ''False
!! 'String' true
!! 0 false
The following is an example:
Copy codeThe Code is as follows:
[]. All ()
//-> True (empty arrays have no elements that cocould be false-equivalent)
$ R (1, 5). all ()
//-> True (all values in [1 .. 5] are true-equivalent)
[0, 1, 2]. all ()
//-> False (with only one loop cycle: 0 is false-equivalent)
[9, 10, 15]. all (function (n) {return n> = 10 ;})
//-> False (the iterator will return false on 9)
$ H ({name: 'john', age: 29, oops: false}). all (function (pair) {return pair. value ;})
//-> False (the oops/false pair yields a value of false)