標籤:define 等於 使用 javascrip 捷徑 自動 obj 對象引用 foo
/*
* =========================================================
*
* JavaScript 詞法欺騙
*
* 1.欺騙詞法範圍,會導致效能下降。
* 2.引擎在代碼中發現了,eval()和 with()函數時,引擎在詞法階段並不知道它們將接收的什麼代碼,引擎只能簡單的假設關於標示符是無效的。
* 3.在javascript中編譯原始碼時,其中一步是對代碼做大量的最佳化,當遇到上述兩個函數時,引擎只能不做任何代碼的最佳化,這個是降低效能的原因。
* 4.eval()和 with()函數,都將在運行時起到作用。
*
* =========================================================
* */
// function foo(str, a) {
// eval(str); // 欺騙詞法
// console.log(a, b); // 1 3
// }
//
// var b = 2;
//
// foo("var b = 3;", 1);
//
// var obj = {
// a: 1,
// b: 2,
// c: 3
// };
//
// console.log(obj.a);
// console.log(obj.b);
// console.log(obj.c);
// with 通常被當作重複引用同一個對象中的多個屬性的捷徑。
// 但不推薦使用,因會改變當前範圍,降低效能,並且可能造成變數泄漏。
// 不用迴圈的重複的調用對象本身。
// with (obj) {
// a = 3;
// b = 4;
// c = 5;
// }
//
// console.log(obj.a);
// console.log(obj.b);
// console.log(obj.c);
// with
// 首先我們知道a = 2; 是一個賦值操作(LHS)。當foo傳入一個引用(obj),with會改變該
// 引用範圍中的a屬性值,當在該引用尋找不到a變數時,範圍尋找方式起到作用,向上層範圍執行尋找a變數
// 在該引用範圍、foo範圍、全域範圍中,都沒有找到a變數時,with 就自動建立了一個全域變數(如果在上述範圍中尋找到a變數將會改變其變數值),
// 這也叫做變數泄漏,造成這個原因是a=2 執行的時賦值操作,根據javascript中的特性,賦值操作前沒有見變數聲明標示符時,javascript就自動建立一個全域變數。
// 前提是非strict 模式下,才會產生以上內容,strict 模式下,將完全禁止使用with函數。
// with 實際上是根據你傳遞給它的對象引用,憑空的建立出一個全新的詞法範圍。
// var a = 10; // 這裡可以驗證with更改了a變數的值。如果沒有定義這個變數,console.log( a );列印的也是2.
// function foo(obj) {
// with (obj) {
// a = 2; // 完全等於賦值操作
// }
// }
// var o1 = {a: 3};
// var o2 = {b: 3};
// foo(o1);
// console.log(o1.a); // 2
//
// foo( o2 );
// console.log( o2.a ); // undefined
// console.log( a ); // 2——不好,a 被泄漏到全域範圍上了!
JavaScript 二、eval 和 with 函數