最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

跟我學習JScript的Bug與內(nèi)存管理

 更新時間:2015年11月18日 10:16:51   作者:小平果118  
跟我學習JScript的Bug與內(nèi)存管理,小編對JScript的Bug與內(nèi)存管理也不甚了解,所以整理了本篇文章,希望可以解決大家學習時的困擾。

1、JScript的Bug

IE的ECMAScript實現(xiàn)JScript嚴重混淆了命名函數(shù)表達式,搞得現(xiàn)很多人都出來反對命名函數(shù)表達式,而且即便是現(xiàn)在還一直在用的一版(IE8中使用的5.8版)仍然存在下列問題。

下面我們就來看看IE在實現(xiàn)中究竟犯了那些錯誤,俗話說知已知彼,才能百戰(zhàn)不殆。我們來看看如下幾個例子:

例1:函數(shù)表達式的標示符泄露到外部作用域

var f = function g(){};
typeof g; // "function"

前面我們說過,命名函數(shù)表達式的標示符在外部作用域是無效的,但JScript明顯是違反了這一規(guī)范,上面例子中的標示符g被解析成函數(shù)對象,這就亂了套了,很多難以發(fā)現(xiàn)的bug都是因為這個原因?qū)е碌摹?/p>

注:IE9以后貌似已經(jīng)修復了這個問題

例2:將命名函數(shù)表達式同時當作函數(shù)聲明和函數(shù)表達式

typeof g; // "function"
var f = function g(){};

特性環(huán)境下,函數(shù)聲明會優(yōu)先于任何表達式被解析,上面的例子展示的是JScript實際上是把命名函數(shù)表達式當成函數(shù)聲明了,因為它在實際聲明之前就解析了g。

這個例子引出了下一個例子。

例3:命名函數(shù)表達式會創(chuàng)建兩個截然不同的函數(shù)對象!

var f = function g(){};
f === g; // false
f.expando = 'foo';
g.expando; // undefined

看到這里,大家會覺得問題嚴重了,因為修改任何一個對象,另外一個沒有什么改變,這太惡了。通過這個例子可以發(fā)現(xiàn),創(chuàng)建2個不同的對象,也就是說如果你想修改f的屬性中保存某個信息,然后想當然地通過引用相同對象的g的同名屬性來使用,那問題就大了,因為根本就不可能。

再來看一個稍微復雜的例子:

例4:僅僅順序解析函數(shù)聲明而忽略條件語句塊

var f = function g() {
  return 1;
};
if (false) {
 f = function g(){
 return 2;
 };
}
g(); // 2

這個bug查找就難多了,但導致bug的原因卻非常簡單。首先,g被當作函數(shù)聲明解析,由于JScript中的函數(shù)聲明不受條件代碼塊約束,所以在這個很惡的if分支中,g被當作另一個函數(shù)function g(){ return 2 },也就是又被聲明了一次。然后,所有“常規(guī)的”表達式被求值,而此時f被賦予了另一個新創(chuàng)建的對象的引用。由于在對表達式求值的時候,永遠不會進入“這個可惡if分支,因此f就會繼續(xù)引用第一個函數(shù)function g(){ return 1 }。分析到這里,問題就很清楚了:假如你不夠細心,在f中調(diào)用了g,那么將會調(diào)用一個毫不相干的g函數(shù)對象。

你可能會問,將不同的對象和arguments.callee相比較時,有什么樣的區(qū)別呢?我們來看看:

var f = function g(){
  return [
  arguments.callee == f,
  arguments.callee == g
  ];
};
f(); // [true, false]
g(); // [false, true]

可以看到,arguments.callee的引用一直是被調(diào)用的函數(shù),實際上這也是好事,稍后會解釋。

還有一個有趣的例子,那就是在不包含聲明的賦值語句中使用命名函數(shù)表達式:

(function(){
 f = function f(){};
})();

