国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

eval到底哪里不好?

elva / 2995人閱讀

摘要:五總結(jié)和應(yīng)對(duì)方案安全性分析是否安全主要由數(shù)據(jù)源決定,如果數(shù)據(jù)源不安全,只是提供了一種攻擊方法而已。方案嚴(yán)格管控?cái)?shù)據(jù)源。方案低頻使用時(shí)影響不大,不要高頻使用,建議尋找替代方案。方案了解直接調(diào)用和間接調(diào)用的區(qū)別,遇到問題時(shí)不要懵逼即可。

為什么要少用eval?

eval是 js 中一個(gè)強(qiáng)大的方法。都說(shuō)eval == evil等于true,這篇文章將研討eval的幾個(gè)缺點(diǎn)和使用注意事項(xiàng)。

目錄

一、安全性

二、運(yùn)行效率

三、作用域

四、內(nèi)存▲

五、總結(jié)和應(yīng)對(duì)方案

一、安全性

太明顯了,暫不討論

二、運(yùn)行效率

都知道 eval 比較慢,到底慢多少,自己測(cè)測(cè)看,下面是代碼(對(duì)比運(yùn)行 1萬(wàn)次 eval("sum++") 和 500萬(wàn)次 sum++ 所需要的時(shí)間)

var getTime = function(){
  // return Date.now();
  return new Date().getTime()     //兼容ie8
}
var sum;
// 測(cè)試 1萬(wàn)次 eval("sum++")
sum = 0;
var startEval = getTime();
for(var i = 0;i<10000;i++){
  eval("sum++");
}
var durEval = getTime() - startEval;
console.log("durEval = ",durEval,"ms");
// 測(cè)試 500萬(wàn)次 sum++
sum = 0;
var startCode = getTime();
for(var i = 0;i<5000000;i++){
  sum++;
}
var durCode = getTime() - startCode;
console.log("durCode = ",durCode,"ms");
//輸出結(jié)果
console.log("直接運(yùn)行 sum++ 的速度約是 運(yùn)行 eval("sum++") 的",(durEval * 500 / durCode).toFixed(0),"倍");
測(cè)試結(jié)果

在同一臺(tái)PC上,測(cè)試3款瀏覽器和nodejs環(huán)境,結(jié)果如下:

Chrome 73

durEval =  236 ms
durCode =  14 ms
直接運(yùn)行 sum++ 的速度約是 運(yùn)行 eval("sum++") 的 8429 倍

Firefox 65

durEval =  766 ms
durCode =  167 ms
直接運(yùn)行 sum++ 的速度約是 運(yùn)行 eval("sum++") 的 2293 倍

IE8

durEval = 417ms
durCode = 572ms
直接運(yùn)行 sum++ 的速度約是 運(yùn)行 eval("sum++") 的365倍

Nodejs 10.15.0

durEval =  5 ms
durCode =  14 ms
直接運(yùn)行 sum++ 的速度約是 運(yùn)行 eval("sum++") 的 179 倍

Chrome 的 V8 果然是王者,F(xiàn)irefox 在運(yùn)行eval的PK上輸給了古董IE8,node環(huán)境中eval的表現(xiàn)最好(只慢100多倍)

三、作用域

在作用域方面,eval 的表現(xiàn)讓人費(fèi)解。直接調(diào)用時(shí):當(dāng)前作用域;間接調(diào)用時(shí):全局作用域

3.1 直接調(diào)用

eval被直接調(diào)用并且調(diào)用函數(shù)就是eval本身時(shí),作用域?yàn)楫?dāng)前作用域,function中的foo被修改了,全局的foo沒被修改。

var foo = 1;
function test() {
    var foo = 2;
    eval("foo = 3");
    return foo;
}
console.log(test());    // 3
console.log(foo);       // 1
3.2間接調(diào)用

間接調(diào)用eval時(shí) 執(zhí)行的作用域?yàn)槿肿饔糜颍瑑蓚€(gè)function中的foo都沒有被修改,全局的foo被修改了。

var foo = 1;
(function(){
  var foo = 1;
  function test() {
      var foo = 2;
      var bar = eval;
      bar("foo = 3");
      return foo;
  }
  console.log(test());    // 2
  console.log(foo);       // 1
})();
console.log(foo);         // 3
四、內(nèi)存 ▲

使用eval會(huì)導(dǎo)致內(nèi)存的浪費(fèi),這是本文要討論的重點(diǎn)。
下面用測(cè)試結(jié)果來(lái)對(duì)比,使用eval不使用eval 的情況下,以下代碼內(nèi)存的消耗情況。

