Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
在修改一個問題的時候,發現在竟然用eval計算數組的和,不知道當時為什么會這樣寫(有點不過腦子),不過eval盡量不要使用,在MDN有2個不建議使用eval的建議:
如果要使用evel,可以使用Function進行替代,在MDN說Function比eval快,在后面的測試中,Function并沒有比eval快很多.
function generateRandomArray(len) {
let arr = [];
for (let i = 0; i < len; i++) {
let value = Math.floor(Math.random() * len * 10);
arr.push(value);
}
return arr;
}
function test() {
let sumArr = [];
let randomArray = generateRandomArray(16);
for (var i = 0, len = randomArray.length; i < len; i++) {
//處理其他的邏輯
sumArr.push(randomArray[i]);
}
let expression = sumArr.join('+');
let sum = eval(expression); //使用eval計算 '1+2'表達式
console.log(expression);
console.log(sum);
}
看一下結果:
JavaScript使用eval計算表達式
先說說test函數中有哪些問題:
1) 使用eval計算表達式
2) 使用sumArr數組,多增加內存的使用,計算數組內值的和,沒必要增加一個數組.
1) 最直接的方式,直接在for循環中進行計算
2) 使用JavaScript中reduce函數計算.
3) 使用Function代替eval函數計算.
來測試這幾種方式,那個性能比較好.
function generateRandomArray(len) {
let arr = [];
for (let i = 0; i < len; i++) {
let value = Math.floor(Math.random() * len * 10);
arr.push(value);
}
return arr;
}
function evalTest(randomArray, testLen) {
let sum = 0;
let sumArray = [];
console.time('eval ' + testLen);
for (var i = 0, len = randomArray.length; i < len; i++) {
sumArray.push(randomArray[i]);
}
sum = eval(sumArray.join('+')); //使用eval計算表達式
console.timeEnd('eval ' + testLen);
console.error('eval:' + sum);
}
function forTest(randomArray, testLen) {
let sum = 0;
console.time('for ' + testLen);
for (var i = 0, len = randomArray.length; i < len; i++) {
//最簡單直接的方式,直接求和運算
sum += randomArray[i];
}
console.timeEnd('for ' + testLen);
console.error('for:' + sum);
}
function readuceTest(randomArray, testLen) {
let sum = 0;
console.time('reduce ' + testLen);
sum = randomArray.reduce((previousValue, currentValue) => {
return previousValue + currentValue
}, 0); //使用reduce
console.timeEnd('reduce ' + testLen);
console.error('reduce:' + sum);
}
function functionTest(randomArray, testLen) {
let sum = 0;
let sumArray = [];
console.time('function ' + testLen);
for (var i = 0, len = randomArray.length; i < len; i++) {
sumArray.push(randomArray[i]);
}
//使用Function
sum = new Function('"use strict"; return ' + sumArray.join('+') + ';')();
console.timeEnd('function ' + testLen);
console.error('function:' + sum);
}
function allTest() {
var testLenArray = [16, 64, 128];
for (var i = 0, len = testLenArray.length; i < len; i++) {
let randomArray = generateRandomArray(testLenArray[i]);
evalTest(randomArray, testLenArray[i]);
forTest(randomArray, testLenArray[i]);
readuceTest(randomArray, testLenArray[i]);
functionTest(randomArray, testLenArray[i]);
}
}
allTest();
先看看Edge瀏覽器執行結果:
使用Edge瀏覽器執行eval和Function性能測試
然后看看Firefox瀏覽器的執行結果:
使用Firefox瀏覽器執行eval和Function性能測試
通過測試結果得出:
1) 在循環內,直接求和的方式在數組長度不多的情況,性能最好
2) reduce在數組長度相對多之后,性能比for求值性能好
3) Function在性能上和eval半斤八兩
個人能力有限,如果您發現有什么不對,請私信我
如果您覺得對您有用的話,可以點個贊或者加個關注,歡迎大家一起進行技術交流
val加密的終極用法
Eval加密,做為一種傳統且古老的JS代碼加密方法,相信很多人都知道。
例如這個在線Eval加密:
https://www.fairysoftware.com/js_jia_mi_eval.html
但這種Eval加密,其實并不能算真正的加密,只能算一種編碼,可以被很容易的逆向得到原始代碼。
但本文要介紹的,并非這種Eval加密。
而是借助Eval,并結合專業JS混淆加密所實現的,用這個方法加密得到的JS代碼,安全強度非常高。
下面,進行演示:
例如一段JS代碼:
function get_copyright(){
var domain = "jshaman.com";
var from_year = 2017;
var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
return copyright;
}
console.log(get_copyright());
用jshaman(https://www.jshaman.com/)進行混淆加密:
得到如下加密代碼:
如上圖所示,雖然加密后的代碼已經非常混亂。
但如果希望console、函數名也“消失”,則可以借且eval。
將原始代碼改造成以下形式:
var str = `
function get_copyright(){
var domain = "jshaman.com";
var from_year = 2017;
var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
return copyright;
}
console.log(get_copyright());
`
eval(str)
說明:將原來的代碼整體做為字符串都包裹在了eval中執行。
再對上面的代碼進行混淆加密:
加密生成了新的代碼:
在新生成的代碼中,console、函數名,都找不到了,原始代碼的線索徹底消失。
因為在用JShaman混淆加密時,把原始代碼整體當做字符串加密了,原本代碼中的語法關鍵字、系統變量、函數名等等,全被加密了。
通常來說,直接用JShaman加密得到的JS代碼,已可滿足99%的需求。但如果遇到特別的場合、加密強度要求的極高,那么,可以用本文講述的方法,對JS代碼改造再進行混淆加密。但需注意:轉成字符串的代碼量不可太大。
val()的使用
eval() 函數可將字符串轉換為代碼執行,并返回一個或多個值
eval調用時,實例為eval( "( javascript代碼 )" )
eval()的返回值
eval()的返回值遵循以下規則:
1.如果eval()的參數不是字符串,那么eval()將直接返回參數。
2.如果eval()的參數是字符串,那么eval()將這個字符串解析成代碼后進行執行,并返回最后一行代碼執行的結果。
3.如果字符串無法解析成合法的代碼,eval()將拋出SyntaxError錯誤。
舉例1(eval的參數不是字符串):
運行結果(谷歌瀏覽器測試):
舉例2(eval的參數是字符串):
運行結果(谷歌瀏覽器測試):
當然,如果不使用eval()方法,上面的代碼可以使用匿名函數寫
舉例3(字符串無法解析成合法的代碼):
運行結果(谷歌瀏覽器測試):此時可以看到 谷歌瀏覽器控制臺報錯
eval()的兼容性問題
IE6/7/8不兼容
使用IE8來測試代碼:
沒有彈出框,控制臺報錯:
解決方法:
a)var s = "[function(){alert('Test!')}][0]";
b)var s = "0?0:function(){alert('Test!')}";
當然這個解決方法是從國外論壇里面找到(網站:http://stackoverflow.com/questions/6807649/problems-with-ie9-javascript-eval)
大意是:這在JScript解釋器里面是一個bug,它不會出現在IE9除非你使用混雜模式或兼容來看。IE8錯誤將這個函數表達式解釋為函數的聲明,使得它沒有任何的返回值。所以你可以寫成其他比較典型的表達式,從從而在JScript解釋器中構成一個表達式
那么我們就知道IE6/7/8使用JScrip解釋器來解析eval()把參數當初函數聲明,沒有返回值,所以我么可以把eval()函數里面的字符串代碼寫成一個表達式,即可以寫成:
[function(){alert('Test!')}][0] 或 0?0:function(){alert('Test!')}
改代碼:
在IE8里面測試結果:
最后利用ietester工具測試在IE6也同樣沒有問題。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。