文章標簽 ‘javascript’

javascript 正則表達式 全局修飾符

2011年11月10日 沒有評論

在javascript中定義一個正則表達式可以有如下形式:

直接量語法
var re = /pattern/attributes //注意后面不能有分號
創建 RegExp 對象的語法
var re = new RegExp(pattern, attributes);

參數 pattern 是一個字符串,指定了正則表達式的模式或其他正則表達式。

參數 attributes 是一個可選的字符串,包含屬性 “g”、”i” 和 “m”,分別用于指定全局匹配、區分大小寫的匹配和多行匹配。ECMAScript 標準化之前,不支持 m 屬性。如果 pattern 是正則表達式,而不是字符串,則必須省略該參數。

如果用錯了attributes中的g修飾符,可能會導致意想不到的結果。例如如下例子中。

var str = "abc123";
var re = /a.c/g
var result1 = re.test(str);
var result2 = re.test(str);
var result3 = re.test(str);

可能第一眼看上去result1、result2、result3都為true吧,但是執行一下,得到的結果有些讓人費解,result2為false。即使在var result2 = re.test(str)前對str從新賦值為str = “abctest”,得到結果還是false。為什么會這樣呢?其實造成這個結果的原因就是在正則表達式中用全局匹配修飾符(/g),如果去掉/g,即re=/a.c/得到的結果就都為true。現在知道問題出在什么地方,但更深層的原因是什么呢?查看文檔,發現RegExp對象有一個lastIndex的屬性,如果使用了全局修飾符,那么執行test方法后,lastIndex就會記錄匹配的字符串在原始字符串中最后一位的索引加一,例如執行了var result1 = re.test(str)后lastIndex為3,如果沒有發現匹配lastIndex置為0。當下次再執行時,對給定的字符串匹配不是從開頭位置,而是要依據lastIndex提供的位置,由于這個原因,所以導致上例中result2的值為false。另外也能通過程序重置lastIndex值。不知道這能不能算是javascript引擎的一個Bug。

最后總結一下正則表達式相關的一些操作,RegExp對象本身的方法有exec和test,字符串對象能使用正則的方法有search、match、replace和split。其中真正能用到全局修飾符的只有match和replace,所以在考慮使用正則表達式的時候不要濫用/g。

深入理解JavaScript定時機制

2011年11月7日 沒有評論

本文系轉載,原文出處http://www.laruence.com/2009/09/23/1089.html

JavaScript的setTimeout與setInterval是兩個很容易欺騙別人感情的方法,因為我們開始常常以為調用了就會按既定的方式執行, 我想不少人都深有同感, 例如:

setTimeout(function() {
    alert('你好!');
}, 0);
setInterval(callbackFunction, 100);

認為setTimeout中的問候方法會立即被執行,因為這并不是憑空而說,而是JavaScript API文檔明確定義第二個參數意義為隔多少毫秒后,回調方法就會被執行. 這里設成0毫秒,理所當然就立即被執行了.

同理對setInterval的callbackFunction方法每間隔100毫秒就立即被執行深信不疑!

但隨著JavaScript應用開發經驗不斷的增加和豐富,有一天你發現了一段怪異的代碼而百思不得其解:

div.onclick = function(){
        setTimeout(function() {
                document.getElementById('inputField').focus();
        }, 0);
};

既然是0毫秒后執行,那么還用setTimeout干什么, 此刻, 堅定的信念已開始動搖.

直到最后某一天 , 你不小心寫了一段糟糕的代碼:

setTimeout(function() {
        while (true) {
        }
}, 100);
setTimeout(function() {
        alert('你好!');
}, 200);
setInterval(callbackFunction, 200);

第一行代碼進入了死循環,但不久你就會發現,第二,第三行并不是預料中的事情,alert問候未見出現,callbacKFunction也杳無音訊!

這時你徹底迷惘了,這種情景是難以接受的,因為改變長久以來既定的認知去接受新思想的過程是痛苦的,但情事實擺在眼前,對JavaScript真理的探求并不會因為痛苦而停止,下面讓我們來展開JavaScript線程和定時器探索之旅!

