国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > JavaScript > 正文

JavaScript中的eval()函數(shù)詳解

2024-05-06 15:51:00
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
和其他很多解釋性語(yǔ)言一樣,JavaScript同樣可以解釋運(yùn)行由JavaScript源代碼組成的字符串,并產(chǎn)生一個(gè)值。JavaScript通過全局函數(shù)eval()來(lái)完成這個(gè)工作

eval(“1+2”),-> 3

      動(dòng)態(tài)判斷源代碼中的字符串是一種很強(qiáng)大的語(yǔ)言特性,幾乎沒有必要在實(shí)際中應(yīng)用。如果你使用了eval(),你應(yīng)當(dāng)仔細(xì)考慮是否真的需要使用它。

一、eval()是一個(gè)函數(shù)還是一個(gè)運(yùn)算符

eval()是一個(gè)函數(shù),但由于它已經(jīng)被當(dāng)成運(yùn)算符來(lái)對(duì)待了。。JavaScript語(yǔ)言的早期版本定義了eval函數(shù),現(xiàn)代JavaScript解釋器進(jìn)行了大量的代碼分析和優(yōu)化。而eval的問題在于,用于動(dòng)態(tài)執(zhí)行的代碼通常來(lái)講不能分析,換句話說,如果一個(gè)函數(shù)調(diào)用了eval,那么解釋器將無(wú)法對(duì)這個(gè)函數(shù)做進(jìn)一步優(yōu)化,而將eval定義為函數(shù)的另一個(gè)問題是,它可以被賦予其他的名字,var f=eval;那么解釋器就無(wú)法放心的優(yōu)化任何調(diào)用了f()的函數(shù)。而當(dāng)eval是一個(gè)運(yùn)算符的時(shí)候,就可以避免這些問題。

二、eval()

eval()只有一個(gè)參數(shù)。如果傳入的參數(shù)不是字符串,它直接返回這個(gè)函數(shù)。如果參數(shù)是字符串,它會(huì)把字符串當(dāng)成JavaScript代碼進(jìn)行編譯,如果編譯失敗者拋出一個(gè)語(yǔ)法錯(cuò)誤異常。如果編譯成功,則開始執(zhí)行這一段代碼,并返回字符串中的最后一個(gè)表達(dá)式會(huì)或語(yǔ)句的值,如果最后一個(gè)表達(dá)式或語(yǔ)句沒有值,則最終返回undefined。如果字符串拋出一個(gè)異常,這個(gè)異常將把該調(diào)用傳遞給eval()。

關(guān)于eval最重要的是,它使用了調(diào)用它的變量作用域環(huán)境。也就是說,它查找變量的值和定義新變量和函數(shù)的操作和局部作用域中的代碼完全一樣。如果一個(gè)函數(shù)定義了一個(gè)局部變量x,然后調(diào)用eval(“x”),它會(huì)返回局部變量的值。如果它調(diào)用eval(“x=1”),它會(huì)改變局部變量的值。如果函數(shù)調(diào)用了eval(“var y=2;”),它聲明了一個(gè)新的局部變量y,同樣地,一個(gè)函數(shù)可以通過如下代碼聲明一個(gè)局部變量:

eval(“function f(){return x+1;}”);

如果在最頂層的代碼中調(diào)用eval,當(dāng)然,它會(huì)作用于全局變量和全局函數(shù)。

需要注意的是,傳遞給eval的字符串必須在語(yǔ)法上將的通,不能通過eval往函數(shù)中任意粘貼代碼片段,比如:eval(“return ;”)是沒有意義的,因?yàn)閞eturn只有在函數(shù)中才起到作用,并且事實(shí)上,eval的字符串執(zhí)行時(shí)的上下文環(huán)境和調(diào)用函數(shù)的上下文環(huán)境是一樣的,這不能使其作為函數(shù)的一部分來(lái)運(yùn)行。如果字符串作為一個(gè)單獨(dú)的腳本是有語(yǔ)義的,那么將其傳遞給eval作參數(shù)是完全沒有問題的,否則,eval會(huì)拋出語(yǔ)法錯(cuò)誤異常。

三、全局eval()