按照代碼的分析,我們原本是想創(chuàng)建一個全局屬性f(注意不要和一般的匿名函數(shù)混淆了,里面用的是帶名字的聲明),JScript在這里搗亂了一把,首先他把表達式當成函數(shù)聲明解析了,所以左邊的f被聲明為局部變量了(和一般的匿名函數(shù)里的聲明一樣),然后在函數(shù)執(zhí)行的時候,f已經(jīng)是定義過的了,右邊的function f(){}則直接就賦值給局部變量f了,所以f根本就不是全局屬性。

了解了JScript這么變態(tài)以后,我們就要及時預防這些問題了,首先防范標識符泄漏帶外部作用域,其次,應該永遠不引用被用作函數(shù)名稱的標識符;還記得前面例子中那個討人厭的標識符g嗎?——如果我們能夠當g不存在,可以避免多少不必要的麻煩哪。因此,關(guān)鍵就在于始終要通過f或者arguments.callee來引用函數(shù)。如果你使用了命名函數(shù)表達式,那么應該只在調(diào)試的時候利用那個名字。最后,還要記住一點,一定要把命名函數(shù)表達式聲明期間錯誤創(chuàng)建的函數(shù)清理干凈。

2、JScript的內(nèi)存管理

知道了這些不符合規(guī)范的代碼解析bug以后,我們?nèi)绻盟脑?,就會發(fā)現(xiàn)內(nèi)存方面其實是有問題的,來看一個例子:

var f = (function(){
 if (true) {
 return function g(){};
 }
 return function g(){};
})();

我們知道,這個匿名函數(shù)調(diào)用返回的函數(shù)(帶有標識符g的函數(shù)),然后賦值給了外部的f。我們也知道,命名函數(shù)表達式會導致產(chǎn)生多余的函數(shù)對象,而該對象與返回的函數(shù)對象不是一回事。所以這個多余的g函數(shù)就死在了返回函數(shù)的閉包中了,因此內(nèi)存問題就出現(xiàn)了。這是因為if語句內(nèi)部的函數(shù)與g是在同一個作用域中被聲明的。這種情況下 ,除非我們顯式斷開對g函數(shù)的引用,否則它一直占著內(nèi)存不放。

var f = (function(){
 var f, g;
 if (true) {
 f = function g(){};
 }
 else {
 f = function g(){};
 }
 // 設(shè)置g為null以后它就不會再占內(nèi)存了
 g = null;
 return f;
})();

通過設(shè)置g為null,垃圾回收器就把g引用的那個隱式函數(shù)給回收掉了,為了驗證我們的代碼,我們來做一些測試,以確保我們的內(nèi)存被回收了。

測試

測試很簡單,就是命名函數(shù)表達式創(chuàng)建10000個函數(shù),然后把它們保存在一個數(shù)組中。等一會兒以后再看這些函數(shù)到底占用了多少內(nèi)存。然后,再斷開這些引用并重復這一過程。下面是測試代碼:

function createFn(){
 return (function(){
 var f;
 if (true) {
  f = function F(){
  return 'standard';
  };
 }
 else if (false) {
  f = function F(){
  return 'alternative';
  };
 }
 else {
  f = function F(){
  return 'fallback';
  };
 }
 // var F = null;
 return f;
 })();
}

var arr = [ ];
for (var i=0; i < 10000; i++) {
 arr[i] = createFn();
}

通過運行在Windows XP SP2中的任務管理器可以看到如下結(jié)果:

IE7:

 without `null`: 7.6K -> 20.3K
 with `null`:  7.6K -> 18K

IE8:

 without `null`: 14K -> 29.7K
 with `null`:  14K -> 27K

如我們所料,顯示斷開引用可以釋放內(nèi)存,但是釋放的內(nèi)存不是很多,10000個函數(shù)對象才釋放大約3M的內(nèi)存,這對一些小型腳本不算什么,但對于大型程序,或者長時間運行在低內(nèi)存的設(shè)備里的時候,這是非常有必要的。

以上就是關(guān)于JScript的Bug與內(nèi)存管理的全部介紹,希望對大家的學習有所幫助。

