常見前端面試題及答案(下)

69.你如何從瀏覽器的URL中獲取查詢字符串參數。

以下函數把獲取一個key的參數。

1 function parseQueryString ( name ){

     name = name.replace(/[\[]/,"\\\[");

     var regexS = "[\\?&]"+name+"=([^&#]*)";

     var regex = new RegExp( regexS );

     var results = regex.exec( window.location.href );

 

     if(results == null) {

         return "";

     } else {

    return results[1];

    }

}

70.請解釋一下JavaScript的同源策略。

在客戶端編程語言中,如javascript和 ActionScript,同源策略是一個很重要的安全理念,它在保證數據的安全性方面有着重要的意義。同源策略規定跨域之間的腳本是隔離的,一個域的腳本不能訪問和操作另外一個域的絕大部分屬性和方法。那麼什麼叫相同域,什麼叫不同的域呢?當兩個域具有相同的協議, 相同的端口,相同的host,那麼我們就可以認爲它們是相同的域。同源策略還應該對一些特殊情況做處理,比如限制file協議下腳本的訪問權限。本地的HTML文件在瀏覽器中是通過file協議打開的,如果腳本能通過file協議訪問到硬盤上其它任意文件,就會出現安全隱患,目前IE8還有這樣的隱患。

71.請描述一下JavaScript的繼承模式。

關於繼承請看文章JavaScript之對象的繼承。

72.如何實現下列代碼:[1,2,3,4,5].duplicator();//[1,2,3,4,5,1,2,3,4,5]。

73.描述一種JavaScript中實現memoization(避免重複運算)的策略。

74.什麼是三元表達式?“三元”表示什麼意思?

三元表達式:? :。三元–三個操作對象。

在表達式boolean-exp ? value0 : value1 中,如果“布爾表達式”的結果爲true,就計算“value0”,而且這個計算結果也就是操作符最終產生的值。如果“布爾表達式”的結果爲false,就計算“value1”,同樣,它的結果也就成爲了操作符最終產生的值。

75.JavaScript裏函數參數arguments是數組嗎?

在函數代碼中,使用特殊對象 arguments,開發者無需明確指出參數名,通過使用下標就可以訪問相應的參數。

arguments雖然有一些數組的性質,但其並非真正的數組,只是一個類數組對象。其並沒有數組的很多方法,不能像真正的數組那樣調用.jion(),.concat(),.pop()等方法。

76.什麼是”use strict”;?使用它的好處和壞處分別是什麼?

在代碼中出現表達式-“use strict”; 意味着代碼按照嚴格模式解析,這種模式使得Javascript在更嚴格的條件下運行。

好處:

  • 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行爲;

  • 消除代碼運行的一些不安全之處,保證代碼運行的安全;

  • 提高編譯器效率,增加運行速度;

  • 爲未來新版本的Javascript做好鋪墊。 
    壞處:

同樣的代碼,在”嚴格模式”中,可能會有不一樣的運行結果;一些在”正常模式”下可以運行的語句,在”嚴格模式”下將不能運行。

77.解釋”chaining”。

jQuery方法鏈接。直到現在,我們都是一次寫一條jQuery語句(一條接着另一條)。不過,有一種名爲鏈接(chaining)的技術,允許我們在相同的元素上運行多條jQuery命令,一條接着另一條。

提示:這樣的話,瀏覽器就不必多次查找相同的元素。

如需鏈接一個動作,您只需簡單地把該動作追加到之前的動作上。

78.解釋”deferreds”。

開發網站的過程中,我們經常遇到某些耗時很長的javascript操作。其中,既有異步的操作(比如ajax讀取服務器數據),也有同步的操作(比如遍歷一個大型數組),它們都不是立即能得到結果的。

通常的做法是,爲它們指定回調函數(callback)。即事先規定,一旦它們運行結束,應該調用哪些函數。

但是,在回調函數方面,jQuery的功能非常弱。爲了改變這一點,jQuery開發團隊就設計了deferred對象。

簡單說,deferred對象就是jQuery的回調函數解決方案。在英語中,defer的意思是”延遲”,所以deferred對象的含義就是”延遲”到未來某個點再執行。

79.你知道哪些針對jQuery的優化方法?

  • 1.總是從ID選擇器開始繼承在jQuery中最快的選擇器是ID選擇器,因爲它直接來自於JavaScript的getElementById()方法。

例如有一段HTML代碼:

 <div id="content">

     <form method="post"action="#">

         <h2>交通信號燈</h2>

         <ul id="traffic_light">

             <li>

                 <input type="radio"class="on"name="light"value="red"/>紅色

             </li>

             <li>

                 <input type="radio"class="off"name="light"value="yellow"/>黃色

            </li>

            <li>

                <input type="radio"class="off"name="light"value="green"/>綠色

            </li>

        </ul>

        <input class="button"id="traffic_button"type="submit"value="Go"/>

    </form>

</div>

比如需要選擇紅綠單選框,那麼可以使用一個tag name來限制(修飾)class,如下所示:var active_light=(input.on);IDvaractivelight=(“input.on”);當然也可以結合就近的ID,如下所示:varactivelight=(“#traffic_light input.on”); 如果採用下面的選擇器,那麼效率是低效的。var traffic_button=(“#content.button”);因爲button已經有ID了,我們可以直接使用ID選擇器。如下所示:var traffic_button=(“#content.button”);因爲button已經有ID了,我們可以直接使用ID選擇器。如下所示:var traffic_button=(“#traffic_button”);當然這只是對於單一的元素來講。如果你需要選擇多個元素,這必然會涉及到DOM遍歷和循環,爲了提高性能,建議從最近的ID開始繼承。如下所示:var traffic_lights=$(“#traffic_light input”);

  • 2.在class前使用tag(標籤名)在jQuery中第二快的選擇器是tag(標籤)選擇器(比如:$(“head”))。

跟ID選擇器累時,因爲它來自原生的getElementsByTagName()方法。繼續看剛纔那段HTML代碼:

在使用tag來修飾class的時候,我們需要注意以下幾點:(1)不要使用tag來修飾ID,如下所示:var content=(“div#content”);這樣一來,選擇器會先遍歷所有的div元素,然後匹配#content。(好像jQuery從1.3.1開始改變了選擇器核心後,不存在這個問題了。暫時無法考證。)(2)不要畫蛇添足的使用ID來修飾ID,如下所示:var traffic_light=(“div#content”);這樣一來,選擇器會先遍歷所有的div元素,然後匹配#content。(好像jQuery從1.3.1開始改變了選擇器核心後,不存在這個問題了。暫時無法考證。)(2)不要畫蛇添足的使用ID來修飾ID,如下所示:var traffic_light=(“#content#traffic_light”);

  • 3.將jQuery對象緩存起來把jQuery對象緩存起來就是要告訴我們要養成將jQuery對象緩存進變量的習慣。

下面是一個jQuery新手寫的一段代碼:

$("#traffic_light input.on").bind("click",function(){});

$("#traffic_light input.on").css("border","1px dashed yellow");

$("#traffic_light input.on").css("background-color","orange");

$("#traffic_light input.on").fadeIn("slow");

但切記不要這麼做。我們應該先將對象緩存進一個變量然後再操作,如下所示:

記住,永遠不要讓相同的選擇器在你的代碼裏出現多次.注:(1)爲了區分普通的JavaScript對象和jQuery對象,可以在變量首字母前加上$符號。(2)上面代碼可以使用jQuery的鏈式操作加以改善。如下所示:

var $active_light = $("#traffic_light input.on");

 

$active_light.bind("click",function(){})

.css("border","1px dashed yellow")

.css("background-color","orange")

.fadeIn("slow");

  • 4.如果你打算在其他函數中使用jQuery對象,那麼你必須把它們緩存到全局環境中。

如下代碼所示:

 // 在全局範圍定義一個對象(例如:window對象)

 window.$my = {

     head:$("head"),

     trafficLight:$("#trafficLight"),

     trafficButton:$("#trafficButton")

 };

 

 function doSomething(){

     // 現在你可以引用存儲的結果並操作它們

    var script=document.createElement("script");

    $my.head.append(script);

 

    // 當你在函數內部操作是,可以繼續將查詢存入全局對象中去.

    $my.coolResults=$("#some_ul li");

    $my.otherResults=$("#some_table td");

 

    // 將全局函數作爲一個普通的jquery對象去使用.

    $my.otherResults.css("border-color","red");

    $my.trafficLight.css("border-color","green");

}

// 你也可以在其他函數中使用它.

這裏的基本思想是在內存中建立你確實想要的東西,然後更新DOM。這並不是一個jQuery最佳實踐,但必須進行有效的JavaScript操作。直接的DOM操作速度很慢。例如,你想動態的創建一組列表元素,千萬不要這樣做,如下所示:對直接的DOM操作進行限制。

var top_100_list = [];// 假設這裏是100個獨一無二的字符串

var $mylist = $("#mylist");// jQuery選擇到<ul>元素

 

for(var i = 0,l = top_100_list.length;i<l;i++) {

    $mylist.append("<li>" + top_100_list[i] + "</li>");

}

我們應該將整套元素字符串在插入進dom中之前先全部創建好,如下所示:

$("#entryform input").bind("focus",function() {

    $(this).addClass("selected");

}).bind("blur",function(){

    $(this).removeClass("selected");

});

  • 5.冒泡除非在特殊情況下,否則每一個js事件(例如:click,mouseover等.)都會冒泡到父級節點。

當我們需要給多個元素調用同個函數時這點會很有用。代替這種效率很差的多元素事件監聽的方法就是,你只需向它們的父節點綁定一次。比如,我們要爲一個擁有很多輸入框的表單綁定這樣的行爲:當輸入框被選中時爲它添加一個class傳統的做法是,直接選中input,然後綁定focus等,如下所示:

$("#entryform").bind("focus",function(e) {

    var $cell = $(e.target); // e.target捕捉到觸發的目標元素

    $cell.addClass("selected");

}).bind("blur",function(e) {

    var $cell = $(e.target);

    $cell.removeClass("selected");

});

當然上面代碼能幫我們完成相應的任務,但如果你要尋求更高效的方法,請使用如下代碼:

通過在父級監聽獲取焦點和失去焦點的事件,對目標元素進行操作。在上面代碼中,父級元素扮演了一個調度員的角色,它可以基於目標元素綁定事件。如果你發現你給很多元素綁定了同一個事件監聽,那麼現在的你肯定知道哪裏做錯了。

  • 6.推遲到$(window).load。

jQuery對於開發者來說有一個很誘人的東西,可以把任何東西掛到(document).ready(document).ready下。儘管(document).rady確實很有用,它可以在頁面渲染時,其它元素還沒下載完成就執行。如果你發現你的頁面一直是載入中的狀態,很有可能就是(document).readyjQuery(document).ready函數引起的。你可以通過將jQuery函數綁定到(window).load事件的方法來減少頁面載入時的cpu使用率。它會在所有的html(包括iframe)被下載完成後執行。一些特效的功能,例如拖放,視覺特效和動畫,預載入隱藏圖像等等,都是適合這種技術的場合。

  • 7.壓縮JavaScript。

在線壓縮地址:http://dean.edwards.name/packer/壓縮之前,請保證你的代碼的規範性,否則可能失敗,導致Js錯誤。

  • 8.儘量使用ID代替Class。

    前面性能優化已經說過,ID選擇器的速度是最快的。所以在HTML代碼中,能使用ID的儘量使用ID來代替class。看下面的一個例子:

 // 創建一個list

 var $myList = $('#myList');

 var myListItems = '<ul>';

 

 for(var i = 0; i < 1000; i ++) {

     myListItems += '<li class = "listItem'+i+'">This is a list item</li>';

     // 這裏使用的是class

 }

 

myListItems += '</ul>';

$myList.html(myListItems);

// 選擇每一個li

 

for(var i = 0; i<1000; i++) {

    var selectedItem = $('.listItem' + i);

}

在上段代碼中,選擇每個li總共只用了61毫秒,相比class的方式,將近快了100倍。 在代碼最後,選擇每個li的過程中,總共用了5066毫秒,超過5秒了。接着我們做一個對比,用ID代替class:

  • 9.給選擇器一個上下文。

jQuery選擇器中有一個這樣的選擇器,它能指定上下文。jQuery(expression,context);通過它,能縮小選擇器在DOM中搜索的範圍,達到節省時間,提高效率。普通方式:(.myDiv)(‘.myDiv′)改進方式:(‘.myDiv’,$(“#listItem”))。

  • 10.慎用.live()方法(應該說盡量不要使用)。

這是jQuery1.3.1版本之後增加的方法,這個方法的功能就是爲新增的DOM元素動態綁定事件。但對於效率來說,這個方法比較佔用資源。所以請儘量不要使用它。例如有這麼一段代碼:

 <script type="text/javascript">

     $(function(){

 

         $("p").click(function(){

             alert($(this).text());

         });

 

         $("button").click(function(){

             $("<p>this is second p</p>").appendTo("body");

        });

    })

</script>

<body>

    <p>this is first p</p>

    <button>add</button>

</body>

運行後,你會發現新增的p元素,並沒用被綁定click事件。你可以改成.live(“click”)方式解決此問題,代碼如下:

 $(function() {

     $("p").live("click",function() {

         // 改成live方式

         alert($(this).text());

     });

 

     $("button").click(function() {

         $("<p>this is second p</p>").appendTo("body");

     });

})

但我並不建議大家這麼做,我想用另一種方式去解決這個問題,代碼如下:

 $(function() {

     $("p").click(function() {

         alert($(this).text());

     });

 

     $("button").click(function() {

         $("<p>this is second p</p>").click(function() {

             // 爲新增的元素重新綁定一次

             alert($(this).text());

        }).appendTo("body");

    });

})

雖然我把綁定事件重新寫了一次,代碼多了點,但這種方式的效率明顯高於live()方式,特別是在頻繁的DOM操作中,這點非常明顯。

80.請解釋.end()的用途。

在官方的API上是這樣描述end()方法的:“回到最近的一個”破壞性”操作之前。即,將匹配的元素列表變爲前一次的狀態。”;看樣子好像是找到最後一次操作的元素的上一元素,在如下的例子中:html代碼:

複製代碼代碼如下:

<div>測試內容1</div><div>測試內容2</div>

jQuery代碼:

複製代碼代碼如下:

$('<p>新增內容</p>').appendTo('div').addClass('c1').end().addClass('c2');

複製代碼代碼如下:

<div>測試內容1

    <p class="c1 c2">新增內容</p>

</div>

<div>測試內容2

    <p class="c1">新增內容</p>

</div>

這裏我就有一點不太明白了,怎麼只有第一個

標籤有兩個樣式,end()方法後返回的是什麼,在火狐裏添加了監控,得到如下結果1.$(‘新增內容‘).appendTo(‘div’)返回的是:[p,p]對象數組,即新增後的兩個p標籤;

2.$(‘新增內容‘).appendTo(‘div’).addClass(‘c1’)返回的是:[p.c1,p.c1]對象數組,即添加了c1類樣式後的p對象數組;

3.$(‘新增內容‘).appendTo(‘div’).addClass(‘c1’).end()返回的是[p.c1],是第1個中的,在2操作中,最後“破壞”的是第2個中的,所以他的前一次操作的對象是第1個中的,返回的就是它;

4.$(‘新增內容‘).appendTo(‘div’).addClass(‘c1’).end().addClass(‘c2’)返回的仍然是第1個中的;現在算是有點明白了,關鍵是要搞清楚最後一次操作的元素的上一元素是什麼。

81.你如何給一個事件處理函數命名空間,爲什麼要這樣做?

任何作爲type參數的字符串都是合法的;如果一個字符串不是原生的JavaScript事件名,那麼這個事件處理函數會綁定到一個自定義事件上。這些自定義事件絕對不會由瀏覽器觸發,但可以通過使用.trigger()或者.triggerHandler()在其他代碼中手動觸發。如果type參數的字符串中包含一個點(.)字符,那麼這個事件就看做是有命名空間的了。這個點字符就用來分隔事件和他的命名空間。舉例來說,如果執行.bind(‘click.name’,handler),那麼字符串中的click是事件類型,而字符串name就是命名空間。命名空間允許我們取消綁定或者觸發一些特定類型的事件,而不用觸發別的事件。參考unbind()來獲取更多信息。

jQuery的bind/unbind方法應該說使用很簡單,而且大多數時候可能並不會用到,取而代之的是直接用click/keydown之類的事件名風格的方法來做事件綁定操作。

但假設如下情況:需要在運行時根據用戶交互的結果進行不同click事件處理邏輯的綁定,因而理論上會無數次對某一個事件進行bind/unbind操作。但又希望unbind的時候只把自己綁上去的處理邏輯給釋放掉而不是所有其他地方有可能的額外的同一事件綁定邏輯。這時候如果直接用.click()/.bind(‘click’)加上.unbind(‘click’)來進行重複綁定的話,被unbind掉的將是所有綁定在元素上的click處理邏輯,潛在會影響到該元素其他第三方的行爲。

當然如果在bind的時候是顯示定義了function變量的話,可以在unbind的時候提供function作爲第二個參數來指定只unbind其中一個處理邏輯,但實際應用中很可能會碰到各種進行匿名函數綁定的情況。對於這種問題,jQuery的解決方案是使用事件綁定的命名空間。即在事件名稱後添加.something來區分自己這部分行爲邏輯範圍。

比如用.bind(‘click.myCustomRoutine’,function(){…});同樣是把匿名函數綁定到click事件(你可以用自己的命名空間多次綁定不同的行爲方法上去),當unbind的時候用.unbind(‘click.myCustomRoutine’)即可釋放所有綁定到.myCustomRoutine命名空間的click事件,而不會解除其他通過.bind(‘click’)或另外的命名空間所綁定的事件行爲。同時,使用命令空間還可以讓你一次性unbind所有此命名空間下的自定義事件綁定,通過.unbind(‘.myCustomRoutine’)即可。要注意的是,jQuery的命名空間並不支持多級空間。

因爲在jQuery裏面,如果用.unbind(‘click.myCustomRoutine.myCustomSubone’),解除的是命名空間分別爲myCustomRoutine和myCustomSubone的兩個並列命名空間下的所有click事件,而不是”myCustomRoutine下的myCustomSubone子空間”。

82.請說出你可以傳遞給jQuery方法的四種不同值。

選擇器(字符串),HTML(字符串),回調函數,HTML元素,對象,數組,元素數組,jQuery對象等。

83.什麼是效果隊列?

jQuery中有個動畫隊列的機制。當我們對一個對象添加多次動畫效果時後添加的動作就會被放入這個動畫隊列中,等前面的動畫完成後再開始執行。可是用戶的操作往往都比動畫快,如果用戶對一個對象頻繁操作時不處理動畫隊列就會造成隊列堆積,影響到效果。jQuery中有stop這個方法可以停止當前執行的動畫,並且它有兩個布爾參數,默認值都爲false。第一個參數爲true時會清空動畫隊列,第二個參數爲true時會瞬間完成掉當前動畫。所以,我們經常使用obj.stop(true,true)來停止動畫。但是這還不夠!正如jQuery文檔中的說法,即使第二個參數爲true,也僅僅是把當前在執行的動畫跳轉到完成狀態。這時第一個參數如果也爲true,後面的隊列就會被清空。如果一個效果需要多個動畫同時處理,我們僅完成其中的一個而把後面的隊列丟棄了,這就會出現意料之外的結果。

84.請指出.get(),[],eq()的區別。

eq:返回是一個jquery對象作用是將匹配的元素集合縮減爲一個元素。這個元素在匹配元素集合中的位置變爲0,而集合長度變成1。

get:是一個html對象數組作用是取得其中一個匹配的元素。num表示取得第幾個匹配的元素。

85.請指出.fn的區別,或者說出$.fn的用途。

Jquery爲開發插件提供了兩個方法,分別是:

$.extend(obj);

$.fn.extend(obj);

  • 1.那麼這兩個分別是什麼意思? 
    $.extend(obj);是爲了擴展jquery本身,爲類添加新的方法。

$.fn.extend(obj);給JQUERY對象添加方法。

  • 2..fnfnprototype.fn中的fn是什麼意思,其實是prototype,即.fn=$.prototype; 
    具體用法請看下面的例子:

$.extend({

 

    add:function(a, b) {

        return a+b;

    }

})

 

$.add(5,8); // return 13

注意沒有,這邊的調用直接調用,前面不用任何對象。直接$.+方法名

$.fn.extend(obj);對prototype進行擴展,爲jquery類添加成員函數,jquery類的實例可以使用這個成員函數。

 $.fn.extend({

 

     clickwhile:function(){

 

         $(this).click(function(){

             alert($(this).val())

         })

     }

 })

 

$('input').clickwhile(); // 當點擊輸入框會彈出該對象的Value值

注意調用時候前面是有對象的。即$(‘input’)這麼個東西。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章