1. JavaScript
1.1.簡要描述 JavaScript的數據類型?
參考答案:
Java Sc ri pt 的數據類型可以分為原始類型和對象類型。
原始類型包括 string、 number和 boolean三種。其中,字符串是使用一對單引號或者一對雙引號括起來的任意文本;而數值類型都采用64位浮點格式存儲,不區分整數和小數;布爾(邏輯)只能有兩個值: true或 false。
復雜類型指其他對象,如 Array、 Date、 Object等。
除此之外, JavaScript中還有兩個特殊的原始值: null(空)和 undefined(未定義),它們代表了各自特殊類型的唯一成員。
1.2.讀代碼,寫結果
寫出下列表達式的計算結果:
var a= [];
var b= a;
b[0] = 1;
console.log(a[0] ) ; console.log(b[0] ) ; console.log(a===b) ;
參考答案:
上述代碼的結果分別為:
1
1
true
將對象賦值給變量,僅僅是賦值的引用,對象本身並沒有賦值一次,因此,變量 a和 b 指向同一個數組
1.3.簡要描述 null和 undefined的區別
參考答案:
null:是 JavaScript的關鍵字,用於描述“空值”,對其執行 typeof操作,返回“object”,
即為一個特殊的對象值,可以表示數字、字符串和對象是“無值”的。
undefined:是預定義的全局變量,其值為“未定義”,它是變量的一種取值,表示變
量沒有初始化。 當查詢對象屬性、數組元素的值時,如果返回 undefined則表示屬性或者元素不存在;如果函數沒有任何返回值,也返回 undefined。
需要注意的是,雖然 null和 undfined是不同的,但是因為都表示“值的空缺”,兩者可以互換。因此,使用“==”認為二者是相等的,需要使用“===”來區分它們。
1.4.讀代碼,寫結果
寫出下列表達式的計算結果:
10+ "objects" "7" * "4"
1 - "x"
1+ {}
true+ true
2 + null
參考答案:
上述代碼的結果分別為:
10objects
28
NaN
1[object Ojbect] 2
1.5.讀代碼,寫結果
/ /轉換為字符串
/ /轉換為字符
//無法轉換為數值進行計算,因此返回 NaN
//返回對象的 toString( )結果,按照字符串相加/ / bo o l 類型轉換為數值類型
//null轉換為數值 0
寫出下列代碼的輸出結果:
var a= 2;
var obj= { x: 1, y: { z: 2} }; var n= [obj,3,[4,5]];
console.log(a<< 2);
console.log(obj["y"] .z) ;
console.log(n[0] .y["z"] ) ;
console.log(n[2] ["1"] ) ;
delete n[0];
console.log(n[0] .x) ;
參考答案:
上述代碼的輸出結果分別為:
8
2
2
5
console. log(n[ 0] .x) ;此行代碼錯誤,無法輸出有效信息,會輸出 Error信息
1.6.閱讀如下代碼:
var x= 10;
var y= 20;
var z= x< y? x++ : ++y;
上述代碼運行后,變量 x、 y和 z的值為多少?
參考答案:
上述代碼運行后,變量x的值為11;變量 y的值為20;變量 z的值為10。
這是因為,運行第三行代碼時,只執行?后的第一個語句,因此, y的值不發生變化,仍為20;並返回 x的值賦值給變量z,因此z的值為10;然后將 x的值增加1,變為11。
1.7.什么是“邏輯短路”?
參考答案:
邏輯短路是對於邏輯運算而言,是指,僅計算邏輯表達式中的一部分便能確定結果,而不對整個表達式進行計算的現象。
對於“&&”運算符,當第一個操作數為 false時,將不會判斷第二個操作數,因為此時無論第二個操作數為何,最后的運算結果一定是 false;
對於“||”運算符,當第一個操作數為 true時,將不會判斷第二個操作數,因為此時無論第二個操作數為何,最后的運算結果一定是 true。
1.8.閱讀如下代碼
var empAge= 20;
var empName;
if (empAge> 20&& empName.length> 0) {
console.log(1) ;
}
else {
console.log(2) ;
}
上述代碼運行后,將產生有效輸出,還是代碼錯誤?
參考答案:
上述代碼運行,會輸出2,而不會發生錯誤。
這是因為, if條件中的邏輯表達式的第一個條件( empAge> 20)不滿足,會返回false,此時,將發生“邏輯短路”,而不會繼續判斷下一個條件。因此,即使下一個條件中的變量 empName沒有賦值,此時如果計算 empName.length將發生錯誤;但是,因為發生了“邏輯短路”,不會計算此表達式,因此不會發生錯誤。
既然 if條件中的邏輯表達式返回 false,則運行 else語句:輸出2。
1.9.解釋一下 JavaScript中的局部變量與全局變量的區別
參考答案:
全局變量擁有全局作用域,在 JavaScript代碼的任何地方都可以訪問;在函數內聲明的變量只在函數體內有定義,即為局部變量,其作用域是局部性的。
需要注意的是,在函數體內聲明局部變量時,如果不使用 var關鍵字,則將聲明全局變量。
1.10. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var x= "global";
function test() {
var x= "local";
return x;
}
console.log(test( ) ) ;
參考答案:
上述代碼的輸出結果為 local。這是因為,在函數 test()體內,局部變量的優先級高於同名的全局變量。因此,如果在函數體內聲明的局部變量和全局變量重名,則以局部變量優先。因此,調用函數 test()時,返回的是局部變量x,其值為 local。
1.11. 什么是 JavaScript中的函數作用域
參考答案:
J ava Sc ri pt 中的函數作用域是指 : 變量在聲明它的函數體以及這個函數體嵌套的任意函數體內都是有定義的。這意味着,在函數體內聲明的所有變量在整個函數體內始終是可見的,這種特性也被稱為“聲明提前”,即,函數內聲明的所有變量(不涉及到賦值)都被提前至函數的頂部聲明。
比如,查看如下代碼:
function test() {
console.log(x) ;
var x= 10;
console.log(x) ; }
test() ;
上述代碼運行,將先輸出 undefined,再輸出10。
這是因為,雖然變量 x在第二行聲明並賦值,但其有效范圍為整個函數體,因此,第
一行代碼輸出時,表示變量 x已經聲明但是沒有賦值,因此輸出 undefined;第三行代碼
運行時,因為變量 x已經賦值為10,則輸出10。
1.12. 讀代碼,寫結果
寫出下列代碼的輸出結果:
function test() {
var sum= 0;
for (var i= 0; i< 10; i++) {
sum+= i;
}
console.log(sum) ;
console.log(i) ;
}
test() ;
參考答案:
上述代碼中,輸出 sum的值為45;輸出 i的值為10。
這是因為,在函數 test()體內,循環計算完畢后,變量 sum的值為從 0累加到10 的和,即45;變量 i雖然是在 for循環中聲明,但是在整個函數體內都有效(函數作用域),因此,循環完畢后,變量 i的值為10。
1.13. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var x= "global";
function test() {
console.log(x) ;
var x= "local";
console.log(x) ;
}
test() ;
參考答案:
上述代碼中,先輸出 undefined,再輸出 local。
函數 test()體內聲明了與全局變量同名的局部變量 x,則將覆蓋全局變量,即局部變量優先。因此,第一次輸出變量 x時,為輸出局部變量x,此時變量 x只有聲明而沒有賦值,因此輸出 undefined;第二次輸出變量 x時,局部變量x已經賦值,因此輸出字符串local。
1.14. 簡述 arguments對象的作用
參考答案:
在函數代碼中,使用特殊對象 arguments可以訪問函數的參數。即,開發者在定義函數時,無需明確的為方法聲明參數,也可以在方法體中使用 arguments來訪問參數。這是因為, arguments是一種特殊對象,在函數代碼中,表示函數的參數數組。
正因為 arguments表示參數組成的數組,因此,首先可以使用 arguments.length 檢測函數的參數個數,其次,可以通過下標( arguments[index])來訪問某個參數。這樣,可以用 arguments對象判斷傳遞給函數的參數個數並獲取參數,適用於函數參數無法確定個數的情況下。
1.15. 簡要描述 JavaScript中定義函數的幾種方式
參考答案:
JavaScript中,有三種定義函數的方式:
1、函數語句:即使用 function關鍵字顯式定義函數。如:
function f(x){
return x+1;
}
2、函數定義表達式:也稱為“函數直接量”。形如:
var f= function(x){return x+1;};
3、使用 Function()構造函數定義,形如:
Var f= new Function(“x”,”return x+1;”);
1.16. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var f= function (x) { return x* x; }
console.log(f) ;
console.log(f(10) ) ;
參考答案:
上述代碼運行時,先輸出 function(x) { return x* x; };再輸出100。
這是因為,變量 f代表一個函數對象,因此直接輸出變量時,將輸出函數體對應的字符文本; f(10)表示調用變量 f所對應的函數,返回100並輸出。
1.17. 閱讀如下代碼
function f() {
console.log("function") ; }
function test() {
console.log(f) ;
f();
f= "hello";
console.log(f) ;
f();
}
test() ;
上述代碼運行后,輸出結果為?
參考答案:
上述代碼運行,會先輸出
function f() {
console.log("function");
};
然后輸出 function;再輸出 hello;然后會輸出異常信息: string is not a function。
這是因為,定義函數時,函數名稱作為一個全局變量,該變量指向函數對象。因此,執行函數 test中的第一行代碼時,將輸出變量 f所對應的函數對象,即輸出函數體中代碼的字符串形式;然后執行 f()表示調用方法 f,則輸出字符串“function”;執行代碼 f =“hello”,意味着將變量 f的值改為字符串,因此再輸出變量 f時,將輸出字符串“Hello”;而如果試圖再執行 f(),會引發錯誤。這是因為,此時,變量 f不再是一個函數對象,而
是一個普通字符串。
1.18. 列舉幾個 JavaScript中常用的全局函數,並描述其作用
參考答案
JavaScript 中常用的全局函數及其作用如下:
1. parseInt:解析一個字符串並返回一個整數;
}}
2. parseFloat:解析一個字符串並返回一個浮點數;
3. isNaN:檢查某個值是否是數字,返回 true或者 false;
4. encodeURI :把字符串作為 URI進行編碼;
5.decodeURI :對 encodeURI()函數編碼過的 URI進行解碼;
6. eval:計算某個字符串,以得到結果,或者用於執行其中的 JavaScript代碼。
1.19. 閱讀如下代碼
function printArray(arr) {
for (var i in arr) {
if (arr[i] instanceof Array) {
printArray(arr[i] ) ;
} else {
document.write(arr[i] + ' ');
}
}
}
var data= [1, [20, 21], [[301, 302], [310, 311]]]; printArray(data) ;
上述代碼運行后,頁面的輸出結果為?
參考答案:
上述代碼運行,會在頁面輸出:1 20 21 301 302 310 311。
函數 printArray使用了遞歸方式,逐一輸出數組中的每個成員,中間以空格隔開。
1.20. 編寫函數,實現冒泡排序
參考答案:
使用 JavaScript編寫的冒泡排序函數如下所示:
function bubbleSort(arr) {
for (var i= 0; i< arr.length; i++) {
for (var j= 0; j< arr.length- i- 1; j++) {
if (arr[j] > arr[j+ 1]) {
var temp= arr[j];
arr[j] = arr[j + 1];
arr[j+ 1] = temp;
}
}
測試函數 bubbleSort,代碼如下:
var arr= [12, 4, 9, 21, 43, 3]; bubbleSort(arr) ;
console.log(arr) ;
arr[j + 1] = arr[j]; }//插入元素arr[j+ 1] = k;}9
上述代碼運行時,將輸出排序后的結果:[3, 4, 9, 12, 21, 43]。
1.21. 編寫函數,實現插入排序
參考答案:
插入排序是指,先假定將 n個元素的數列分為已有序和無序兩個部分;然后將無序數列的第一個元素與有序數列的元素從后往前逐個進行比較,找出插入位置,將該元素插入到有序數列的合適位置中。過程如下圖所示:
使用 JavaScript編寫的插入排序函數如下所示:
function insertionSort(arr) {
/ /從第二個元素開始
for (var i= 1; i< arr.length; i++) {
//取出待比較的元素
var k= arr[i];
//向前找,找到比當前元素大的位置
var j;
for (j= i- 1; j>= 0&& k< arr[j]; j--) {
/ /向后移動一位
}
測試函數 insertionSort,代碼如下:
var arr= [12, 4, 9, 21, 43, 3]; insertionSort(arr) ;
console.log(arr) ;
/ /驗證方法function verifyCode(id) {if(id.length !=18 )var c= sum%11;//3、分別對應的最后一位身份證的號碼為:1- 0- X-9-8-7-6-5-4-3-2}10
上述代碼運行時,將輸出排序后的結果:[3, 4, 9, 12, 21, 43]。
1.22. 編寫函數,實現對身份證號碼最后一位的驗證
二代身份證號碼為18位,其最后一位(第18位)的計算方法為:
1、 將前面的身份證號碼17位數分別乘以不同的系數。從第一位到第十七位的系數分
別為:
7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2
2、 將這17位數字和系數相乘的結果相加
3、 用加出來和除以11,看余數是多少?
4、 余數只可能有 0-1-2-3-4-5-6-7-8-9-10這11個數字。每個數字所對應
的最后一位身份證的號碼為:1- 0- X-9-8-7-6-5-4-3-2。即,如果余數
是2,就會在身份證的第18位數字上出現羅馬數字的Ⅹ。如果余數是10,身份證
的最后一位號碼就是2。
例如:某男性的身份證號碼是34052419800101001X。驗證其最后一位是否正確時,首先需要得出前17位的乘積和是189,然后用189除以11得出的結果是17+2/11,也就是說其余數是2。最后通過對應規則就可以知道余數2對應的數字是 x。所以,可以判定此身份證號碼的最后一位是合格的。
參考答案:
編寫驗證方法如下:
return false;
/*1、從第一位到第十七位的系數分別為:
7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2
將這17位數字和系數相乘的結果相加。 */
var arr= [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]; var sum= 0;
for(var i=0; i<arr.length; i++){
sum+= parseInt(id.charAt(i) ) * arr[i];
}
//2、用加出來和除以11,看余數,
var ch= ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; var code= ch[c];
var last= id.charAt(17);
last= last=='x' ? 'X': last;
return last== code;
測試該方法:
var id= "34052419800101001X"; console.log(verifyCode(id) ) ;
1.23. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var arr1 = [10, 20];
arr1 .push(30) ;
arr1.push( [40, 50] ) ;
var data= arr1.pop(); console.log(data) ;
參考答案:
上述代碼的輸出結果為[40, 50]。
數組的方法 push()表示入棧,即在棧頂(數組尾端)添加指定的元素;方法 pop()表示出棧,刪除並返回棧頂(數組尾端)的元素。
代碼中,第一次入棧為數字30;第二次入棧為數組[40,50],且該數組排在棧頂。因此,調用方法 pop()時,將刪除並返回棧頂元素[40,50],這是一個數組,因此輸出結果為[40, 50]。
1.24. 什么是棧?在 JavaScript中,如何模擬棧操作?
參考答案:
棧( stack)是一種運算受限的線性表,其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對的把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。棧的操作如下圖所示:
在 JavaScript中,可以使用數組及其相關操作來模擬棧操作。首先,使用數組存儲一列元素,然后使用數組的 push()方法在數組的尾部添加指定的元素,類似於在棧頂添加元素,即頂部入;然后使用數組的 pop()刪除並返回數組尾部的元素,類似於頂部出棧,即后入的元素先出。
1.25. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var arr1 = [10, 20, 30, 40]; arr1 .push(50) ;
arr1 .shift( ) ;
console.log(arr1 ) ;
參考答案:
上述代碼的輸出結果為[20, 30, 40, 50]。
數組的方法 push()表示入棧,即在棧頂(數組尾端)添加指定的元素,因此,數字50將作為數組的最后一個元素;方法 shift()表示刪除並返回棧底(數組頭部)的元素,因此,將從數組刪除數值10。此時,輸出數組,將輸出剩余的4個數值,即[20, 30, 40, 50]。
1.26. 什么是正則表達式?在 JavaScript中,如何應用正則表達式?
參考答案:
正則表達式(Regular Expression)本身就是一個字符串,由一些普通字符和特殊字符組成的,用以描述一種特定的字符規則的表達式。
正則表達式常用於在一段文本中搜索、匹配或替換特定形式的文本。如:詞語出現頻率
}console.log('try block end' ) ;} catch (e) {console.log( 'catch block' ) ;return;} finally{console.log( 'finally block' ) ;}console.log( ' function end' ) ;}add( '10x' ) ;13
統計、驗證字符串是否符合郵箱格式、屏蔽一篇帖子中的限制性詞語等。許多程序設計語言都支持利用正則表達式進行字符串操作。
在 JavaScript中,正則表達式的應用分為兩種:
1、結合 String對象的 replace、 search和 match方法,實現對字符串的替換、查
找和匹配;
2、定義正則表達式對象,實現對字符串的復雜匹配操作。
1.27. 讀代碼,寫結果
寫出下列代碼的輸出結果:
var regexp= /\bdo\b/ig;
var data= 'He does told to Do,do.'; console.log(data.search(regexp) ) ;
參考答案:
上述代碼的輸出結果為3。
String的 search(regexp)方法,用於返回第一次出現匹配指定正則表達式的下標,若沒有匹配則返回- 1。
試題中,正則表達式\bdo\b表示匹配完整的單詞 do,且不區分大小寫。而變量 data 中,第一次出現單詞 do(不區分大小寫)的位置為16。
1.28. 閱讀如下代碼
function add(num) {
try{
num= Number(num) ;
if (isNaN(num)) {
throw new Error('Arguments is NaN');
上述代碼運行后,輸出結果為?
參考答案:
上述代碼運行,會先輸出 catch block;再輸出 finally block。
這是因為,執行代碼 num= Number(num);時,因為傳入的參數值為字符串“10x”,無法轉換為 number類型,則產生錯誤,運行到 catch語句塊中,輸出“catch bloc”;而 finally塊始終會運行,因此繼續輸出“finallyblock”。程序發生異常后,將退出,因此不再執行其他語句。
1.29. 簡要描述 JavaScript中的匿名函數
參考答案:
匿名函數是指在定義時沒有指定名字的函數,且定義后往往直接調用。如:
function(num1, num2) {
console.log( num1 + num2 ); }
這種方式所定義的匿名函數,往往需要直接調用,如:
(function (num1, num2) {
console.log(num1 + num2); }) (10,20);
匿名函數常用於定義不需要重復使用的函數,用完即釋放。另外,對於直接調用的匿名函數而言,可以看成是一個臨時的命名空間,其區域內定義的所有變量,不會污染到全局命名空間。
1.30. 簡要描述 JavaScript中的作用域鏈
參考答案:
任何一段 JavaScript代碼都對應一個作用域鏈,作用域鏈中存放一系列對象,代碼中聲明的變量將作為對象的屬性存放。
在 JavaScript的頂層代碼中,作用域鏈由一個全局對象組成;當定義一個函數時,它保存一個作用域鏈,作用域鏈上有兩個對象,一個是函數對象,一個是全局對象。
每當一個函數被調用時,會創建一個活動對象(也叫上下文對象),函數中的局部變量將作為該對象的屬性存放。
當需要使用一個變量時,將從作用域鏈中逐個查找對象的屬性。比如:要使用變量 a,將先查找作用域中的第一個對象是否有屬性 a,如果有就使用;如果沒有就查找作用域鏈中下一個對象的屬性,以此類推。如果作用域鏈上沒有任何一個對象含有屬性 x,則認為這段代碼的作用域鏈上不存在 x,將拋出引用錯誤異常。
當函數調用完成后,如果沒有其他引用指向為此次調用所創建的上下文對象,該對象將被回收。
1.31. 閱讀如下代碼
var a= 100;
function f() {
var a= 200;
function g() {
return a;
}
return g;
}
console.log(f() () ) ;
上述代碼運行后,輸出結果為?
參考答案:
上述代碼運行,會輸出200。
上述代碼意味着,先執行 f(),得到該函數內嵌套的一個函數對象 g,然后調用這個嵌
套的函數。
定義函數 f時,它保存一個作用域鏈,作用域鏈上有兩個對象,一個是函數對象,
個是全局對象,此時,全局變量 a是全局對象的屬性,和函數對象 f無關。
執行函數 f時,會創建一個活動對象,其中保存變量 a作為函數 f的屬性而存在。
而函數 g嵌套定義在函數 f里,對其訪問變量 a時,它沒有變量 a,則繼續往下查找函數
f。找到函數 f的屬性 a並返回。因此,輸出結果為200。
這種函數將變量包裹起來,外部代碼可以通過內嵌函數 g來訪問函數 f內的局部變量
的方式,也稱為閉包。
1.32. 簡要描述你對閉包的理解
參考答案:
函數對象可以通過作用域鏈相互關聯起來,函數體內部的變量都可以保存在函數作用域
這種特性稱為閉包。這意味着函數變量可以隱藏於作用域鏈之內,看起來好像是函數將
變量包裹了起來。這種方式常用於共享函數內的私有變量。
閉包有如下應用特征:
1、局部變量:在函數中定義有共享意義(如:緩存、計數器等)的局部變量(注:定
義成全局變量會對外造成污染);
2、內嵌函數:在函數中聲明有內嵌函數,內嵌函數對函數中的局部變量進行訪問;
3、外部使用:函數向外返回此內嵌函數,外部可以通過此內嵌函數持有並訪問聲明在
函數中的局部變量,而此變量在外部是通過其他途徑無法訪問的。
1.33. 閱讀如下代碼
var n= 10;
function counter() {
var n= 0;
var g= function () {
return++n;
};
return g;
}
var c1 = counter(); console.log(c1 ( ) ) ; console.log(c1 ( ) ) ; console.log(c1 ( ) ) ;
上述代碼運行后的輸出為?
參考答案:
上述代碼運行后,分別輸出數字1、2、3。
首先從應用上分析,這是一個閉包的典型應用:模擬計數器。調用一次函數 counter,則得到一個計數器,即代碼中的變量 c1,用於統計被調用的次數;每運行一次計數器 c1,則訪問次數加1。因此分別輸出數字1、2、3。
其次從代碼原理來分析:函數 counter返回其內嵌函數 g,該函數中包裹了函數counter的局部變量 n,其初始值為 0;每次運行函數 g,均訪問相應的局部變量 n,從而實現累加計數的效果。
1.34. 閱讀如下代碼
for (var i= 0; i< 3; i++) {
setTimeout(function () { alert(i); }, 3000);
}
上述代碼希望實現:3s后彈出三次警告對話框,對話框中顯示的數字分別為 0、1、2。問,上述代碼能否實現所需要的效果?如果不能,應該如何實現?
參考答案:
上述代碼不能實現所需要的效果。會在3s后彈出三次警告對話框,對話框中的數字均為3。
這是因為,循環結束后,變量 i的值為3;當3s后運行循環中內嵌的函數,執行語句alert(i)時,訪問的是循環中的變量 i。因此,三次彈出均為數值3。
如果希望實現分別彈出數字 0、1、2,需要將代碼修改如下:
for (var i= 0; i< 3; i++) {
(function (n) {
setTimeout(function () { alert(n); }, 3000);
})(i);
}
修改后的代碼中,使用匿名函數封裝一次性定時器的代碼,並在調用匿名函數時,將變量 i的值作為參數傳入。每次循環中,調用一次匿名函數,則啟動一個定時器對象,將相應的數字傳入。3s后執行函數時,不再訪問循環中的局部變量 i,則會依次彈出 0、1、2。
1.35. 簡述 JavaScript中創建自定義對象的方式
參考答案:
自定義對象( user-defined object)指由用戶創建的對象,兼容性問題需要由編寫者
注意。創建自定義對象的方式有:
1、對象直接量
2、 newObject()
3、 function對象模板
4、 Object.create()
1.36. 查看如下 JavaScript代碼:
var p= new User("mary");
alert(p.name) ; //彈出 mary
p.introduce(); //彈出 i am mary
為使上段代碼正確運行,請定義對象 User。
參考答案:
需要使用 function模板創建對象 User,代碼如下:
function User(name) {
this.name= name;
this.introduce= function () {
alert("i am" + this.name);
};
}
1.37. JavaScript中, this關鍵字的作用是什么?
參考答案:
籠統的說,關鍵字 this指向當前對象。比如,頂級代碼中的 this指向全局對象;在指定元素事件的時候, this指定當前發生事件的元素對象。
對於嵌套函數,如果嵌套函數作為方法被調用,其 this指向調用它的對象;如果作為函數調用, this是全局對象或者為 undefined(嚴格模式下)。
1.38. 查看如下 JavaScript代碼:
var o= {
m: function () {
console.log(this) ;
f();
}
};
o.m();
function f() {
console.log(this) ; }
請描述上述代碼的運行結果。
參考答案:
上述代碼在瀏覽器中運行后,第一行的輸出結果類似於: Object{m: function},表示this關鍵字指向調用它的當前對象;第二行的輸出結果為 Window,表示 this關鍵字指向全局變量。
這是因為,調用對象 o的方法 m,在該方法中直接使用 this關鍵字,則指向調用它的對象;然后運行嵌套函數 f時, this指向全局對象,在瀏覽器中運行時,全局對象為Window對象。需要注意的是,如果使用嚴格模式,則第二行會輸出 undefined。
1.39. 查看如下 JavaScript代碼:
var a= 10;
var foo= {
a: 20,
bar: function () { var a= 30; return this.a} }
console.log(foo.bar( ) ) ;
console.log( (foo.bar= foo.bar) ());
上述代碼運行后,輸出結果是?
參考答案:
上述代碼運行后,先輸出20。這是因為調用對象 foo的 bar()方法時, this關鍵字指向調用它的對象,即 foo,因此,輸出該對象中所定義的屬性值。
第二行將輸出 10。這是屬於函數調用,此時,非嚴格模式下 th is指代全局對象window,因此 a的值為10。
1.40. 簡述你對 JavaScript中原型的理解
參考答案:
在 JavaScript中,函數本身就是一個包含了方法和屬性的對象。每個函數中都有一個prototype屬性,該屬性所存儲的就是原型對象。
原型對象用來保存共享屬性和方法,可以通過原型來實現為對象擴展屬性,實現繼承。
1.41. 查看如下 JavaScript代碼:
function Emp(ename, salary) {
this.ename= ename;
this.salary= salary;
this.toString= function(){
return this.ename+ ":" + this.salary;
};
}
var emp1 = new Emp("mary",3500);
var emp2 = new Emp("john", 5500);
Emp.prototype.hireDate= "2015/05/01";
delete emp1.ename;
delete Emp.prototype. hireDate;
console.log(emp1.toString() + ":" + emp1.hireDate); console.log(emp2.toString() + ":" + emp2.hireDate);
上述代碼運行后,輸出結果是?
參考答案:
第一行輸出為: undefined:3500:undefined
第二行輸出為: john:5500:undefined
JavaScript中,每個函數都有一個 prototype屬性,該屬性引用着該函數的原型對象,原型對象中包含着當前函數所有實例共享的方法和屬性。
使用函數的 prototype屬性可以向函數的原型對象添加或刪除屬性和方法,並且這些屬性和方法是這一類對象所共享的。
可以使用 delete關鍵字刪除對象的屬性,包括自有屬性和原型屬性。
1.42. 簡要描述 JavaScript中的自有屬性和原型屬性
參考答案:
自有屬性是指,通過對象的引用添加的屬性,此時,其它對象可能無此屬性。對於自有
屬性,是各個對象所特有的、彼此獨立的屬性。比如:
emp1.job= 'Coder';
原型屬性是指從原型對象中繼承來的屬性,一旦原型對象中屬性值改變,所有繼承自該原型的對象屬性均改變。比如:
Emp.prototype.dept= '研發部';
當需要檢測對象的自有屬性時,可以使用 hasOwnProperty()方法。另,還可以使用 in 操作檢測對象及其原型鏈中是否具備指定屬性。
需要注意的是,在檢測對象屬性時,先檢測自有屬性,再檢測原型屬性。
1.43. 查看如下 JavaScript代碼:
function Hero() {
this.name= "unknown"; }
Hero.prototype.age= 20;
var hero= new Hero();
console.log('name' in hero);
console.log(hero.hasOwnProperty( 'name' ) ) ; console.log('age' in hero);
console.log(hero.hasOwnProperty( 'age' ) ) ; hero.age= 30;
console.log(hero.hasOwnProperty( 'age' ) ) ;
上述代碼運行后,輸出結果是?
參考答案:
輸出結果分別為 true、 true、 true、 false和true。
因為在構造函數中定義了屬性 name,因此變量 hero擁有自有屬性 name。因此在
對 hero用 in操作符檢測 name屬性時,先檢測 name屬性為自有屬性還是原型屬性,則輸出 true;使用 hasOwnProperty()進行判斷也是輸出 true。
使用函數的 prototype向函數的原型添加屬性時,添加的屬性 age為原型屬性。因此,下面代碼:
console.log('age' in hero);
console.log(hero.hasOwnProperty( 'age' ) ) ;
使用 in操作符判斷時,先判斷是否為自有屬性,如果沒有,則在原型鏈中查找屬性age,因此第一行輸出 true;但是 age並非自有屬性,所以第二行輸出 false。
此時,再添加代碼:
hero.age= 30;
這是為 hero定義了同名的自有屬性 age,其值為30。因此,此時再檢測 hero對象是否有自有屬性 age時,將輸出 true。
1.44. 簡要描述你對原型鏈的理解
參考答案:
}Hero.prototype.name= "Caesar";21
每個函數中都有 prototype屬性,該函數被 new操作符用於創建對象。將一個函數的prototype屬性指向某個對象,由此形成了一條鏈,稱之為原型鏈。
可以使用 isPrototypeOf()方法判定一個 prototype對象是否存在於另一個對象的原型鏈中。如果是,返回 true,否則返回 false。
1.45. 簡要描述JavaScript中的繼承
參考答案:
在 JavaScript中,繼承都是源於原型,有多種實現方式。比如:
1. 修改構造函數的原型,為該構造函數創建的對象指定統一的父級對象。代碼如下:
B.prototype= new A();
2. 只繼承於原型(盡可能地將可重用的屬性和方法添加到原型中),代碼如下:
B.prototype= A.prototype;
3. 單獨修改一個對象的原型,而不影響其他對象的原型。代碼如下:
var b1 = new B();
Object.setPrototypeOf(b1, new A() ) ;
4. 修改構造函數,這將影響使用該構造函數創建的所有對象。代碼如下:
function B() {
Object.setPrototypeOf(this, new A() ) ; }
1.46. 查看如下 JavaScript代碼:
function Hero() {
this.name= "unknown";
var hero= new Hero(); console.log(hero.name) ;
delete hero.name;
console.log(hero.name) ;
delete Hero.prototype.name; console.log(hero.name) ;
上述代碼運行后,輸出結果是?
參考答案:
上述代碼運行后,首先輸出 unknown;然后輸出 Caesar;最后輸出 undefined。
查找對象屬性時,先查找自有屬性,因此,第一次輸出的是 hero的自有屬性 name的值,該屬性的值從構造函數中繼承而來,即為“unknown“;刪除 hero的自有屬性后,再試圖輸出 name屬性時,則查找其原型鏈中的屬性 name的值並輸出,即為“Caesar”;繼續刪除 hero的原型屬性后,則輸出“undefined”。
1.47. 查看如下 JavaScript代碼:
function A() {
this.name= "a";
this.toString= function () { return this.name}; }
function B() {
this.name= "b";
}
var b1 = new B();
console.log(b1 .toString( ) ) ;
B.prototype= new A();
var b2 = new B();
console.log(b2 .toString( ) ) ;
上述代碼運行后,輸出結果是?
參考答案:
上述代碼運行后,首先輸出[object Object];然后輸出 b。
這是因為,雖然修改了 B的原型,但是,只影響修改之后的對象。因此,對象 b1依然使用默認的從 Object繼承而來的 toString()方法,因此輸出對象的類型和名稱。
對象 b2是在修改了 B的原型之后創建的,因此將使用A中所定義的 toString()方法,將輸出字符“b”。
1.48. 簡要描述Call和 apply的區別
參考答案:
ca l l()和 a pply()都用於間接調用函數。
call方法用於調用一個對象的一個方法,並以另一個對象替換當前對象。即,任何函數可以作為任何對象的方法來調用,哪怕這個函數並非那個對象的方法。語法如:
call( [thisObj[,arg1[, arg2[, [, .argN] ] ] ] ] )
其中,第一個參數 thisObj要調用函數的上下文,即將被用作當前對象的對象。其他參
數為可選參數,表示將被傳遞方法參數序列。
apply()和 ca ll()在作用上是相同的,但兩者在參數上有區別的。它倆的第一個參數相同,
不同的是第二個參數。對於 apply(),第二個參數是一個參數數組,也就是將多個參數組合成為一個數組傳入。如:
func.call(func1,var1,var2,var3)
func.apply(func1, [var1,var2,var3] )
1.49. 查看如下 JavaScript代碼:
function A() {
this.name= "a";
this.introduce= function() { console.log("Myname is" + this.name) }; }
function B() {
this.name= "b";
}
var a1 = new A();
var b1 = new B();
a1 .introduce.call(b1 ) ;
上述代碼運行后,輸出結果是?
參考答案:
上述代碼運行后,輸出 My name is b。
代碼 a1.introduce.call(b1);表示對於對象 b1調用 a1的 introduce()方法。
1.50. 查看如下 JavaScript代碼:
var a= b= { n: 1 }; a.x= a= { n: 2 };
alert(a.x) ;
alert(b.x.n);
上述代碼運行后,輸出結果是?
參考答案:
上述代碼運行后,先彈出顯示 undefined,再彈出顯示2。
第一行代碼運行后,變量 a和 b都指向對象{n:1},第二行代碼運行,先為對象{n:1} 添加新屬性 x,其值為{n:2}。此時,對象{n:1}形如{ n:1,x:{n:2}}。然后創建新對象{n:2},並將變量 a指向這個新對象,而變量 b依然指向原有對象。
因此, a.x將輸出 undefined,因為此時新對象中只有屬性 n沒有屬性x; b.x.n將表
示向原有對象的中的新屬性,因此輸出2。
2. DOM
2.1.談談innerHTML、 nodeValue與 textContent之間的區別
參考答案:
innerHTM L屬性讀取或設置節點起始和結束標簽中的 HTM L內容;
nodeValue屬性讀取或設置指定節點的文本內容,適用於文本類型的節點;
textContent屬性讀取或設置指定節點的文本內容,對於元素節點而言,會返回所包含的所有子節點中的文本內容的組合。
2.2. DOM操作中,如何獲取元素的屬性值?
參考答案:
對於元素節點,獲取其某屬性的值有多種方式,如下所示:1、 element.attributes[下標].value
2、 element.attributes['屬性名'].value
3、 element.getAttributeNode('屬性名').value
4、 element.getAttribute('屬性名')
2.3.簡要描述 DOM操作中查找元素的方式
參考答案:
1、 通過 HTML中的信息選取元素,比如:
a) getElementById()方法:根據元素的 id屬性值查詢單個節點;
b) getElementsByTagName()方法:根據元素標簽的名稱查詢節點;
c) getElementsByName()方法:根據元素 name屬性的值查詢節點。
2、 通過 CSS類選取元素
a) getElementsByClassName('className')方法:根據class名稱選取元素;
b) querySelector('selector')和 querySelectorAll('selector')方法:根據 CSS選擇器
選取元素。
3、 通過 document對象選取,如 document.all、 document.body等;
4、 通過節點遍歷選取節點,如 parentNode、 firstChild等。
2.4.為 html頁面上的一個按鈕添加 onclick事件處理,有幾種方法?
參考答案:
1、 直接在 HTML代碼中添加,如:
<input type=”button” onclick=”funcA();”/>
其中, funcA()為一個有效函數。
2、 在 js代碼中添加,如:
btn.onclick= funcA;
或者
btn.onclick= function() {};
其中, btn表示按鈕對象。
3、 定義監聽函數,代碼如:
btn.addEventListener( 'click' , function( ) { }) ;
2.5.簡述window對象除 document以外的一些常用子對象,並描述其作用?
參考答案:
window對象有很多子對象,除了 document以外,還有如下常用子對象:
screen對象:此對象包含有關客戶端顯示屏幕的信息,常用於獲取屏幕的分
辨率和色彩;
history對象:此對象包含用戶(在瀏覽器窗口中)訪問過的 URL;
location對象:此對象包含有關當前 URL的信息,常用於獲取和改變當前
瀏覽的網址;
navigator對象:此對象包含有關瀏覽器的信息,常用於獲取客戶端瀏覽器和
操作系統信息;
event對象:任何事件觸發后將會產生一個 event對象,該對象記錄事件發
生時的鼠標位置、鍵盤按鍵狀態和觸發對象等信息。
2.6.查看如下代碼:
<html>
<head>
<title>bubble</title>
<script type="text/javascript" language="javascript">
function clickP(e) {
var target= e.target || e.srcElement;
alert("clickP, target=" + target.nodeName);
}
function clickDIV(e) {
var target= e.target || e.srcElement;
alert("clickDIV, target=" + target.nodeName);
}
</script>
</head>
<body>
<div onclick="clickDIV(event) ;">
<p onclick="clickP(event) ;">ClickMe</p>
</div>
</body>
</html>
該代碼在瀏覽器中運行時,點擊段落中的文本“ClickMe“,頁面效果為?
參考答案:
先彈出“clickP,target=P”,再彈出“clickDIV,target=P”。
單擊段落中的文本“ClickMe”,先觸發<P>元素的 onclick事件,且觸發事件的元素為段落 P,因此,先彈出“clickP,target=P”;然后事件冒泡,觸發<div>元素的onclick 事件,再彈出“clickDIV,target=P”。
2.7.實現每隔一秒鍾彈出一個對話框,且此彈出過程持續5秒鍾
參考答案:
代碼如下所示:
var id= setInterval(function() {alert("Hello JavaScript");},1000) setTimeout( function( ) {clearInterval(id) ; } , 5*1000)
2.8.為頁面動態添加按鈕
使用 js代碼為頁面動態添加5個按鈕,每個按鈕上的文本為“button1”、“button2”…“button5”。單擊每個按鈕時,分別彈出數字1、2…5。代碼如下:
for (var i= 1; i< 6; i++) {
var input = document.createElement( 'input' ) ;
(空白處)
document.body. appendChild(input) ;
為空白處填上代碼,實現所需功能
}}else{ //ieevent.returnValue= false;}}27
參考答案:
代碼如下所示:
for (var i= 1; i< 6; i++) {
var input = document.createElement( 'input' ) ;
input.setAttribute("type", "button") ;
input.setAttribute("value", "button" + i);
(function (n) {
input.onclick= function () { alert(n); }; })(i);
document.body. appendChild(input) ;
2.9.文本框驗證(考慮瀏覽器兼容性)
頁面有文本框,需要限制該文本框中只能錄入數字,即:如果用戶按下數字以外的其他鍵,文本框中無法錄入;如果用戶粘貼進非數字字符,也需要進行過濾。
請設計 HTML代碼以及 JS代碼,實現上述功能。
參考答案:
首先,需要為文本框定義 onkeypress事件,用於在錄入文本時做出判斷;並為文本框定義 onkyeup事件,用於過濾粘貼進來的文本。 HTML代碼如下所示:
<h2 >輸入框中只能輸入數字</ h2 >
請輸入您的年齡:
<input onkeypress="digitOnly(event) " onkeyup="filterChar(this) "/>
JS代碼如下所示:
//當按鍵按下時,阻止非數字字符的輸入
function digitOnly(event) {
var code= event.keyCode | | event.which; //ie| |firefox if( (code<48) | | (code>57) ) {
if(event.preventDefault) { //firefox
event.preventDefault( ) ;
}
/ /當按鍵彈起時 , 剔除輸入中的非中文字符——解決復制粘貼進來的非數字function filterChar(input){
input.value= input.value.replace(/ [^0-9] /g, ' ' ) ;
}
2.10. 總結可以實現頁面跳轉和刷新的方法
參考答案:
1、 使用超級鏈接,代碼如:
<a href=”url”></a>
2、 表單提交,代碼如:
<form action=”url”></form>
3、 JS代碼,代碼如:
location. href=”url”;
location.assign(‘url’) ; location.replace( ) ;
location.reload( ) ;
window.open(‘url’) ;
history.go( ) ;