拔開云霧見月明,出現上面所有誤區的最主要一個原因是:潛意識中認為,JavaScript引擎有多個線程在執行,JavaScript的定時器回調函數是異步執行的.

而事實上的,JavaScript使用了障眼法,在多數時候騙過了我們的眼睛,這里背光得澄清一個事實:

JavaScript引擎是單線程運行的,瀏覽器無論在什么時候都只且只有一個線程在運行JavaScript程序.

JavaScript引擎用單線程運行也是有意義的,單線程不必理會線程同步這些復雜的問題,問題得到簡化.

那么單線程的JavaScript引擎是怎么配合瀏覽器內核處理這些定時器和響應瀏覽器事件的呢?下面結合瀏覽器內核處理方式簡單說明.

瀏覽器內核實現允許多個線程異步執行,這些線程在內核制控下相互配合以保持同步.假如某一瀏覽器內核的實現至少有三個常駐線程:javascript引擎線程,界面渲染線程,瀏覽器事件觸發線程,除些以外,也有一些執行完就終止的線程,如Http請求線程,這些異步線程都會產生不同的異步事件,下面通過一個圖來闡明單線程的JavaScript引擎與另外那些線程是怎樣互動通信的.雖然每個瀏覽器內核實現細節不同,但這其中的調用原理都是大同小異.

由圖可看出,瀏覽器中的JavaScript引擎是基于事件驅動的,這里的事件可看作是瀏覽器派給它的各種任務,這些任務可以源自 JavaScript引擎當前執行的代碼塊,如調用setTimeout添加一個任務,也可來自瀏覽器內核的其它線程,如界面元素鼠標點擊事件,定時觸發器時間到達通知,異步請求狀態變更通知等.從代碼角度看來任務實體就是各種回調函數,JavaScript引擎一直等待著任務隊列中任務的到來.由于單線程關系,這些任務得進行排隊,一個接著一個被引擎處理.

上圖t1-t2..tn表示不同的時間點,tn下面對應的小方塊代表該時間點的任務,假設現在是t1時刻,引擎運行在t1對應的任務方塊代碼內,在這個時間點內,我們來描述一下瀏覽器內核其它線程的狀態.

t1時刻,GUI渲染線程:

該線程負責渲染瀏覽器界面HTML元素,當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行.本文雖然重點解釋JavaScript定時機制,但這時有必要說說渲染線程,因為該線程與JavaScript引擎線程是互斥的,這容易理解,因為 JavaScript腳本是可操縱DOM元素,在修改這些元素屬性同時渲染界面,那么渲染線程前后獲得的元素數據就可能不一致了.

在JavaScript引擎運行腳本期間,瀏覽器渲染線程都是處于掛起狀態的,也就是說被”凍結”了.

所以,在腳本中執行對界面進行更新操作,如添加結點,刪除結點或改變結點的外觀等更新并不會立即體現出來,這些操作將保存在一個隊列中,待JavaScript引擎空閑時才有機會渲染出來.

GUI事件觸發線程:

JavaScript腳本的執行不影響html元素事件的觸發,在t1時間段內,首先是用戶點擊了一個鼠標鍵,點擊被瀏覽器事件觸發線程捕捉后形成一個鼠標點擊事件,由圖可知,對于JavaScript引擎線程來說,這事件是由其它線程異步傳到任務隊列尾的,由于引擎正在處理t1時的任務,這個鼠標點擊事件正在等待處理.

定時觸發線程:

注意這里的瀏覽器模型定時計數器并不是由JavaScript引擎計數的,因為JavaScript引擎是單線程的,如果處于阻塞線程狀態就計不了時,它必須依賴外部來計時并觸發定時,所以隊列中的定時事件也是異步事件.

