Home Web Front-end JS Tutorial A brief analysis of Prototype source code Enumerable part (2)_prototype

A brief analysis of Prototype source code Enumerable part (2)_prototype

May 16, 2016 pm 05:56 PM

There is one aspect that was not mentioned in the each method earlier, which is $break and $continue in the source code. These two variables are predefined, and their functions are equivalent to the break and continue statements in ordinary loops. For efficiency reasons, in some operations it is not necessary to completely traverse a collection (not limited to an array), so break and continue are still necessary.
For a loop, compare the following ways to exit the loop:

Copy the code The code is as follows:

var array_1 = [1,2,3];
var array_2 = ['a','b','c'];
(function(){
for( var i = 0, len = array_1.length; i < len; i ){
for(var j = 0, len_j = array_1.length; i < len_j; j ){
if('c ' === array_2[j]){
break;
}
console.log(array_2[j]);
}
}
})();// a,b,a,b,a,b
(function(){
for(var i = 0, len = array_1.length; i < len; i ){
try{
for(var j = 0, len_j = array_1.length; i < len_j; j ){
if('c' === array_2[j]){
throw new Error();
}
console.log(array_2[j]);
}
}catch(e){
console.log('Exit one level of loop');
}
}
})();//a,b,'Exit one level of loop',a,b,'Exit one level of loop',a,b,'Exit one level of loop'
(function() {
try{
for(var i = 0, len = array_1.length; i < len; i ){
for(var j = 0, len_j = array_1.length; i < len_j ; j ){
if('c' === array_2[j]){
throw new Error();
}
console.log(array_2[j]);
}
}
}catch(e){
console.log('Exit one level of loop');
}
})(); //a,b,'Exit one level of loop' Layer loop'

When we put error trapping at the corresponding loop level, we can interrupt the corresponding loop. The functions of break and break label (goto) can be realized. One such application requirement is that interrupts can be moved externally, which exactly meets the requirements of Enumerable.

Back to Enumerable, since the essence of each (each = function(iterator, context){}) method is a loop, its first parameter iterator does not contain a loop, so the break statement is called directly A syntax error will be reported, so the second method above is used in the Prototype source code.
Copy code The code is as follows:

Enumerable.each = function(iterator, context) {
var index = 0;
try{
this._each(function(value){
iterator.call(context, value, index );
});
}catch( e){
if(e != $break){
throw e;
}
}
return this;
};

Once If a $break is thrown during iterator execution, the loop will be interrupted. If it is not $break, then the corresponding error will be thrown and the program will be more stable. There are no special requirements for the definition of $break here. You can change it according to your own preferences, but it doesn't mean much.

Some methods in Enumerable have been implemented in some modern browsers (see the array of chrome native methods). Here is a comparison chart:


When implementing these methods, you can borrow native methods to improve efficiency. However, the source code does not borrow the native part, probably because Enumerable needs to be mixed into other objects in addition to the Array part.

Looking at the above diagram, we can clearly see the importance of each and map. The essence of map is still each, but each processes each item of the collection in sequence, and map is based on each. Also returns the processed results. Within Enumerable, map is an alias of the collect method, and the other alias is select, and the name collect is used internally.

Detection: all | any | include

These three methods do not involve processing the original collection, and the return values ​​are all of boolean type.

all : If all the elements in the Enumerable are equivalent to true, return true, otherwise return false

Copy code The code is as follows:

function all(iterator, context) {
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index);
});
return result;
}

For the all method, the two parameters inside are not necessary, so a function is provided internally to replace the iterator without actual parameters and directly return the original value. The name is Prototype.K. Prototype.K is defined at the beginning of the library and is a function that returns parameter values. Prototype.K = function(x){return x;}. In addition, in the all method, as long as the processing result of one item is false, the entire process can be abandoned (break), so the method of interrupting the loop at the beginning of this article is used. The final form is:
Copy code The code is as follows:

Prototype.K = function() {};
Enumerable.all = function(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;
}

The final result returned is a boolean type. If it deviates from all, let’s change the result:
Copy code The code is as follows:

function collect(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each( function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
}

At this time, results are an array. We do not interrupt the processing, save all the results and return them. Well, this is the collect method, or map method.


any: If one or more elements in the Enumerable are equivalent to true, then return true, otherwise return false. The principle is similar to all. all means to stop working when false is found, and any means to find false. If true, call it a day.
Copy code The code is as follows:

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;
}

