你不知道的js (2)- eval和with

欺騙詞法

欺騙詞法作用域會導致性能問題。
JavaScript 引擎會在編譯階段進行數項的性能優化。其中有些優化依賴於詞法進行靜態分析,並預先確定所有變量和函數的定義位置,才能在執行過程中快速找到 標識符。js引擎無法在詞法分析階段知道eval() 和with會接收到什麼樣的代碼,就會完全不做任何優化。
eval(…) 和 with。前者可以對一段包 含一個或多個聲明的“代碼”字符串進行演算,並藉此來修改已經存在的詞法作用域(在 運行時)。後者本質上是通過將一個對象的引用當作作用域來處理,將對象的屬性當作作 用域中的標識符來處理,從而創建了一個新的詞法作用域(同樣是在運行時)。副作用是引擎無法在編譯時對作用域查找進行優化,因爲引擎只能謹慎地認 爲這樣的優化是無效的

1,eval 接受一個字符串爲參數,並將其中的內容視爲好像在書寫
時就存在與程序中這個位置的代碼。
eval(…) 通常被用來執行動態創建的代碼,在嚴格模式的程序中,eval(…) 在運行時有其自己的詞法作用域,意味着其中的聲明無法修改所在的作用域。

function foo (str,a){
	eval(str)  ;  // 欺騙
	console.log(a,b);
}
var b = 2;
foo(‘var b = 3;’,1);  // 1,3 
在console.log(a,b)處進行RHS輪詢的時候,eval 裏面的字符串就相當於在此處執行了一行代碼 var b = 2;在此形成了一個新的作用域。


function foo(str) { 
	"use strict"; 
	eval( str ); 
  	console.log( a ); // ReferenceError: a is not defined
    }
 foo( "var a = 2;console.log(a)" );
 2  //嚴格模式下,會在eval中形成一個作用域,聲明的值只在eval中有效。
 
 function foo(str) { 
	console.log(a) //  Uncaught ReferenceError: a is not defined
	eval( str ); 
    }
 foo( "var a = 2;console.log(a)" );
 // 在eval代碼執行之前,RHS a的值會報引用錯誤

2,with
with 通常被當作重複引用同一個對象中的多個屬性的快捷方式,可以不需要重複引用對象本身。
eval(…) 和 with 是會被嚴格模式所影響(限 制)。with 被完全禁止,而在保留核心功能的前提下,間接或非安全地使用 eval(…) 也被禁止了。

發佈了16 篇原創文章 · 獲贊 0 · 訪問量 8138
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章