由圖可知,在這t1的時間段內,繼鼠標點擊事件觸發后,先前已設置的setTimeout定時也到達了,此刻對JavaScript引擎來說,定時觸發線程產生了一個異步定時事件并放到任務隊列中, 該事件被排到點擊事件回調之后,等待處理.
同理, 還是在t1時間段內,接下來某個setInterval定時器也被添加了,由于是間隔定時,在t1段內連續被觸發了兩次,這兩個事件被排到隊尾等待處理.

可見,假如時間段t1非常長,遠大于setInterval的定時間隔,那么定時觸發線程就會源源不斷的產生異步定時事件并放到任務隊列尾而不管它們是否已被處理,但一旦t1和最先的定時事件前面的任務已處理完,這些排列中的定時事件就依次不間斷的被執行,這是因為,對于JavaScript引擎來說,在處理隊列中的各任務處理方式都是一樣的,只是處理的次序不同而已.

t1過后,也就是說當前處理的任務已返回,JavaScript引擎會檢查任務隊列,發現當前隊列非空,就取出t2下面對應的任務執行,其它時間依此類推,由此看來:

如果隊列非空,引擎就從隊列頭取出一個任務,直到該任務處理完,即返回后引擎接著運行下一個任務,在任務沒返回前隊列中的其它任務是沒法被執行的.

相信您現在已經很清楚JavaScript是否可多線程,也了解理解JavaScript定時器運行機制了,下面我們來對一些案例進行分析:
案例1:setTimeout與setInterval

setTimeout(function() {
        /* 代碼塊... */
        setTimeout(arguments.callee, 10);
}, 10);

setInterval(function(){
        /*代碼塊... */
}, 10);

這兩段代碼看一起效果一樣,其實非也,第一段中回調函數內的setTimeout是JavaScript引擎執行后再設置新的setTimeout 定時, 假定上一個回調處理完到下一個回調開始處理為一個時間間隔,理論兩個setTimeout回調執行時間間隔>=10ms .第二段自setInterval設置定時后,定時觸發線程就會源源不斷的每隔十秒產生異步定時事件并放到任務隊列尾,理論上兩個setInterval 回調執行時間間隔

案例2:ajax異步請求是否真的異步?

很多同學朋友搞不清楚,既然說JavaScript是單線程運行的,那么XMLHttpRequest在連接后是否真的異步?
其實請求確實是異步的,不過這請求是由瀏覽器新開一個線程請求(參見上圖),當請求的狀態變更時,如果先前已設置回調,這異步線程就產生狀態變更事件放到 JavaScript引擎的處理隊列中等待處理,當任務被處理時,JavaScript引擎始終是單線程運行回調函數,具體點即還是單線程運行 onreadystatechange所設置的函數.

分類: web前端 標簽: ,

javascript中如何判斷某變量是否存在

2011年10月25日 沒有評論

如果js代碼中用到了某個變量,但是該變量又沒有聲明,只是script就會報錯,大致是“變量xx沒有定義”,可以用如下方法來判斷一個變量是否已經定義了。

if (typeof(x) == "undefined") {
    alert("未定義");
}

該方法判斷一個變量是否未定義,適用于兩種情況:

1、x 從來沒有出現過。

2、x 只是用 var 聲明了,但沒有賦值。

javascript中幾種連接字符串效率的測試例子

2011年9月27日 沒有評論

在javascript對應字符串的連接有三種方法,用的最多可能是”+=“,其次是concat函數,其實還可以借助array的join方法來完成字符串的連接。分別在瀏覽器IE6,firefox3.0,safari,chorme中測試,發現通過join的方式最快,其次是 +=,最慢的是concat方式。啥也別說了,直接上代碼。

重要提示,IE6中可能會把瀏覽器卡死,如果要測試,請把initData中的100000修改一下,似乎1000就可以看到效果了!效果測試請點擊這 里閱讀全文…

javascript的repacle方法的用法

2011年9月1日 沒有評論

