js近期的研究总结
很慶幸 在 javascript高級群 中認識了 wait. 因為他的 激情 和一些 奇思妙想.敦促我們大家不斷的 研究更多更有趣的 怪異問題.
同時 真的加深了 我對js 的理解...?? 那么下面一些文字 屬于 我于 wait 還有其他幾位朋友 閑聊時 扯出來的一些js怪異現象的 總結...? 其中也有疑問? 至盡 不知其原理.
?
我們知道 js? 有種機制 叫預編譯.
即 在根環境 順序執行的過程中 會把 var 和function 這兩個聲明 關鍵字 提前解釋一下. 以告訴瀏覽器 . 有多少個變量和 方法被聲明.
?
對于一個變量聲明. 其過程如下.
var x=1;
在預編譯階段 .他等價于 var x;? 即 var x=undefined 以便告訴瀏覽器 這里有個變量. 但不會去執行 賦值語句.
只有在預編譯完成后 真正 解釋執行 當前代碼時 才會執行 x=1; 部分.
這也就解釋了.下面兩組代碼的區別和現象 :
?
Code Snippet
alert(x);//打印undefined
var x=1;
而
Code Snippet
alert(x) //不含下面的聲明語句時 .瀏覽器報錯.
?
?
那么 function? 既然也屬于預編譯 的目標. 為什么其 表現和 var差別如此巨大呢? 我的疑問? 就在這里
?
有些觀點 提出 function f(){} 和 var f=function(){}? 是完全等價的.
很明顯.根據前面對 var 的測試. 即說明兩者的差別.? 這也解釋了 為什么 以OO方式去寫js時 this.func=function(){} 一定要出現在你調用 this.func()前面 的根本呢原因.
?
那么很明顯 對于function 和var 的預編譯機制 是不同的. 瀏覽器會在預編譯階段. 把function 聲明部分直接 解釋..如果是具名函數. 則會把函數名作為存放該函數引用 的變量. 直接標記出來. 這就解釋了 方法可以 先調用 后聲明的原因.?? 這僅僅是我的推斷. 如果有該部分的資料 希望各位老師 可以給出.
?
那么看下一個問題. 也是有關瀏覽器 解釋執行時的一些細節
?
很多類庫 都會把 其實現 都封裝到 一個偽名稱空間中. 即 把代碼 放到一個 自執行的匿名函數中去 如
(function(){........code....... })();
在我過去逐漸加深對js的學習過程中. 第一次看到 自執行匿名函數時. 實在是覺得 匪夷所思. 他是如此的優雅.
但并沒有對他 深入的去理解.? 最近通過看 周愛民 老師的blog? 才引起了我對它的 反思... 為什么函數聲明部分 加個括號.就可以執行了呢? 而function(){}();就會報錯呢? 通過不斷的測試. 終于摸到些門道.
首先 我們得明白 一個函數聲明部分 對 js來說意味著什么.? 根據前面的 預編譯. 我們知道 他就是一段聲明. 而不同于一般的表達式. 表達式 預編譯期間. js完全忽略?? 所以 當 js解釋執行 到 function(){}(); 部分時 會忽略掉 聲明語句. 因為 那部分 在預編譯時.? js已經解釋執行過了. 再執行一次 就屬于 浪費感情.? 所以 它跳過.? 然后試圖 去執行(); 這顯然就會報錯.
那么加了( function(){})? 有什么區別呢? 很顯然 ( ) 是表達式的一部分 所以js遇到 ( ) 會被迫去 對( )中的 部分求解 得到返回值. 這就逼迫 js去再次解釋執行 函數聲明部分的語句.... 所以到了這里 我猜測 如果js沒有 某個機制 去 分辨 是否某個函數 已存在 過 而 此時 把() 中的函數聲明 部分看成是 類似某條件分枝 被滿足時 才執行的聲明語句. 則可能會產生兩個 作用相同的 函數.? 從而 浪費內存. (這只是我的推斷.沒有任何資料可以支持我的觀點.)
?
接著上面.? 我們可以做以下嘗試.用類似的語句?同樣實現 匿名函數自執行:
+function(){...}();
1,function(){.....}();
結果證明. 完全可行.
?
最后再說一個? 我至盡沒有找到答案的 怪異問題 一個關于 delete 的問題. 希望各位老師能給予指點.
我們都知道 delete 是無法 刪除 一個私有屬性 或 原型鏈中的東西的.
如
var x=1;
delete x;
alert(x);//打印1 即刪除失敗.
但下面的代碼卻沒有問題.
?
eval(' var x=1;');
delete x;
alert(x);// 報錯?x未定義 .說明刪除成功.??很明顯 eval 中的val 是無效的. 那么 我很想知道 這個x 到底是怎樣一個存在.
因為他 并不簡單等價于 eval('x=1') 或?x=1;?? 用個測試即可證明
?
首先 要提的就是 我們以前 在某個非 window 作用域(即非根環境聲明全局變量) 內聲明一個 全局變量 是 不使用 var 聲明語句 .而直接 使用 如? x=1; 這樣的表達式.? 一旦js執行到這里 就會產生一個 全局變量
下面的例子. 說明他們的不同
function func(){
? a=1;
}
func();
alert(a)// 或alert(window.a) 打印 1
而
function func(){
? eval('var a=1;');
}
func();
alert(a) //報錯. alert(typeof a) 打印undefined
就是這里. 徹底把我搞暈了. 那么 eval 中出現的 var 變量聲明 到底意味著什么呢?
?
?
我們再來看看? var 的威力有多大.
?
window={}; //ie報錯 . ff忽略之.
那么
var window={};// ie opera safari 全過? ff3.0 報錯
alert(window.location);// 報錯.對象不支持此屬性或方法.
?
說明 只有ff 的js? moneky引擎 做了預防. 即 不允許你聲明的變量名 同?核心對象名 重復.
而其他引擎 都 允許..? 那么我們暫時不討論引擎的問題.? 只看 var window={} 成功執行之后的情況
?
?上面兩組代碼 充分說明 一下2點問題:
1.js的預編譯機制的 特權.?
? 因為我們根據上面2組代碼 可以看出 真正起作用的 不是 賦值語句 而是 變量聲明部分 即 var window;//此時強制window 指向undefined對象. 然后 執行到 window={}; 因為此時 window指向的 已經不是 我們的那個全局環境(平常我都叫他window對象...) 而是undefined . 所以js 允許 我們為這個變量 賦值...為一個 new Object()...
2. window!=全局環境. 而僅僅是一個指針 一個引用 一個句柄.
因為? 下面的代碼 說明了此問題:
ie opera9 ?safari? chrome 可過
var window={};
alert(123);//正常打印 123
window.alert(123)//失敗.不存在該方法. 因為window引用的 目前是一個空對象.? 而不是 原始的window 引用即 全局環境 .
?
轉載于:https://www.cnblogs.com/qiantuwuliang/archive/2009/06/17/1505420.html
總結
- 上一篇: 软件项目开发应写的13类文档
- 下一篇: 光纤 概述