51.你是如何組織自己的代碼?是使用模塊模式,還是使用經典繼承的方法? 請看文章-JavaScript之模塊化編程和Javascript之對象的繼承 52.請指出JavaScript宿主對象和原生對象的區(qū)別? 原生對象 ECMA-262 把本地對象(native object)定義為“獨立于宿主環(huán)境的 ECMAScript 實現(xiàn)提供的對象”。 “本地對象”包含哪些內容:Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError。 由此可以看出,簡單來說,本地對象就是 ECMA-262 定義的類(引用類型)。 內置對象 ECMA-262 把內置對象(built-in object)定義為“由 ECMAScript 實現(xiàn)提供的、獨立于宿主環(huán)境的所有對象,在 ECMAScript 程序開始執(zhí)行時出現(xiàn)”。這意味著開發(fā)者不必明確實例化內置對象,它已被實例化了。 同樣是“獨立于宿主環(huán)境”。根據(jù)定義我們似乎很難分清“內置對象”與“本地對象”的區(qū)別。而ECMA-262 只定義了兩個內置對象,即 Global 和 Math (它們也是本地對象,根據(jù)定義,每個內置對象都是本地對象)。如此就可以理解了。內置對象是本地對象的一種。 宿主對象 何為“宿主對象”?主要在這個“宿主”的概念上,ECMAScript中的“宿主”當然就是我們網(wǎng)頁的運行環(huán)境,即“操作系統(tǒng)”和“瀏覽器”。 所有非本地對象都是宿主對象(host object),即由 ECMAScript 實現(xiàn)的宿主環(huán)境提供的對象。所有的BOM和DOM都是宿主對象。因為其對于不同的“宿主”環(huán)境所展示的內容不同。其實說白了就是,ECMAScript官方未定義的對象都屬于宿主對象,因為其未定義的對象大多數(shù)是自己通過ECMAScript程序創(chuàng)建的對象。 53.call和.apply的區(qū)別是什么? call方法: 語法:call(thisObj,Object) 定義:調用一個對象的一個方法,以另一個對象替換當前對象。 說明:call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對象。 如果沒有提供 thisObj 參數(shù),那么 Global 對象被用作 thisObj。 apply方法: 語法:apply(thisObj,[argArray]) 定義:應用某一對象的一個方法,用另一個對象替換當前對象。 說明:如果 argArray 不是一個有效的數(shù)組或者不是 arguments 對象,那么將導致一個 TypeError。如果沒有提供 argArray 和 thisObj 任何一個參數(shù),那么 Global 對象將被用作 thisObj, 并且無法被傳遞任何參數(shù)。 對于apply和call兩者在作用上是相同的,但兩者在參數(shù)上有以下區(qū)別: 對于第一個參數(shù)意義都一樣,但對第二個參數(shù):apply傳入的是一個參數(shù)數(shù)組,也就是將多個參數(shù)組合成為一個數(shù)組傳入,而call則作為call的參數(shù)傳入(從第二個參數(shù)開始)。如 func.call(func1,var1,var2,var3)對應的apply寫法為:func.apply(func1,[var1,var2,var3])同時使用apply的好處是可以直接將當前函數(shù)的arguments對象作為apply的第二個參數(shù)傳入。 54.請解釋Function.prototype.bind的作用? 55.你何時優(yōu)化自己的代碼? 請看文章JavaScript之高效編程 及JavaScript編碼風格指南。 56.你能解釋一下JavaScript中的繼承是如何工作的嗎? 原型鏈等。 57.在什么時候你會使用document.write()? 大多數(shù)生成的廣告代碼依舊使用document.write(),雖然這種用法會讓人很不爽。 58.請指出瀏覽器特性檢測,特性推斷和瀏覽器UA字符串嗅探的區(qū)別? 特性檢測:為特定瀏覽器的特性進行測試,并僅當特性存在時即可應用特性。 User-Agent檢測:最早的瀏覽器嗅探即用戶代理檢測,服務端(以及后來的客戶端)根據(jù)UA字符串屏蔽某些特定的瀏覽器查看網(wǎng)站內容。 特性推斷:嘗試使用多個特性但僅驗證了其中之一。根據(jù)一個特性的存在推斷另一個特性是否存在。問題是,推斷是假設并非事實,而且可能導致可維護性的問題。 59.請盡可能詳盡的解釋AJAX的工作原理。 請參考文章AJAX工作原理。 60.請解釋JSONP的工作原理,以及它為什么不是真正的AJAX。 JSONP (JSON with Padding)是一個簡單高效的跨域方式,HTML中的script標簽可以加載并執(zhí)行其他域的javascript,于是我們可以通過script標記來動態(tài)加載其他域的資源。例如我要從域A的頁面pageA加載域B的數(shù)據(jù),那么在域B的頁面pageB中我以JavaScript的形式聲明pageA需要的數(shù)據(jù),然后在 pageA中用script標簽把pageB加載進來,那么pageB中的腳本就會得以執(zhí)行。JSONP在此基礎上加入了回調函數(shù),pageB加載完之后會執(zhí)行pageA中定義的函數(shù),所需要的數(shù)據(jù)會以參數(shù)的形式傳遞給該函數(shù)。JSONP易于實現(xiàn),但是也會存在一些安全隱患,如果第三方的腳本隨意地執(zhí)行,那么它就可以篡改頁面內容,截獲敏感數(shù)據(jù)。但是在受信任的雙方傳遞數(shù)據(jù),JSONP是非常合適的選擇。 AJAX是不跨域的,而JSONP是一個是跨域的,還有就是二者接收參數(shù)形式不一樣! 61.你使用過JavaScript模板系統(tǒng)嗎? 如有使用過,請談談你都使用過哪些庫,比如Mustache.js,Handlebars等等。 62.請解釋變量聲明提升。 在JS里定義的變量,存在于作用域鏈里,而在函數(shù)執(zhí)行時會先把變量的聲明進行提升,僅僅是把聲明進行了提升,而其值的定義還在原來位置。示例如下: 復制代碼 1 var test = function() {2 console.log(name); // 輸出:undefined3 var name = 'jeri';4 console.log(name); // 輸出:jeri5 }6 7 test(); 復制代碼 上述代碼與下述代碼等價。 復制代碼 1 var test = function() {2 var name;3 console.log(name); // 輸出:undefined4 name = 'jeri';5 console.log(name); // 輸出:jeri6 }7 8 test(); 復制代碼 由以上代碼可知,在函數(shù)執(zhí)行時,把變量的聲明提升到了函數(shù)頂部,而其值定義依然在原來位置。 63.請描述下事件冒泡機制。 冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發(fā)。 捕獲型事件:事件從最不精確的對象(document 對象)開始觸發(fā),然后到最精確(也可以在窗口級別捕獲事件,不過必須由開發(fā)人員特別指定)。 支持W3C標準的瀏覽器在添加事件時用addEventListener(event,fn,useCapture)方法,基中第3個參數(shù)useCapture是一個Boolean值,用來設置事件是在事件捕獲時執(zhí)行,還是事件冒泡時執(zhí)行。而不兼容W3C的瀏覽器(IE)用attachEvent()方法,此方法沒有相關設置,不過IE的事件模型默認是在事件冒泡時執(zhí)行的,也就是在useCapture等于false的時候執(zhí)行,所以把在處理事件時把useCapture設置為false是比較安全,也實現(xiàn)兼容瀏覽器的效果。 64.'attribute'和'property'的區(qū)別是什么? 1. 定義 Property:屬性,所有的HTML元素都由HTMLElement類型表示,HTMLElement類型直接繼承自Element并添加了一些屬性,添加的這些屬性分別對應于每個HTML元素都有下面的這5個標準特性: id,title,lang,dir,className。DOM節(jié)點是一個對象,因此,他可以和其他的JavaScript對象一樣添加自定義的屬性以及方法。property的值可以是任何的數(shù)據(jù)類型,對大小寫敏感,自定義的property不會出現(xiàn)在html代碼中,只存在js中。 Attribute:特性,區(qū)別于property,attribute只能是字符串,大小寫不敏感,出現(xiàn)在innerHTML中,通過類數(shù)組attributes可以羅列所有的attribute。 2. 相同之處 標準的 DOM properties 與 attributes 是同步的。公認的(非自定義的)特性會被以屬性的形式添加到DOM對象中。如,id,align,style等,這時候操作property或者使用操作特性的DOM方法如getAttribute()都可以操作屬性。不過傳遞給getAttribute()的特性名與實際的特性名相同。因此對于class的特性值獲取的時候要傳入“class”。 3. 不同之處 1).對于有些標準的特性的操作,getAttribute與點號(.)獲取的值存在差異性。如href,src,value,style,onclick等事件處理程序。 2).href:getAttribute獲取的是href的實際值,而點號獲取的是完整的url,存在瀏覽器差異。 65.為什么擴展JavaScript內置對象不是好的做法? 66.為什么擴展JavaScript內置對象是好的做法? 67.請指出document.onload和document.ready兩個事件的區(qū)別。 頁面加載完成有兩種事件,一是ready,表示文檔結構已經加載完成(不包含圖片等非文字媒體文件),二是onload,指示頁面包含圖片等文件在內的所有元素都加載完成。 68.==和===有什么不同? 首先,== equality 等同,=== identity 恒等。 ==, 兩邊值類型不同的時候,要先進行類型轉換,再比較。 ===,不做類型轉換,類型不同的一定不等。 先說 ===,這個比較簡單。下面的規(guī)則用來判斷兩個值是否===相等: 如果類型不同,就[不相等] 如果兩個都是數(shù)值,并且是同一個值,那么[相等];(!例外)的是,如果其中至少一個是NaN,那么[不相等]。(判斷一個值是否是NaN,只能用isNaN()來判斷) 如果兩個都是字符串,每個位置的字符都一樣,那么[相等];否則[不相等]。 如果兩個值都是true,或者都是false,那么[相等]。 如果兩個值都引用同一個對象或函數(shù),那么[相等];否則[不相等]。 如果兩個值都是null,或者都是undefined,那么[相等]。 再說 ==,根據(jù)以下規(guī)則: 如果兩個值類型相同,進行 === 比較。 如果兩個值類型不同,他們可能相等。根據(jù)下面規(guī)則進行類型轉換再比較: 如果一個是null、一個是undefined,那么[相等]。 如果一個是字符串,一個是數(shù)值,把字符串轉換成數(shù)值再進行比較。 如果任一值是 true,把它轉換成 1 再比較;如果任一值是 false,把它轉換成 0 再比較。 如果一個是對象,另一個是數(shù)值或字符串,把對象轉換成基礎類型的值再比較。對象轉換成基礎類型,利用它的toString或者valueOf方法。js核心內置類,會嘗試valueOf先于toString;例外的是Date,Date利用的是toString轉換。非js核心的對象,令說(比較麻煩,我也不大懂) 任何其他組合,都[不相等]。 69.你如何從瀏覽器的URL中獲取查詢字符串參數(shù)。 以下函數(shù)把獲取一個key的參數(shù)。 復制代碼 1 function parseQueryString ( name ){ 2 name = name.replace(/[\[]/,'\\\['); 3 var regexS = '[\\?&]'+name+'=([^&#]*)'; 4 var regex = new RegExp( regexS ); 5 var results = regex.exec( window.location.href ); 6 7 if(results == null) { 8 return ''; 9 } else {10 return results[1];11 }12 } 復制代碼 70.請解釋一下JavaScript的同源策略。 在客戶端編程語言中,如javascript和 ActionScript,同源策略是一個很重要的安全理念,它在保證數(shù)據(jù)的安全性方面有著重要的意義。同源策略規(guī)定跨域之間的腳本是隔離的,一個域的腳本不能訪問和操作另外一個域的絕大部分屬性和方法。那么什么叫相同域,什么叫不同的域呢?當兩個域具有相同的協(xié)議, 相同的端口,相同的host,那么我們就可以認為它們是相同的域。同源策略還應該對一些特殊情況做處理,比如限制file協(xié)議下腳本的訪問權限。本地的HTML文件在瀏覽器中是通過file協(xié)議打開的,如果腳本能通過file協(xié)議訪問到硬盤上其它任意文件,就會出現(xiàn)安全隱患,目前IE8還有這樣的隱患。 71.請描述一下JavaScript的繼承模式。 關于繼承請看文章JavaScript之對象的繼承。 72.如何實現(xiàn)下列代碼:[1,2,3,4,5].duplicator();//[1,2,3,4,5,1,2,3,4,5]。 73.描述一種JavaScript中實現(xiàn)memoization(避免重復運算)的策略。 74.什么是三元表達式?“三元”表示什么意思? 三元表達式:? :。三元--三個操作對象。 在表達式boolean-exp ? value0 : value1 中,如果“布爾表達式”的結果為true,就計算“value0”,而且這個計算結果也就是操作符最終產生的值。如果“布爾表達式”的結果為false,就計算“value1”,同樣,它的結果也就成為了操作符最終產生的值。 75.JavaScript里函數(shù)參數(shù)arguments是數(shù)組嗎? 在函數(shù)代碼中,使用特殊對象 arguments,開發(fā)者無需明確指出參數(shù)名,通過使用下標就可以訪問相應的參數(shù)。 arguments雖然有一些數(shù)組的性質,但其并非真正的數(shù)組,只是一個類數(shù)組對象。其并沒有數(shù)組的很多方法,不能像真正的數(shù)組那樣調用.jion(),.concat(),.pop()等方法。 76.什么是'use strict';?使用它的好處和壞處分別是什么? 在代碼中出現(xiàn)表達式-'use strict'; 意味著代碼按照嚴格模式解析,這種模式使得Javascript在更嚴格的條件下運行。 好處: 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為; 消除代碼運行的一些不安全之處,保證代碼運行的安全; 提高編譯器效率,增加運行速度; 為未來新版本的Javascript做好鋪墊。 壞處: 同樣的代碼,在'嚴格模式'中,可能會有不一樣的運行結果;一些在'正常模式'下可以運行的語句,在'嚴格模式'下將不能運行。 77.解釋'chaining'。 jQuery方法鏈接。直到現(xiàn)在,我們都是一次寫一條jQuery語句(一條接著另一條)。不過,有一種名為鏈接(chaining)的技術,允許我們在相同的元素上運行多條jQuery命令,一條接著另一條。 提示:這樣的話,瀏覽器就不必多次查找相同的元素。 如需鏈接一個動作,您只需簡單地把該動作追加到之前的動作上。 78.解釋'deferreds'。 開發(fā)網(wǎng)站的過程中,我們經常遇到某些耗時很長的javascript操作。其中,既有異步的操作(比如ajax讀取服務器數(shù)據(jù)),也有同步的操作(比如遍歷一個大型數(shù)組),它們都不是立即能得到結果的。 通常的做法是,為它們指定回調函數(shù)(callback)。即事先規(guī)定,一旦它們運行結束,應該調用哪些函數(shù)。 但是,在回調函數(shù)方面,jQuery的功能非常弱。為了改變這一點,jQuery開發(fā)團隊就設計了deferred對象。 簡單說,deferred對象就是jQuery的回調函數(shù)解決方案。在英語中,defer的意思是'延遲',所以deferred對象的含義就是'延遲'到未來某個點再執(zhí)行。 79.你知道哪些針對jQuery的優(yōu)化方法? 1.總是從ID選擇器開始繼承在jQuery中最快的選擇器是ID選擇器,因為它直接來自于JavaScript的getElementById()方法。 例如有一段HTML代碼: 復制代碼 1 2 17 復制代碼 比如需要選擇紅綠單選框,那么可以使用一個tag name來限制(修飾)class,如下所示:var active_light=$(“input.on”);當然也可以結合就近的ID,如下所示:var active_light=$(“#traffic_light input.on”); 如果采用下面的選擇器,那么效率是低效的。var traffic_button=$(“#content.button”);因為button已經有ID了,我們可以直接使用ID選擇器。如下所示:var traffic_button=$(“#traffic_button”);當然這只是對于單一的元素來講。如果你需要選擇多個元素,這必然會涉及到DOM遍歷和循環(huán),為了提高性能,建議從最近的ID開始繼承。如下所示:var traffic_lights=$(“#traffic_light input”); 2.在class前使用tag(標簽名)在jQuery中第二快的選擇器是tag(標簽)選擇器(比如:$(“head”))。 跟ID選擇器累時,因為它來自原生的getElementsByTagName()方法。繼續(xù)看剛才那段HTML代碼: 在使用tag來修飾class的時候,我們需要注意以下幾點:(1)不要使用tag來修飾ID,如下所示:var content=$(“div#content”);這樣一來,選擇器會先遍歷所有的div元素,然后匹配#content。(好像jQuery從1.3.1開始改變了選擇器核心后,不存在這個問題了。暫時無法考證。)(2)不要畫蛇添足的使用ID來修飾ID,如下所示:var traffic_light=$(“#content#traffic_light”); 3.將jQuery對象緩存起來把jQuery對象緩存起來就是要告訴我們要養(yǎng)成將jQuery對象緩存進變量的習慣。 下面是一個jQuery新手寫的一段代碼: 1 $('#traffic_light input.on').bind('click',function(){});2 $('#traffic_light input.on').css('border','1px dashed yellow');3 $('#traffic_light input.on').css('background-color','orange');4 $('#traffic_light input.on').fadeIn('slow'); 但切記不要這么做。我們應該先將對象緩存進一個變量然后再操作,如下所示: 記住,永遠不要讓相同的選擇器在你的代碼里出現(xiàn)多次.注:(1)為了區(qū)分普通的JavaScript對象和jQuery對象,可以在變量首字母前加上$符號。(2)上面代碼可以使用jQuery的鏈式操作加以改善。如下所示: 復制代碼 1 var $active_light = $('#traffic_light input.on');2 3 $active_light.bind('click',function(){})4 .css('border','1px dashed yellow')5 .css('background-color','orange')6 .fadeIn('slow'); 復制代碼 4.如果你打算在其他函數(shù)中使用jQuery對象,那么你必須把它們緩存到全局環(huán)境中。 如下代碼所示: 復制代碼 1 // 在全局范圍定義一個對象(例如:window對象) 2 window.$my = { 3 head:$('head'), 4 trafficLight:$('#trafficLight'), 5 trafficButton:$('#trafficButton') 6 }; 7 8 function doSomething(){ 9 // 現(xiàn)在你可以引用存儲的結果并操作它們10 var script=document.createElement('script');11 $my.head.append(script);12 13 // 當你在函數(shù)內部操作是,可以繼續(xù)將查詢存入全局對象中去.14 $my.coolResults=$('#some_ul li');15 $my.otherResults=$('#some_table td');16 17 // 將全局函數(shù)作為一個普通的jquery對象去使用.18 $my.otherResults.css('border-color','red');19 $my.trafficLight.css('border-color','green');20 }21 // 你也可以在其他函數(shù)中使用它. 復制代碼 這里的基本思想是在內存中建立你確實想要的東西,然后更新DOM。這并不是一個jQuery最佳實踐,但必須進行有效的JavaScript操作。直接的DOM操作速度很慢。例如,你想動態(tài)的創(chuàng)建一組列表元素,千萬不要這樣做,如下所示:對直接的DOM操作進行限制。 復制代碼 1 var top_100_list = [];// 假設這里是100個獨一無二的字符串2 var $mylist = $('#mylist');// jQuery選擇到
復制代碼 我們應該將整套元素字符串在插入進dom中之前先全部創(chuàng)建好,如下所示: 1 $('#entryform input').bind('focus',function() {2 $(this).addClass('selected');3 }).bind('blur',function(){4 $(this).removeClass('selected');5 }); 5.冒泡除非在特殊情況下,否則每一個js事件(例如:click,mouseover等.)都會冒泡到父級節(jié)點。 當我們需要給多個元素調用同個函數(shù)時這點會很有用。代替這種效率很差的多元素事件監(jiān)聽的方法就是,你只需向它們的父節(jié)點綁定一次。比如,我們要為一個擁有很多輸入框的表單綁定這樣的行為:當輸入框被選中時為它添加一個class傳統(tǒng)的做法是,直接選中input,然后綁定focus等,如下所示: 復制代碼 1 $('#entryform').bind('focus',function(e) {2 var $cell = $(e.target); // e.target捕捉到觸發(fā)的目標元素3 $cell.addClass('selected');4 }).bind('blur',function(e) {5 var $cell = $(e.target);6 $cell.removeClass('selected');7 }); 復制代碼 當然上面代碼能幫我們完成相應的任務,但如果你要尋求更高效的方法,請使用如下代碼: 通過在父級監(jiān)聽獲取焦點和失去焦點的事件,對目標元素進行操作。在上面代碼中,父級元素扮演了一個調度員的角色,它可以基于目標元素綁定事件。如果你發(fā)現(xiàn)你給很多元素綁定了同一個事件監(jiān)聽,那么現(xiàn)在的你肯定知道哪里做錯了。 6.推遲到$(window).load。 jQuery對于開發(fā)者來說有一個很誘人的東西,可以把任何東西掛到$(document).ready下。盡管$(document).rady確實很有用,它可以在頁面渲染時,其它元素還沒下載完成就執(zhí)行。如果你發(fā)現(xiàn)你的頁面一直是載入中的狀態(tài),很有可能就是$(document).ready函數(shù)引起的。你可以通過將jQuery函數(shù)綁定到$(window).load事件的方法來減少頁面載入時的cpu使用率。它會在所有的html(包括iframe)被下載完成后執(zhí)行。一些特效的功能,例如拖放,視覺特效和動畫,預載入隱藏圖像等等,都是適合這種技術的場合。 7.壓縮JavaScript。 在線壓縮地址:http://dean./packer/壓縮之前,請保證你的代碼的規(guī)范性,否則可能失敗,導致Js錯誤。 8.盡量使用ID代替Class。 前面性能優(yōu)化已經說過,ID選擇器的速度是最快的。所以在HTML代碼中,能使用ID的盡量使用ID來代替class??聪旅娴囊粋€例子: 復制代碼 1 // 創(chuàng)建一個list 2 var $myList = $('#myList'); 3 var myListItems = '
復制代碼 在上段代碼中,選擇每個li總共只用了61毫秒,相比class的方式,將近快了100倍。 在代碼最后,選擇每個li的過程中,總共用了5066毫秒,超過5秒了。接著我們做一個對比,用ID代替class: 9.給選擇器一個上下文。 jQuery選擇器中有一個這樣的選擇器,它能指定上下文。jQuery(expression,context);通過它,能縮小選擇器在DOM中搜索的范圍,達到節(jié)省時間,提高效率。普通方式:$(‘.myDiv’)改進方式:$(‘.myDiv’,$(“#listItem”))。 10.慎用.live()方法(應該說盡量不要使用)。 這是jQuery1.3.1版本之后增加的方法,這個方法的功能就是為新增的DOM元素動態(tài)綁定事件。但對于效率來說,這個方法比較占用資源。所以請盡量不要使用它。例如有這么一段代碼: 復制代碼 1 13 14 this is first p 15 16復制代碼 運行后,你會發(fā)現(xiàn)新增的p元素,并沒用被綁定click事件。你可以改成.live(“click”)方式解決此問題,代碼如下: 復制代碼 1 $(function() { 2 $('p').live('click',function() { 3 // 改成live方式 4 alert($(this).text()); 5 }); 6 7 $('button').click(function() { 8 $(' this is second p ').appendTo('body'); 9 });10 })復制代碼 但我并不建議大家這么做,我想用另一種方式去解決這個問題,代碼如下: 復制代碼 1 $(function() { 2 $('p').click(function() { 3 alert($(this).text()); 4 }); 5 6 $('button').click(function() { 7 $(' this is second p ').click(function() { 8 // 為新增的元素重新綁定一次 9 alert($(this).text());10 }).appendTo('body');11 });12 })復制代碼 雖然我把綁定事件重新寫了一次,代碼多了點,但這種方式的效率明顯高于live()方式,特別是在頻繁的DOM操作中,這點非常明顯。 80.請解釋.end()的用途。 在官方的API上是這樣描述end()方法的:“回到最近的一個'破壞性'操作之前。即,將匹配的元素列表變?yōu)榍耙淮蔚臓顟B(tài)?!?;看樣子好像是找到最后一次操作的元素的上一元素,在如下的例子中:html代碼: 復制代碼代碼如下: 1 測試內容1 測試內容2 jQuery代碼: 復制代碼代碼如下: 1 $(' 新增內容 ').appendTo('div').addClass('c1').end().addClass('c2');復制代碼代碼如下: 復制代碼 1 測試內容12 4 新增內容 3測試內容25 新增內容 6復制代碼 這里我就有一點不太明白了,怎么只有第一個 標簽有兩個樣式,end()方法后返回的是什么,在火狐里添加了監(jiān)控,得到如下結果:1.$(' 新增內容 ').appendTo('div')返回的是:[p,p]對象數(shù)組,即新增后的兩個p標簽;2.$('新增內容 ').appendTo('div').addClass('c1')返回的是:[p.c1,p.c1]對象數(shù)組,即添加了c1類樣式后的p對象數(shù)組;3.$('新增內容 ').appendTo('div').addClass('c1').end()返回的是[p.c1],是第1個中的 ,在2操作中,最后“破壞”的是第2個 中的 ,所以他的前一次操作的對象是第1個 中的 ,返回的就是它;4.$(' 新增內容 ').appendTo('div').addClass('c1').end().addClass('c2')返回的仍然是第1個中的 ;現(xiàn)在算是有點明白了,關鍵是要搞清楚最后一次操作的元素的上一元素是什么。 81.你如何給一個事件處理函數(shù)命名空間,為什么要這樣做? 任何作為type參數(shù)的字符串都是合法的;如果一個字符串不是原生的JavaScript事件名,那么這個事件處理函數(shù)會綁定到一個自定義事件上。這些自定義事件絕對不會由瀏覽器觸發(fā),但可以通過使用.trigger()或者.triggerHandler()在其他代碼中手動觸發(fā)。如果type參數(shù)的字符串中包含一個點(.)字符,那么這個事件就看做是有命名空間的了。這個點字符就用來分隔事件和他的命名空間。舉例來說,如果執(zhí)行.bind('click.name',handler),那么字符串中的click是事件類型,而字符串name就是命名空間。命名空間允許我們取消綁定或者觸發(fā)一些特定類型的事件,而不用觸發(fā)別的事件。參考unbind()來獲取更多信息。 jQuery的bind/unbind方法應該說使用很簡單,而且大多數(shù)時候可能并不會用到,取而代之的是直接用click/keydown之類的事件名風格的方法來做事件綁定操作。 但假設如下情況:需要在運行時根據(jù)用戶交互的結果進行不同click事件處理邏輯的綁定,因而理論上會無數(shù)次對某一個事件進行bind/unbind操作。但又希望unbind的時候只把自己綁上去的處理邏輯給釋放掉而不是所有其他地方有可能的額外的同一事件綁定邏輯。這時候如果直接用.click()/.bind('click')加上.unbind('click')來進行重復綁定的話,被unbind掉的將是所有綁定在元素上的click處理邏輯,潛在會影響到該元素其他第三方的行為。 當然如果在bind的時候是顯示定義了function變量的話,可以在unbind的時候提供function作為第二個參數(shù)來指定只unbind其中一個處理邏輯,但實際應用中很可能會碰到各種進行匿名函數(shù)綁定的情況。對于這種問題,jQuery的解決方案是使用事件綁定的命名空間。即在事件名稱后添加.something來區(qū)分自己這部分行為邏輯范圍。 比如用.bind('click.myCustomRoutine',function(){...});同樣是把匿名函數(shù)綁定到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(字符串),回調函數(shù),HTML元素,對象,數(shù)組,元素數(shù)組,jQuery對象等。 83.什么是效果隊列? jQuery中有個動畫隊列的機制。當我們對一個對象添加多次動畫效果時后添加的動作就會被放入這個動畫隊列中,等前面的動畫完成后再開始執(zhí)行??墒怯脩舻牟僮魍急葎赢嬁?,如果用戶對一個對象頻繁操作時不處理動畫隊列就會造成隊列堆積,影響到效果。jQuery中有stop這個方法可以停止當前執(zhí)行的動畫,并且它有兩個布爾參數(shù),默認值都為false。第一個參數(shù)為true時會清空動畫隊列,第二個參數(shù)為true時會瞬間完成掉當前動畫。所以,我們經常使用obj.stop(true,true)來停止動畫。但是這還不夠!正如jQuery文檔中的說法,即使第二個參數(shù)為true,也僅僅是把當前在執(zhí)行的動畫跳轉到完成狀態(tài)。這時第一個參數(shù)如果也為true,后面的隊列就會被清空。如果一個效果需要多個動畫同時處理,我們僅完成其中的一個而把后面的隊列丟棄了,這就會出現(xiàn)意料之外的結果。 84.請指出.get(),[],eq()的區(qū)別。 eq:返回是一個jquery對象作用是將匹配的元素集合縮減為一個元素。這個元素在匹配元素集合中的位置變?yōu)?,而集合長度變成1。 get:是一個html對象數(shù)組作用是取得其中一個匹配的元素。num表示取得第幾個匹配的元素。 85.請指出.bind(),.live()和.delegate()的區(qū)別。 在操縱DOM的語境中,document是根節(jié)點?,F(xiàn)在我們可以較容易地說明.bind()、.live()和.delegate()的不同之處了。 .bind() 1 $('a').bind('click', function() {alert('That tickles!')}); 這是最簡單的綁定方法了。JQuery掃描文檔找出所有的$(‘a’)元素,并把alert函數(shù)綁定到每個元素的click事件上。 .live() 1 $('a').live('click', function() {alert('That tickles!')}); JQuery把alert函數(shù)綁定到$(document)元素上,并使用’click’和’a’作為參數(shù)。任何時候只要有事件冒泡到document節(jié)點上,它就查看該事件是否是一個click事件,以及該事件的目標元素與’a’這一CSS選擇器是否匹配,如果都是的話,則執(zhí)行函數(shù)。 live方法還可以被綁定到具體的元素(或context)而不是document上,像這樣: 1 $('a', $('#container')[0]).live(...); .delegate() 1 $('#container').delegate('a', 'click', function() {alert('That tickles!')}); JQuery掃描文檔查找$(‘#container’),并使用click事件和’a’這一CSS選擇器作為參數(shù)把alert函數(shù)綁定到$(‘#container’)上。任何時候只要有事件冒泡到$(‘#container’)上,它就查看該事件是否是click事件,以及該事件的目標元素是否與CCS選擇器相匹配。如果兩種檢查的結果都為真的話,它就執(zhí)行函數(shù)。 可以注意到,這一過程與.live()類似,但是其把處理程序綁定到具體的元素而非document這一根上。精明的JS’er們可能會做出這樣的結論,即$('a').live()==$(document).delegate('a'),是這樣嗎?嗯,不,不完全是。 為什么.delegate()要比.live()好用? 基于幾個原因,人們通常更愿意選用jQuery的delegate方法而不是live方法??紤]下面的例子: 1 $('a').live('click', function(){blah()}); // 或者2 $(document).delegate('a', 'click', function(){blah()}); 速度 后者實際上要快過前者,因為前者首先要掃描整個的文檔查找所有的$(‘a’)元素,把它們存成jQuery對象。盡管live函數(shù)僅需要把’a’作為串參數(shù)傳遞以用做之后的判斷,但是$()函數(shù)并未知道被鏈接的方法將會是.live()。而另一方面,delegate方法僅需要查找并存儲$(document)元素。 一種尋求避開這一問題的方法是調用在$(document).ready()之外綁定的live,這樣它就會立即執(zhí)行。在這種方式下,其會在DOM獲得填充之前運行,因此就不會查找元素或是創(chuàng)建jQuery對象了。 靈活性和鏈能力 live函數(shù)也挺令人費解的。想想看,它被鏈到$(‘a’)對象集上,但其實際上是在$(document)對象上發(fā)生作用。由于這個原因,它能夠試圖以一種嚇死人的方式來把方法鏈到自身上。實際上,我想說的是,以$.live(‘a’,…)這一形式作為一種全局性的jQuery方法,live方法會更具意義一些。 僅支持CSS選擇器 最后一點,live方法有一個非常大的缺點,那就是它僅能針對直接的CSS選擇器做操作,這使得它變得非常的不靈活。 為什么選擇.live()或.delegate()而不是.bind()? 畢竟,bind看起來似乎更加的明確和直接,難道不是嗎?嗯,有兩個原因讓我們更愿意選擇delegate或live而不是bind: 為了把處理程序附加到可能還未存在于DOM中的DOM元素之上。因為bind是直接把處理程序綁定到各個元素上,它不能把處理程序綁定到還未存在于頁面中的元素之上。 如果你運行了$(‘a’).bind(…),而后新的鏈接經由AJAX加入到了頁面中,則你的bind處理程序對于這些新加入的鏈接來說是無效的。而另一方面live和delegate則是被綁定到另一個祖先節(jié)點上,因此其對于任何目前或是將來存在于該祖先元素之內的元素都是有效的。 或者為了把處理程序附加到單個元素上或是一小組元素之上,監(jiān)聽后代元素上的事件而不是循環(huán)遍歷并把同一個函數(shù)逐個附加到DOM中的100個元素上。把處理程序附加到一個(或是一小組)祖先元素上而不是直接把處理程序附加到頁面中的所有元素上,這種做法帶來了性能上的好處。 停止傳播 最后一個我想做的提醒與事件傳播有關。通常情況下,我們可以通過使用這樣的事件方法來終止處理函數(shù)的執(zhí)行: 1 $('a').bind('click', function(e) {2 e.preventDefault();3 // 或者 e.stopPropagation();4 }); 不過,當我們使用live或是delegate方法的時候,處理函數(shù)實際上并沒有在運行,需要等到事件冒泡到處理程序實際綁定的元素上時函數(shù)才會運行。而到此時為止,我們的其他的來自.bind()的處理函數(shù)早已運行了。 86.請指出$和$.fn的區(qū)別,或者說出$.fn的用途。 Jquery為開發(fā)插件提供了兩個方法,分別是: 1 $.extend(obj);2 $.fn.extend(obj); 1.那么這兩個分別是什么意思? $.extend(obj);是為了擴展jquery本身,為類添加新的方法。 $.fn.extend(obj);給JQUERY對象添加方法。 2.$.fn中的fn是什么意思,其實是prototype,即$.fn=$.prototype; 具體用法請看下面的例子: 復制代碼 1 $.extend({2 3 add:function(a, b) {4 return a+b;5 }6 })7 8 $.add(5,8); // return 13 復制代碼 注意沒有,這邊的調用直接調用,前面不用任何對象。直接$.+方法名 $.fn.extend(obj);對prototype進行擴展,為jquery類添加成員函數(shù),jquery類的實例可以使用這個成員函數(shù)。 復制代碼 1 $.fn.extend({ 2 3 clickwhile:function(){ 4 5 $(this).click(function(){ 6 alert($(this).val()) 7 }) 8 } 9 })10 11 $('input').clickwhile(); // 當點擊輸入框會彈出該對象的Value值 復制代碼 注意調用時候前面是有對象的。即$('input')這么個東西。 87.請寫出一個函數(shù)實現(xiàn)N!的計算。N取很大的值時,該怎么辦? 使用循環(huán)、遞歸都能寫出函數(shù)。 當N取值很大時,應該考慮把數(shù)值轉化為字符串再進行運算。大數(shù)乘法再轉化為大數(shù)加法運算,其具體算法應該有不少C語言實現(xiàn),可以參考一下。 88.modulo(12,5) //2 ;問題:實現(xiàn)滿足上述結果的modulo函數(shù)。 89.'i'm a lasagna hog'.split('').reverse().join('');問題:上面的語句的返回值是什么? 答案:'goh angasal a m'i'; 90.(window.foo||(window.foo='bar'));問題:window.foo的值是什么? 答案:'bar'只有window.foo為假時的才是上面答案,否則就是它本身的值。 var foo='Hello';(function(){var bar='World';alert(foo+bar);})();alert(foo+bar); 91.問題:上面兩個alert的結果是什么? 答案:'Hello World'和ReferenceError:bar is not defined 92.var foo=[];foo.push(1);foo.push(2);問題:foo.length的值是什么? 答案:2 喜歡編程的寶寶可以加大牛微信 tang365666,備注數(shù)字2 ,即可免費獲取更多編程學習視頻,以及面試題,一定記得備注數(shù)字2 |
|