replace是String對象上的一個方法,可以實現把字符串中某些指定的子字符串替換成其他字符串。用法為 “字符串.replace(parm1,parm2)”。其中parm1的老字符串,可以使普通字符串,也可以是一個正則表達式;parm2退換的結果,可以是一個字符串,更重要的是也可以是一個javascript的方法,作為回調函數。下面用幾個小例子來分別說明一下。

alert(‘abcabd’.replace(‘ab’,’12′));

這里alert的結果就是12cabd,注意到它只替換到第一次出現的,后面不做替換。如果把子串全部替換,只能用正則表達式的方法來操作。

alert(‘abcabdAbe’.replace(/ab/g,’12′));

這樣得到的結果為12c12dAbe,g 表示進行全局替換,同時也可以用 i 來忽略大小寫,注意正則表達式不能用引號引起來。

var i = 0;
alert(‘abAabBabC’.replace(/ab/g, function(m) {
i++;
return m + ‘-’ + i + ‘-’;
}));

這里的結果是ab-1-Aab-2-Bab-3-C,當匹配到子字符串時,調用回調方法,并把匹配到的值作為參數傳入。另外一個例子,把字符串中小于30的數替換成星號

alert(’10 33 21 18 52′.replace(/\d+/g, function(match) {
return parseInt(match) < 30 ? '*' : match;
}));

javascript讀寫cookie實例

2011年8月29日 沒有評論

Cookie是網站存放在客戶端的一小段數據。一般的,網站為了提升用戶體驗,在客戶的客戶端中保存用戶的歷史信息,以備用戶再次訪問時網站能提供 更方便,更有針對性的服務。比如,網站可以記住你的登錄狀態,只要登錄一次下次訪問就不用在登錄;購物網能記住你瀏覽過的產品,保留你購物車中的物品。這 些都有Cookie的功勞。

cookie的存取操作不止局限于服務器段,客戶端通過javascript也一樣可以進行cookie的存取。利用document.cookie對象就能操作了。下面分別給出讀寫cookie的方法示例代碼。

function getCookie(name){
    var arr = document.cookie.match(new RegExp("(^| )" 
                                   + name + "=([^;]*)(;|$)"));
    if(arr != null) return (arr[2]);
    return null;
}

document.cookie就是以key/value的形式返回所有對于當前頁面有權限讀取的cookie字符串,然后通過正則表達式查詢參數指定cookie名的cookie值。

function setCookie (name, value, expire) {
    var expireStr = '';

    if (expire || expire > 0) {
        var exp  = new Date();
        exp.setTime(exp.getTime() + expire * 1000);

        expireStr = ';expires=' + exp.toGMTString();
    }

    document.cookie = name + '=' + value +  
                      '; path=/;' + expireStr + 
                      'domain=.youdomain.com';
}

注意setCookie中的第三個參數,是指定cookie的過期時間,單位為秒,如果不指定或者值不大于0,那么寫入的cookie類型為會話cookie,即瀏覽器關閉后,cookie就失效,反正就是硬盤cookie,會記錄在客戶端的電腦上。

IE6 加載動態js不執行的問題

2011年8月25日 沒有評論

用戶的信息存放在主站上,一個子站也提供用戶登錄的接口,登陸采用ajax不刷新頁面的方式,由于安全原因,ajax不允許跨域執行,所以單純的ajax是不能直接運行的。但是動態創建script的方式不存在跨域的問題,大致的操作是通過document.createElement創建一個script對象,同時script的src指向主站提供驗證用戶信息的url,url中參數包括用戶輸入的用戶名和密碼,把這個script對象添加到當前頁面上。主站的接口根據用戶名密碼來驗證用戶是否合法,響應的內容是調用一個js方法。