include: Determine whether the specified object exists in the Enumerable, and compare based on the == operator One step of optimization for this method is to call the indexOf method. For arrays, if indexOf returns -1, it means that the corresponding element does not exist. If the collection does not have an indexOf method, it can only be searched and compared. There is no algorithm for the search and sum here, it is just traversal one by one. It is easy to rewrite it, but it is not commonly used, so it is estimated that no effort has been spent on optimizing this. So if the result is true, the efficiency is higher than when the result is false, it depends on luck.
Copy code The code is as follows:

function include(object) {
if (Object .isFunction(this.indexOf))//This judgment function should be very familiar
if (this.indexOf(object) != -1) return true;//If there is indexOf, just call

var directly found = false;
this.each(function(value) {//Efficiency issue here
if (value == object) {
found = true;
throw $break;
}
});
return found;
}


The following is a set of methods to filter data: Return a single element: max | min | detect returns an array : grep | findAll | reject | partition where max and min are not limited to comparison of numbers, comparison of characters is also possible. max(iterator, context) can still have two parameters. You can use iterator to process it first and then compare the values. The advantage of this is that it does not have to be limited to specific data types. For example, an object array takes the maximum value according to certain rules:
Copy code The code is as follows:

console.dir([{value : 3},{value : 1 },{value : 2}].max(function(item){
return item.value;
}));//3

So the implementation of the source code can be imagined , when compared directly, the implementation can be as follows:
Copy code The code is as follows:

function max() {
var result;
this.each(function(value) {
if (result == null || value >= result) //result==null is the first comparison
result = value;
});
return result;
}

After expansion, value will further become value = (return value after iterator processing):
Copy code The code is as follows :

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;
}

min has the same principle. The principles of detect and any are similar. any returns true when it finds a true, and detect returns the value that satisfies the true condition when it finds a true. The source code will not be posted. grep looks familiar. It is a unix/linux tool, and its function is also very familiar - it returns all elements that match the specified regular expression. However, unix/linux can only handle strings. The scope is expanded here, but the basic form remains unchanged. If each item in the collection is a string, then the implementation is as follows:
Copy code The code is as follows:

Enumerable.grep = function(filter) {
if(typeof filter == 'string'){
filter = new RegExp(filter);
}
var results = [];
this.each(function(value,index){
if(value.match(filter)){
results.push(value);
}
})
return results;
};

However, there is a collection to be processed that may not all be strings. In order to achieve a wider range of applications, the first thing to consider is the calling form. Looking at the above implementation, pay attention to this sentence:
if(value.match(filter))
where value is a string, and match is a method of String. Now we need to expand the supported types, or give each value Add the match method, or convert the form. Obviously the first type of noise was too loud, so the author changed his mind:
if (filter.match(value))
In this way, no matter what the value is, as long as the filter has a corresponding match method, the above is The RegExp object does not have a match method, so in the source code, the author extended the RegExp object:
RegExp.prototype.match = RegExp.prototype.test;
Note that the above match is essentially different from the String match. In this way, if value is an object, our filter only needs to provide the corresponding match method to detect the object. So there is:
Copy code The code is as follows:

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))//The native filter has no match method.
results.push( iterator.call(context, value, index));
});
return results;
}

For matching results, you can process them and then return them. This is The role of the iterator parameter. Different from the max method, grep uses an iterator to process the results when performing the main operation. Max uses an iterator to process the source data before performing the main operation. Because the filter in grep replaces the iterator in max. As for findAll, it is an enhanced version of grep. After reading grep, findAll is very simple. Reject is the twin version of findAll, which has exactly the opposite effect. partition is findAll reject, combined parent-child version. Please indicate when reprinting from Xiaoxi Shanzi [http://www.cnblogs.com/xesam/]
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

Demystifying JavaScript: What It Does and Why It Matters Demystifying JavaScript: What It Does and Why It Matters Apr 09, 2025 am 12:07 AM

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

Is JavaScript hard to learn? Is JavaScript hard to learn? Apr 03, 2025 am 12:20 AM

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

How to achieve parallax scrolling and element animation effects, like Shiseido's official website?
or:
How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? How to achieve parallax scrolling and element animation effects, like Shiseido's official website? or: How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? Apr 04, 2025 pm 05:36 PM

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

The Evolution of JavaScript: Current Trends and Future Prospects The Evolution of JavaScript: Current Trends and Future Prospects Apr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

See all articles