4.1 不用eval的情況
var f1 = function(){          // 創(chuàng)建一個(gè)f1方法
  var data = {
    name:"data",
    data: (new Array(50000)).fill("data 111 data")
    };                        // 創(chuàng)建一個(gè)不會(huì)被使用到的變量
  var f = function(){         // 創(chuàng)建f方法然后返回
    console.log("code:hello world");
  };
  return f;
};
var F1 = f1();
測(cè)試結(jié)果

在Chrome上查看內(nèi)存使用情況,開發(fā)者工具->Momery->Profiles->Take snapshot,給內(nèi)存拍個(gè)快照。

為了便于查找,在過(guò)濾器中輸入window,查看當(dāng)前域的window

可以看到,window占用了686122%的內(nèi)存。然后在其中找F1變量:

F1占用了320%的內(nèi)存。

這似乎說(shuō)明不了什么。沒有對(duì)比就沒有傷害,下面我們來(lái)傷害一下eval

4.2 使用eval的情況

修改上面的代碼,把 console.log 修改為 eval 運(yùn)行:

- console.log("code:hello world");
+ eval("console.log("eval:hello world");");
測(cè)試結(jié)果

方法同上。在Chrome上查看內(nèi)存使用情況,開發(fā)者工具->Momery->Profiles->Take snapshot

window占用了2510484%的內(nèi)存,其中F1占用了200140,相當(dāng)于總量的3%的內(nèi)存,F1.context.data,占用了200044,約等于F1的占用量,可見這些額外的內(nèi)存開銷都是來(lái)自于F1.context.data

4.3 分析

使用eval時(shí):F1占用了2001403%的內(nèi)存;
不用eval時(shí):F1占用了320%的內(nèi)存;

這樣的差別來(lái)自于javascript引擎的優(yōu)化。在方法f1運(yùn)行時(shí)創(chuàng)建了data,接著創(chuàng)建了一個(gè)方法ff中可以訪問到data,但它沒有使用data,然后f被返回賦值給變量F1,經(jīng)過(guò)javascript引擎優(yōu)化,這時(shí)data不會(huì)被加入到閉包中,同時(shí)也沒有其他指針指向datadata的內(nèi)存就會(huì)被回收。然而在f中使用了eval后,情況就不同了,eval太過(guò)強(qiáng)大,導(dǎo)致javascript引擎無(wú)法分辨f會(huì)不會(huì)使用到data,從而只能將全部的環(huán)境變量(包括data),一起加入到閉包中,這樣F1就間接引用了datadata的內(nèi)存就不會(huì)被回收。從而導(dǎo)致了額外的內(nèi)存開銷。

我們可以進(jìn)一步測(cè)試,這時(shí)在開發(fā)者工具->Console 中輸入:

F1 = "Hello"  //重設(shè)F1,這樣就沒什么引用到data了

然后用同樣的方法查看內(nèi)存,可以發(fā)現(xiàn) window占用的內(nèi)存,從200000+下降到了60000+

說(shuō)到這里,再回頭看eval奇怪的作用域。直接調(diào)用時(shí):當(dāng)前作用域;間接調(diào)用時(shí):全局作用域,也就可以理解了。當(dāng)間接調(diào)用時(shí),javascript引擎不知道它是eval,優(yōu)化時(shí)就會(huì)移除不需要的變量,如果eval中用到了那些變量,就會(huì)發(fā)生意想不到的事情。這違背了閉包的原則,變得難以理解。索性把間接調(diào)用的作用域設(shè)置為了全局。

五、總結(jié)和應(yīng)對(duì)方案 安全性

分析:eval是否安全主要由數(shù)據(jù)源決定,如果數(shù)據(jù)源不安全,eval只是提供了一種攻擊方法而已。
方案:嚴(yán)格管控?cái)?shù)據(jù)源。

運(yùn)行效率

分析:eval比直接運(yùn)行慢很多倍,但主要的消耗在于編譯代碼過(guò)程,簡(jiǎn)單項(xiàng)目中,不會(huì)這樣高頻率的運(yùn)行eval
方案:低頻使用時(shí)影響不大,不要高頻使用,建議尋找替代方案。

作用域

分析:實(shí)際項(xiàng)目中直接調(diào)用都很少,間接調(diào)用更是少之又少。
方案:了解直接調(diào)用和間接調(diào)用的區(qū)別,遇到問題時(shí)不要懵逼即可。

內(nèi)存