該方式在IE6下有時不能正常工作,其他主流瀏覽器都沒有問題。IE6的具體癥狀是第一次能正常工作,如果用戶輸入用戶名和密碼不匹配,第一次能提示用戶重新輸入,但是修改后重新提交了就沒有反應,必須要強制刷新才會正常,通過httpwatcher查看,請求是發送,也有響應,就是沒有調用成功頁面上的js方法。經常反復折騰,終于找到問題的根源,主站接口url是php,所以響應的header中content-type不是text/html,強制設置header中content-type設置為 Content-Type: text/javascript 或者Content-Type: application/x-javascript后,IE6就正常工作了。另外如果服務器啟用gzip壓縮,可能也會造成IE6不能正常工作,在apache中可以針對某個特定的uri設置成不壓縮,如:SetEnvIfNoCase Request_URI /user/vlogin/.* no-gzip dont-vary。

flash與javascript的相互通信的例子

2011年8月24日 沒有評論

當前的Web應用中少不了flash,有時候當前頁面需要跟flash交互,交互的橋梁是通過javasript來實現,javascript能夠調用到flash中定義的方法,同樣的flash中也可以調用到javacript的方法。

點這里 查看演示例子 || ?點這里 下載完整代碼

flash可以用 ExternalInterface.call(“swfCall” [,arg1[,arg2]]) 的方式來調用javacript中定義的swfCall方法,參數為可選;但是javascript中調用flash的方法,需要flash指定那些方法能調用,例如在flash的代碼

ExternalInterface。addCallback("setFlashVal", flashFunction);

function flashFunction(msg) {
	//do something
}

function flashFunction_1(msg) {
	//do something
}

javascript中就可以調用到flashFunction,但調用的方法名是setFlashVal,由于flashFunction_1沒有導出,所以頁面javascript無法訪問到。IE跟Firefox、chrome獲取flash對象的方式不同,IE是用window對象,Firefox等則是用document對象。具體參看下面代碼:

function getSwfObject(movieName) {
	if (navigator.appName.indexOf("Microsoft") != -1) {
		return window[movieName]
	}else{
		return document[movieName]
	}
}

getSwfObject('swfId').setFlashVal('text');

其中movieName是flash的ID,即<object>標簽中定義的ID、或者是embed標簽的name屬性值,最好這兩個值保持一致,否則可能在不同的平臺下無法正常工作。

分類: web前端 標簽: , , , ,

javascript下動態創建IMG時IE6兩次請求指定資源

2011年8月19日 沒有評論

眾所周知js可以通過document.createElement方法創建DOM對象,并可以把增加到頁面上,今天碰到一個怪異的事情,使用如下代碼動態創建一個Img

function req() {
	var el = document.createElement('IMG');
	el.src = '資源的WEB地址';                 //line 3
	document.body.appendChild(el);          //line 4
}

在某種特定的調用req方法時,發現在IE6會有兩次請求“資源的WEB地址”,其他瀏覽器都是正常,真是萬惡的IE6啊。由于req方法是另一個函數調用的,以后是多次觸發了req方法,經過多方的debug,發生確實只調用了一次req,所以產生問題的原因就是在req方法的內部,對于這么簡單的代碼,唯一可以修改的地方把第3、4行代碼換一下位置,調整后,發現IE6正常了,只請求一次了,測試其他瀏覽器也是正常,唉,再次BS一下IE6。

 

分類: web前端 標簽: , ,

iframe中的swf無法調用頁面中的js函數

2011年8月19日 沒有評論

主頁面中存在一個iframe,目的是讓iframe在后臺處理一些事情,所以把iframe的width,height設置為1個像素,同時設置visibility為hidden,iframe指向的頁面中嵌套了一個swf,該swf是flash、as3,as3腳本中是讀取flash的SharedObjects中存放的值,并把該值傳回給頁面的js函數。直接訪問這個iframe的頁面能夠正常工作,即flash能調用到頁面上的js函數,但是訪問主頁面時,FF、safari、chrome也是正常工作,IE6、8就歇菜了,沒有反應,經過一番的查找問題,發現根源是iframe不能是隱藏的,即把visibility設置為visible或者去掉visibility的設置就可以了。

分類: web前端 標簽: , , , , ,

無覓相關文章插件,快速提升流量

30选5怎么中奖