Home >Web Front-end >JS Tutorial >Tips for improving the performance of JavaScript programs using parameter arraying of Function.apply()_javascript tips
Let’s talk about the skills of Function.apply() in improving program performance.
Let’s start with the Math.max() function. Math.max can be followed by any number of parameters, and finally returns the maximum value among all parameters.
For example
alert(Math.max(5,8)) //8 alert(Math.max(5,7,9,3,1,6)) //9
But in many cases, we need to find the largest element in the array.
var arr=[5,7,9,1] alert(Math.max(arr)) // 这样却是不行的。一定要这样写 function getMax(arr){ var arrLen=arr.length; for(var i=0,ret=arr[0];i<arrLen;i++){ ret=Math.max(ret,arr[i]); } return ret; }
Writing like this is cumbersome and inefficient. If you use apply, look at the code:
function getMax2(arr){ return Math.max.apply(null,arr) }
The two pieces of code achieve the same purpose, but getMax2 is much more elegant, efficient and concise.
Look at the performance test:
getMax performance test
var myArr=new Array() function fillRnd(arrLen){ //填入 arrLen个1-10的随机数字到数组 for(var i=0,arr=[];i<arrLen;i++){ arr[i]=Math.ceil(Math.random()*10) } return arr } function getMax(arr){ var arrLen=arr.length; for(var i=0,ret=arr[0];i<arrLen;i++){ ret=Math.max(ret,arr[i]); } return ret; } function getMax2(arr){ return Math.max.apply(null,arr) } myArr=fillRnd(20*10000) //生成20万个随机数填到数组 var t1=new Date() var max1=getMax(myArr) var t2=new Date() var max2=getMax2(myArr) var t3=new Date() if (max1!==max2) alert("error") alert([t3-t2,t2-t1]) //在我机器上 96,464 .不同的机器,结果可能有差异
By comparing 200,000 data, the getMax2 time is 96ms and the getmax time is 464. The difference between the two is 5 times
Another example is the push method of an array.
var arr1=[1,3,4]; var arr2=[3,4,5];
If we want to expand arr2, and then append to arr1 one by one, finally let arr1=[1,3,4,3,4,5]
arr1.push(arr2) obviously doesn’t work. Because doing this will get [1,3,4, [3,4,5] ]
We can only use a loop to push one by one (of course you can also use arr1.concat(arr2) but the concat method does not change arr1 itself)
var arrLen=arr2.length for(var i=0;i<arrLen;i++){ arr1.push(arr2[i]) }
Since applying Apply , things have become so simple
Array.prototype.push.apply(arr1,arr2)
Attachment: How to optimize the performance of JavaScript scripts
With the development of the Internet and the improvement of network speed and machine speed, more and more websites use rich client technology. Now Ajax is the most popular method. JavaScript is an interpreted language, so whether it can reach the same level as C/Java limits what it can do on the client. In order to improve its performance, I want to build on what I have done for JavaScript before. Many tests are used to talk about their own experiences, hoping to help everyone improve their JavaScript script performance.
Language level
Loop
Loop is a very commonly used control structure. Most things rely on it to complete. In JavaScript, we can use three kinds of loops: for(;;), while(), and for(in). In fact, this The efficiency of for(in) among the three types of loops is extremely poor because it needs to query the hash key, so it should be used as little as possible if possible. The performance of for(;;) and while loop should be said to be basically equivalent (when used in daily use).
In fact, how to use these two loops is very particular. I had some interesting situations in my testing, see the appendix. The final conclusion is:
If the loop variable is incrementing or decrementing, do not assign a value to the loop variable alone. You should use the nested ++ or - operator when it is last read.
If you want to compare with the length of the array, you should put the length attribute of the array into a local variable in advance to reduce the number of queries.
Local variables and global variables
Local variables are accessed faster than global variables, because global variables are actually members of the global object, while local variables are placed on the stack of the function.
Do not use Eval
Using eval is equivalent to calling the interpretation engine again to run the content at runtime, which takes a lot of time. At this time, function templates can be implemented using closures supported by JavaScript (for details on closures, please refer to relevant content on functional programming)
Reduce object lookup
Because of the interpretability of JavaScript, a.b.c.d.e requires at least 4 query operations. First check a, then check b in a, then check c in b, and so on. Therefore, if such expressions appear repeatedly, such expressions should be kept as rare as possible as much as possible. You can use local variables to put them in a temporary place for querying.
This can be combined with looping, because we often need to loop based on the length of strings and arrays, and usually this length is unchanged. For example, every time a.length is queried, an additional operation is required, and If you set var len=a.length in advance, there will be one less query.
String concatenation
If you are appending a string, it is best to use the s+=anotherStr operation instead of using s=s+anotherStr.
If you want to concatenate multiple strings, you should use less +=, such as
s+=a;s+=b;s+=c; should be written as
s+=a + b + c; and if you are collecting strings, such as performing += operations on the same string multiple times, it is best to use a cache. How to use it? Use JavaScript arrays to collect, and finally use the join method to connect, as follows
var buf = new Array();for(var i = 0; i < 100; i++){ buf.push(i.toString());}var all = buf.join("");类型转换
Type conversion is a common mistake everyone makes, because JavaScript is a dynamically typed language and you cannot specify the type of a variable.
1. Convert numbers into strings and use "" + 1. Although it looks a bit ugly, in fact this is the most efficient, in terms of performance:
("" +) > String() > .toString() > new String()
This is actually somewhat similar to the "direct quantity" below. Try to use internal operations that can be used at compile time to be faster than user operations used at runtime.
String() is an internal function, so it is very fast, while .toString() queries the function in the prototype, so it is not as fast. new String() is used to return an exact copy.
2. Converting floating point numbers to integers is more error-prone. Many people like to use parseInt(). In fact, parseInt() is used to convert strings into numbers, not between floating point numbers and integers. , we should use Math.floor() or Math.round().
In addition, unlike the problem in object search in Section 2, Math is an internal object, so Math.floor() actually does not have many query methods and calling times, and is the fastest.
3. For custom objects, if the toString() method is defined for type conversion, it is recommended to explicitly call toString(), because the internal operation will try the object's toString() after trying all possibilities. The method tests whether it can be converted into String, so calling this method directly will be more efficient
Use direct quantities
In fact, this impact is relatively small and can be ignored. What does it mean to use direct quantities? For example, JavaScript supports using [param, param, param,...] to directly express an array. In the past, we all used new Array(param, param,...). Using the former is directly interpreted by the engine. , the latter requires calling an Array internal constructor, so it is slightly faster.
Similarly, var foo = {} is faster than var foo = new Object();, and var reg = /../; is faster than var reg=new RegExp().
String traversal operation
To perform loop operations on strings, such as replacement and search, regular expressions should be used, because the loop speed of JavaScript itself is relatively slow, and the operation of regular expressions is an API written in C, and the performance is very good.
Advanced Objects
Custom advanced objects and Date and RegExp objects will consume a lot of time during construction. If it can be reused, caching should be used.
DOM related
Insert HTML
Many people like to use document.write in JavaScript to generate content for the page. In fact, this is less efficient. If you need to insert HTML directly, you can find a container element, such as specifying a div or span, and set their innerHTML to insert your own HTML code into the page.
Object Query
Using [""] to query is faster than .items(). This is the same as the previous idea of reducing object search. Calling .items() adds a query and function call.
Create DOM node
Usually we may use strings to write HTML directly to create nodes, but actually do this
The validity of the code cannot be guaranteed
String operation efficiency is low
So you should use the document.createElement() method, and if there is a ready-made template node in the document, you should use the cloneNode() method, because after using the createElement() method, you need to set the attributes of the element multiple times, use cloneNode() can reduce the number of attribute settings - similarly, if you need to create many elements, you should prepare a template node first.
Timer
If you are targeting code that is constantly running, you should not use setTimeout, but setInterval. setTimeout resets a timer each time.
Others
Script engine
According to my test, the efficiency of Microsoft's JScript is much worse than Mozilla's Spidermonkey, both in terms of execution speed and memory management, because JScript is basically not updated now. But SpiderMonkey cannot use ActiveXObject
File Optimization
File optimization is also a very effective method. Delete all spaces and comments and put the code into one line to speed up the download. Note that it is the download speed rather than the parsing speed. If it is local, comments and Spaces do not affect interpretation and execution speed.
Summary
This article summarizes some of the methods I have found in JavaScript programming to improve JavaScript running performance. In fact, these experiences are based on several principles:
It is faster to just use what is readily available. For example, local variables are faster than global variables, direct variables are faster than constructing objects at runtime, etc.
Reduce the number of executions as much as possible, such as caching those that require multiple queries first.
Use built-in language features as much as possible, such as string links.
Use the APIs provided by the system as much as possible, because these APIs are compiled binary codes and have high execution efficiency
同时,一些基本的算法上的优化,同样可以用在JavaScript中,比如运算结构的调整,这里就不再赘述了。但是由于JavaScript是解释型的,一般不会在运行时对字节码进行优化,所以这些优化仍然是很重要的。
当然,其实这里的一些技巧同样使用在其他的一些解释型语言中,大家也可以进行参考。
由于是以前做过的测试,测试代码已经不全,我补充了一部分如下:
var print; if(typeof document != "undefined" ){ print = function(){ document.write(arguments[0]); } }else if(typeof WScript != "undefined" ){ print = function(){ WScript.Echo(arguments[0],arguments[1],arguments[2]); } } function empty(){ } function benchmark(f){ var i = 0; var start = (new Date()).getTime(); while(i < pressure){ f(i++); } var end = (new Date()).getTime(); WScript.Echo(end-start); } /* i=0 start = (new Date()).getTime(); while(i < 60000){ c = [i,i,i,i,i,i,i,i,i,i]; i++; } end = (new Date()).getTime(); WScript.Echo(end-start); i=0 start = (new Date()).getTime(); while(i < 60000){ c = new Array(i,i,i,i,i,i,i,i,i,i); i++; } var end = (new Date()).getTime(); WScript.Echo(end-start); */ function internCast(i){ return "" + i; } function StringCast(i){ return String(i) } function newStringCast(i){ return new String(i) } function toStringCast(i){ return i.toString(); } function ParseInt(){ return parseInt(j); } function MathFloor(){ return Math.floor(j); } function Floor(){ return floor(j); } var pressure = 50000; var a = ""; var floor = Math.floor; j = 123.123; print("-------------\nString Conversion Test"); print("The empty:", benchmark(empty)); print("intern:", benchmark(internCast)); print("String:"); benchmark(StringCast); print("new String:"); benchmark(newStringCast); print("toString:"); benchmark(toStringCast); print("-------------\nFloat to Int Conversion Test"); print("parseInt"); benchmark(ParseInt); print("Math.floor"); benchmark(MathFloor); print("floor") benchmark(Floor); function newObject(){ return new Object(); } function internObject(){ return {}; } print("------------\nliteral Test"); print("runtime new object", benchmark(newObject)); print("literal object", benchmark(internObject));
附录2
代码1:
for(var i=0;i<100;i++){ arr[i]=0; }
代码2:
var i = 0; while(i < 100){ arr[i++]=0; }
代码3:
var i = 0; while(i < 100){ arr[i]=0; i++; }
在firefox下测试这两段代码,结果是代码2优于代码1和3,而代码1一般优于代码3,有时会被代码3超过;而在IE 6.0下,测试压力较大的时候(如测试10000次以上)代码2和3则有时候优于代码1,有时候就会远远落后代码1,而在测试压力较小(如5000次),则代码2>代码3>代码1。
代码4:
var i = 0; var a; while(i < 100){ a = 0; i++; }
代码5:
var a; for(var i=0;i<100;i++){ a = 0; }
上面两段代码在Firefox和IE下测试结果都是性能接近的。
代码6:
var a; var i=0; while(i<100){ a=i; i++; }
代码7:
var a; var i=0; while(i<100){ a=i++; }
代码8:
var a; for(var i=0;i<100;i++){ a = i; }
代码9:
var a; for(var i=0;i<100;){ a = i++; }
这四段代码在Firefox下6和8的性能接近,7和9的性能接近,而6, 8 < 7, 9;
最后我们来看一下空循环
代码10:
for(var i=0;i<100;i++){ }
代码11:
var i; while(i<100){ i++; }
最后的测试出现了神奇的结果,Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值,于是我没有放在一开始给大家看。