eval()具有更改布局變量的能力,這對(duì)于JavaScript優(yōu)化器來(lái)說是一個(gè)很大的問題。然而作為一種權(quán)宜之計(jì),JavaScript解釋器針對(duì)那些調(diào)用了eval的函數(shù)所做的優(yōu)化并不多。但當(dāng)腳本定義了eval的一個(gè)別名,且用另一個(gè)名稱調(diào)用它,JavaScript解釋器又會(huì)如何工作呢?為了讓JavaScript解釋器的實(shí)現(xiàn)更加簡(jiǎn)化,ECMAScript3標(biāo)準(zhǔn)規(guī)定了任何解釋器都不允許對(duì)eval賦予別名。如果eval函數(shù)通過別名調(diào)用的話,則會(huì)拋出一個(gè)EavlError異常。

實(shí)際上,大多數(shù)的實(shí)現(xiàn)并不是這么做的。當(dāng)通過別名調(diào)用時(shí),eval會(huì)將其字符串當(dāng)成頂層的全局代碼來(lái)執(zhí)行。執(zhí)行的代碼可能會(huì)定義新的全局變量和全局函數(shù),或者給全局變量賦值,但卻不能使用或者修改主調(diào)函數(shù)中的局部變量,因此,這不會(huì)影響到函數(shù)內(nèi)的代碼優(yōu)化。

ECMAScript5是反對(duì)使用EavlError的,并且規(guī)范了eval的行為,“直接的eval”,當(dāng)直接使用非限定的“eval”名稱來(lái)調(diào)用eval()函數(shù)時(shí),通常稱為“直接eval”。直接調(diào)用eval()時(shí),它總是在調(diào)用它的上下文作用域內(nèi)執(zhí)行。其他的間接調(diào)用則使用全局對(duì)象作為其上下文作用域,并且無(wú)法讀、寫、定義局部變量和函數(shù)。下面有一段示例代碼:

復(fù)制代碼 代碼如下:


var geval=eval;                //使用別名調(diào)用evla將是全局eval
var x="global",y="global";    //兩個(gè)全局變量
function f(){                //函數(shù)內(nèi)執(zhí)行的是局部eval
    var x="local";            //定義局部變量
    eval("x += ' chenged';");//直接使用eval改變的局部變量的值
    return x;                //返回更改后的局部變量
}
Function g(){                //這個(gè)函數(shù)內(nèi)執(zhí)行了全局eval
    var y="local";
    geval("y += ' changed';"); //直接調(diào)用改變了全局變量的值
    return y;
}
console.log(f(),x);            //改變了布局變了,輸出 “l(fā)ocal changed global”
console.log(g(),y);            //改變了全局變量,輸出    “l(fā)ocal global changed”


全局的eval的這些行為不僅僅是處于代碼優(yōu)化其的需要而作出的一種折中方案,它實(shí)際上是一種非常有用的特性,它允許我們執(zhí)行那些對(duì)上下文沒有任何依賴的全局腳本代碼段。真正需要eval來(lái)執(zhí)行代碼段的場(chǎng)景并不多見。但當(dāng)你真的意識(shí)到它的必要性的時(shí)候,你更可能會(huì)使用全局eval而不是局部eval。

四、嚴(yán)格eval()

ECMAScript5嚴(yán)格模式對(duì)eval()函數(shù)的行為施加了更多的限制,甚至對(duì)標(biāo)識(shí)符eval的使用也施加了限制。當(dāng)在嚴(yán)格模式下調(diào)用eval時(shí),或者eval執(zhí)行的代碼段以“Use strict” 指令開始,這里的eval是私有上下文環(huán)境中的局部eval。也就是說,在嚴(yán)格模式下,eval執(zhí)行的代碼段可以查詢或更改局部變量,但不能在局部作用域中定義新的變量或函數(shù)。

此外,嚴(yán)格模式將“eval”列為保留字,這讓eval()更像一個(gè)運(yùn)算符。不能用一個(gè)別名覆蓋eval()函數(shù)。并且變量名,函數(shù)名。函數(shù)參數(shù)或者異常捕獲的參數(shù)都不能取名為eval。

寶劍鋒從磨礪出,梅花香自苦寒來(lái)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 唐河县| 嘉义市| 堆龙德庆县| 尖扎县| 新绛县| 闸北区| 平遥县| 荣昌县| 兴安盟| 始兴县| 卓尼县| 黄大仙区| 黎川县| 凯里市| 华宁县| 杂多县| 广河县| 遂宁市| 遂平县| 保亭| 宣威市| 荆州市| 敖汉旗| 洛南县| 郴州市| 达拉特旗| 洛阳市| 波密县| 延吉市| 东丰县| 定安县| 台中市| 宽城| 和龙市| 垦利县| 中方县| 武陟县| 嘉义县| 台山市| 东乌珠穆沁旗| 顺昌县|