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
在修改一個問題的時候,發(fā)現(xiàn)在竟然用eval計算數(shù)組的和,不知道當時為什么會這樣寫(有點不過腦子),不過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);
}
看一下結(jié)果:
JavaScript使用eval計算表達式
先說說test函數(shù)中有哪些問題:
1) 使用eval計算表達式
2) 使用sumArr數(shù)組,多增加內(nèi)存的使用,計算數(shù)組內(nèi)值的和,沒必要增加一個數(shù)組.
1) 最直接的方式,直接在for循環(huán)中進行計算
2) 使用JavaScript中reduce函數(shù)計算.
3) 使用Function代替eval函數(shù)計算.
來測試這幾種方式,那個性能比較好.
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瀏覽器執(zhí)行結(jié)果:
使用Edge瀏覽器執(zhí)行eval和Function性能測試
然后看看Firefox瀏覽器的執(zhí)行結(jié)果:
使用Firefox瀏覽器執(zhí)行eval和Function性能測試
通過測試結(jié)果得出:
1) 在循環(huán)內(nèi),直接求和的方式在數(shù)組長度不多的情況,性能最好
2) reduce在數(shù)組長度相對多之后,性能比for求值性能好
3) Function在性能上和eval半斤八兩
個人能力有限,如果您發(fā)現(xiàn)有什么不對,請私信我
如果您覺得對您有用的話,可以點個贊或者加個關(guān)注,歡迎大家一起進行技術(shù)交流
val加密的終極用法
Eval加密,做為一種傳統(tǒng)且古老的JS代碼加密方法,相信很多人都知道。
例如這個在線Eval加密:
https://www.fairysoftware.com/js_jia_mi_eval.html
但這種Eval加密,其實并不能算真正的加密,只能算一種編碼,可以被很容易的逆向得到原始代碼。
但本文要介紹的,并非這種Eval加密。
而是借助Eval,并結(jié)合專業(yè)JS混淆加密所實現(xiàn)的,用這個方法加密得到的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/)進行混淆加密:
得到如下加密代碼:
如上圖所示,雖然加密后的代碼已經(jīng)非常混亂。
但如果希望console、函數(shù)名也“消失”,則可以借且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中執(zhí)行。
再對上面的代碼進行混淆加密:
加密生成了新的代碼:
在新生成的代碼中,console、函數(shù)名,都找不到了,原始代碼的線索徹底消失。
因為在用JShaman混淆加密時,把原始代碼整體當做字符串加密了,原本代碼中的語法關(guān)鍵字、系統(tǒng)變量、函數(shù)名等等,全被加密了。
通常來說,直接用JShaman加密得到的JS代碼,已可滿足99%的需求。但如果遇到特別的場合、加密強度要求的極高,那么,可以用本文講述的方法,對JS代碼改造再進行混淆加密。但需注意:轉(zhuǎn)成字符串的代碼量不可太大。
val()的使用
eval() 函數(shù)可將字符串轉(zhuǎn)換為代碼執(zhí)行,并返回一個或多個值
eval調(diào)用時,實例為eval( "( javascript代碼 )" )
eval()的返回值
eval()的返回值遵循以下規(guī)則:
1.如果eval()的參數(shù)不是字符串,那么eval()將直接返回參數(shù)。
2.如果eval()的參數(shù)是字符串,那么eval()將這個字符串解析成代碼后進行執(zhí)行,并返回最后一行代碼執(zhí)行的結(jié)果。
3.如果字符串無法解析成合法的代碼,eval()將拋出SyntaxError錯誤。
舉例1(eval的參數(shù)不是字符串):
運行結(jié)果(谷歌瀏覽器測試):
舉例2(eval的參數(shù)是字符串):
運行結(jié)果(谷歌瀏覽器測試):
當然,如果不使用eval()方法,上面的代碼可以使用匿名函數(shù)寫
舉例3(字符串無法解析成合法的代碼):
運行結(jié)果(谷歌瀏覽器測試):此時可以看到 谷歌瀏覽器控制臺報錯
eval()的兼容性問題
IE6/7/8不兼容
使用IE8來測試代碼:
沒有彈出框,控制臺報錯:
解決方法:
a)var s = "[function(){alert('Test!')}][0]";
b)var s = "0?0:function(){alert('Test!')}";
當然這個解決方法是從國外論壇里面找到(網(wǎng)站:http://stackoverflow.com/questions/6807649/problems-with-ie9-javascript-eval)
大意是:這在JScript解釋器里面是一個bug,它不會出現(xiàn)在IE9除非你使用混雜模式或兼容來看。IE8錯誤將這個函數(shù)表達式解釋為函數(shù)的聲明,使得它沒有任何的返回值。所以你可以寫成其他比較典型的表達式,從從而在JScript解釋器中構(gòu)成一個表達式
那么我們就知道IE6/7/8使用JScrip解釋器來解析eval()把參數(shù)當初函數(shù)聲明,沒有返回值,所以我么可以把eval()函數(shù)里面的字符串代碼寫成一個表達式,即可以寫成:
[function(){alert('Test!')}][0] 或 0?0:function(){alert('Test!')}
改代碼:
在IE8里面測試結(jié)果:
最后利用ietester工具測試在IE6也同樣沒有問題。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。