相關(guān)文章

  • JavaScript實現(xiàn)瀑布動畫

    JavaScript實現(xiàn)瀑布動畫

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)瀑布動畫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 微信小程序與h5的相互跳轉(zhuǎn)場景分析

    微信小程序與h5的相互跳轉(zhuǎn)場景分析

    這篇文章主要介紹了微信小程序與h5的相互跳轉(zhuǎn)場景分析,在微信小程序內(nèi)編寫webview文件,通過webview去跳轉(zhuǎn)h5,loadUrl為h5的地址,非嵌套,h5需要跳轉(zhuǎn)打開某個微信小程序,需要的朋友可以參考下
    2023-10-10
  • js鼠標懸浮出現(xiàn)遮罩層的方法

    js鼠標懸浮出現(xiàn)遮罩層的方法

    這篇文章主要介紹了js鼠標懸浮出現(xiàn)遮罩層的方法,以實例形式較為詳細的分析了html及css頁面布局與js特效的實現(xiàn)方法,是非常實用的技巧,需要的朋友可以參考下
    2015-01-01
  • JavaScript阻止表單提交方法(附代碼)

    JavaScript阻止表單提交方法(附代碼)

    這篇文章主要介紹了JavaScript阻止表單提交方法,通過代碼示例講解了阻止表單提交需要注意的事項,以及onSubmit和check()的區(qū)別寫法,需要的朋友可以參考下
    2017-08-08
  • 如何利用js實時監(jiān)聽input輸入框值的變化

    如何利用js實時監(jiān)聽input輸入框值的變化

    在做web開發(fā)時候很多時候都需要即時監(jiān)聽輸入框值的變化,以便作出即時動作去引導瀏覽者增強網(wǎng)站的用戶體驗感,這篇文章主要給大家介紹了關(guān)于如何利用js實時監(jiān)聽input輸入框值的變化,需要的朋友可以參考下
    2024-02-02
  • 前端MQTT詳細使用的兩種方法

    前端MQTT詳細使用的兩種方法

    MQTT(消息隊列遙測傳輸協(xié)議),是一種基于發(fā)布/訂閱(publish/subscribe)模式的通訊協(xié)議,該協(xié)議構(gòu)建于TCP/IP協(xié)議上,這篇文章主要給大家介紹了關(guān)于前端MQTT詳細使用的兩種方法,需要的朋友可以參考下
    2024-07-07
  • csdn 論壇技術(shù)區(qū)平均給分功能

    csdn 論壇技術(shù)區(qū)平均給分功能

    看論壇里技術(shù)區(qū)沒有平均給分的功能,感覺散分很不方便,就寫了一個:IE8,FF3.5下測試ok
    2009-11-11
  • 微信小程序文章詳情功能完整實例

    微信小程序文章詳情功能完整實例

    這篇文章主要介紹了微信小程序文章詳情功能,結(jié)合完整實例形式詳細分析了微信小程序文章詳情功能具體步驟、原理及功能實現(xiàn)技巧,需要的朋友可以參考下
    2020-06-06
  • js 獲取圖像縮放后的實際寬高,位置等信息

    js 獲取圖像縮放后的實際寬高,位置等信息

    本文主要介紹了js獲取圖像縮放后的實際寬高,位置等信息的方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • 單擊某一段文字改寫文本顏色

    單擊某一段文字改寫文本顏色

    單擊某一段文字,改文字變?yōu)榧t色,再次單擊之后,文字又變回黑色,示例如下,需要的朋友可以參考下
    2014-06-06

最新評論

福海县| 巴青县| 通州区| 呼和浩特市| 文登市| 淅川县| 清水河县| 临漳县| 绵竹市| 历史| 日土县| 奇台县| 蒙阴县| 达孜县| 利川市| 屏边| 峨眉山市| 平舆县| 盖州市| 台中市| 黄梅县| 布尔津县| 随州市| 洪江市| 胶州市| 华蓥市| 沁水县| 京山县| 晋江市| 双流县| 绥滨县| 宽城| 安泽县| 济源市| 吴忠市| 简阳市| 灌云县| 象山县| 徐州市| 阳西县| 平泉县|