分析:實(shí)際應(yīng)用中很常見,卻很少有人會(huì)注意到內(nèi)存管理,大項(xiàng)目中被重復(fù)使用會(huì)浪費(fèi)較多的內(nèi)存。
方案:優(yōu)化編碼規(guī)范,使用eval時(shí)注意那些沒有被用到局部變量。

源碼鏈接:github

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/103428.html

相關(guān)文章

  • 關(guān)于javascript中的this指向

    摘要:當(dāng)中的是一個(gè)用于指向當(dāng)前上下文對(duì)象的關(guān)鍵字。創(chuàng)建實(shí)例時(shí)的構(gòu)造函數(shù)中的,永遠(yuǎn)指向那個(gè)實(shí)例后對(duì)象,不是外部環(huán)境使用來(lái)調(diào)用函數(shù)時(shí),先改變其上下文環(huán)境,在對(duì)其構(gòu)造函數(shù)進(jìn)行調(diào)用。 javascript 當(dāng)中的 this是一個(gè)用于指向當(dāng)前上下文對(duì)象的關(guān)鍵字。在面向?qū)ο缶幊碳叭粘i_發(fā)當(dāng)中我們經(jīng)常與其打交道,初學(xué)javscript的朋友非常容易誤入歧途從而理解錯(cuò)誤。 上下文對(duì)象概念 在我的深入貫徹閉包...

    蘇丹 評(píng)論0 收藏0
  • PHP 安全:如何防范用戶上傳 PHP 可執(zhí)行文件

    摘要:每個(gè)專業(yè)的開發(fā)者都知道用戶上傳的文件都是極其危險(xiǎn)的。如何防止引入用戶上傳的文件重命名文件名可以嗎不,辦不到解析器不關(guān)心文件的后綴名。服務(wù)器通常被設(shè)置成執(zhí)行文件并將執(zhí)行結(jié)果回復(fù)輸出。如何進(jìn)行檢查這很簡(jiǎn)單。用戶可以上傳文件到該站點(diǎn)。 showImg(https://segmentfault.com/img/remote/1460000017893665?w=1200&h=627); 每個(gè)專...

    wangxinarhat 評(píng)論0 收藏0
  • 你應(yīng)該要知道的作用域和閉包

    摘要:寫在前面對(duì)于一個(gè)前端開發(fā)者,應(yīng)該沒有不知道作用域的。欺騙詞法作用域有兩個(gè)機(jī)制可以欺騙詞法作用域和。關(guān)于你不知道的的第一部分作用域和閉包已經(jīng)結(jié)束了,但是,更新不會(huì)就此止住未完待續(xù) 這是《你不知道的JavaScript》的第一部分。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 寫在前面 對(duì)于一個(gè)前端開發(fā)者,應(yīng)該沒有不知道作用域的。它是一個(gè)既簡(jiǎn)單有復(fù)雜的概念,簡(jiǎn)單到每行代碼都有它的影子...

    JouyPub 評(píng)論0 收藏0
  • 重讀你不知道的JS (上) 第一節(jié)二章

    摘要:詞法作用域定義在詞法階段的作用域由你在寫代碼時(shí)將變量和塊作用域?qū)懺谀膩?lái)決定的,因此當(dāng)詞法分析器處理代碼時(shí)會(huì)保持作用域不變。欺騙詞法作用域在詞法分析器處理過(guò)后依然可以修改作用域。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡(jiǎn)單易用的語(yǔ)言,又是一門具有許多復(fù)雜微妙技術(shù)的語(yǔ)言,即使是經(jīng)驗(yàn)豐富的 JavaScript 開發(fā)者,如果沒...

    baihe 評(píng)論0 收藏0
  • JS學(xué)習(xí)系列 02 - 詞法作用域

    摘要:作用域有兩種主要工作模型詞法作用域和動(dòng)態(tài)作用域。可能會(huì)有一些同學(xué)認(rèn)為是,那就是沒有搞清楚詞法作用域的概念。在嚴(yán)格模式下,在運(yùn)行時(shí)有自己的詞法作用域,意味著其中的聲明無(wú)法修改所在的作用域。 1. 兩種作用域 作用域我們知道是一套規(guī)則,用來(lái)管理引擎如何在當(dāng)前作用域以及嵌套的子作用域中根據(jù)標(biāo)識(shí)符名稱進(jìn)行變量查找。 作用域有兩種主要工作模型:詞法作用域和動(dòng)態(tài)作用域。 大多數(shù)語(yǔ)言采用的都是詞法作...

    bladefury 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<