互聯網公司前端面試題

1.JavaScript是一門什麼樣的語言,它有哪些特色?javascript

沒有標準答案。html

 

2.JavaScript的數據類型都有什麼?java

基本數據類型:String,Boolean,Number,Undefined, Nulljquery

引用數據類型:Object(Array,Date,RegExp,Function)web

那麼問題來了,如何判斷某變量是否爲數組數據類型?ajax

  • 方法一.判斷其是否具備「數組性質」,如slice()方法。可本身給該變量定義slice方法,故有時會失效
  • 方法二.obj instanceof Array 在某些IE版本中不正確
  • 方法三.方法一二皆有漏洞,在ECMA Script5中定義了新方法Array.isArray(), 保證其兼容性,最好的方法以下:
1
2
3
4
5
6
7
<span style= "font-family: verdana, geneva;" > if ( typeof  Array.isArray=== "undefined" )
{
   Array.isArray =  function (arg){
         return  Object.prototype.toString.call(arg)=== "[object Array]"
     }; 
}
</span>

  

3.已知ID的Input輸入框,但願獲取這個輸入框的輸入值,怎麼作?(不使用第三方框架)正則表達式

1
2
<span style= "font-family: verdana, geneva;" >document.getElementById(「ID」).value
</span>

  

4.但願獲取到頁面中全部的checkbox怎麼作?(不使用第三方框架)算法

1
2
3
4
5
6
7
8
9
<span style= "font-family: verdana, geneva;" > var  domList = document.getElementsByTagName(‘input’)
var  checkBoxList = [];
var  len = domList.length;   //緩存到局部變量
while  (len--) {   //使用while的效率會比for循環更高
   if  (domList[len].type == ‘checkbox’) {
       checkBoxList.push(domList[len]);
  }
}
</span>

  

5.設置一個已知ID的DIV的html內容爲xxxx,字體顏色設置爲黑色(不使用第三方框架)json

1
2
3
4
<span style= "font-family: verdana, geneva;" > var  dom = document.getElementById(「ID」);
dom.innerHTML = 「xxxx」;
dom.style.color = 「 #000」;
</span>

  

6.當一個DOM節點被點擊時候,咱們但願可以執行一個函數,應該怎麼作?跨域

  •  直接在DOM裏綁定事件:<div onclick=」test()」></div>
  •  在JS裏經過onclick綁定:xxx.onclick = test 
  •  經過事件添加進行綁定:addEventListener(xxx, ‘click’, test) 

那麼問題來了,Javascript的事件流模型都有什麼?

  • 「事件冒泡」:事件開始由最具體的元素接受,而後逐級向上傳播
  • 「事件捕捉」:事件由最不具體的節點先接收,而後逐級向下,一直到最具體的
  • 「DOM事件流」:三個階段:事件捕捉,目標階段,事件冒泡

 

7.什麼是Ajax和JSON,它們的優缺點。

Ajax是異步JavaScript和XML,用於在Web頁面中實現異步數據交互。

優勢:

  • 可使得頁面不重載所有內容的狀況下加載局部內容,下降數據傳輸量
  • 避免用戶不斷刷新或者跳轉頁面,提升用戶體驗

缺點:

  • 對搜索引擎不友好(
  • 要實現ajax下的先後退功能成本較大
  • 可能形成請求數的增長
  • 跨域問題限制

JSON是一種輕量級的數據交換格式,ECMA的一個子集

優勢:輕量級、易於人的閱讀和編寫,便於機器(JavaScript)解析,支持複合數據類型(數組、對象、字符串、數字)

 

8.看下列代碼輸出爲什麼?解釋緣由。

1
2
3
<span style= "font-family: verdana, geneva;" > var  a;
alert( typeof  a);  // undefined
alert(b);  // 報錯</span>

解釋:Undefined是一個只有一個值的數據類型,這個值就是「undefined」,在使用var聲明變量但並未對其賦值進行初始化時,這個變量的值就是undefined。而b因爲未聲明將報錯。注意未申明的變量和聲明瞭未賦值的是不同的。

 

9.看下列代碼,輸出什麼?解釋緣由。

1
2
3
<span style= "font-family: verdana, geneva;" > var  a =  null ;
alert( typeof  a);  //object
</span>

解釋:null是一個只有一個值的數據類型,這個值就是null。表示一個空指針對象,因此用typeof檢測會返回」object」。

 

10.看下列代碼,輸出什麼?解釋緣由。

1
2
3
4
5
6
7
8
9
<span style= "font-family: verdana, geneva;" > var  undefined;
undefined ==  null // true
1 ==  true ;    // true
2 ==  true ;    // false
0 ==  false ;   // true
0 ==  '' ;      // true
NaN == NaN;   // false
[] ==  false // true
[] == ![];    // true</span>
  • undefined與null相等,但不恆等(===)

  • 一個是number一個是string時,會嘗試將string轉換爲number

  • 嘗試將boolean轉換爲number,0或1

  • 嘗試將Object轉換成number或string,取決於另一個對比量的類型

  • 因此,對於0、空字符串的判斷,建議使用 「===」 。「===」會先判斷兩邊的值類型,類型不匹配時爲false。

那麼問題來了,看下面的代碼,輸出什麼,foo的類型爲何?

1
2
3
<span style= "font-family: verdana, geneva;" > var  foo =  "11" +2- "1" ;
console.log(foo);
console.log( typeof  foo);</span>

執行完後foo的值爲111,foo的類型爲Number。

1
2
3
<span style= "font-family: verdana, geneva;" > var  foo =  "11" +2+ "1" ;     //體會加一個字符串'1' 和 減去一個字符串'1'的不一樣
console.log(foo);
console.log( typeof  foo);</span>

執行完後foo的值爲1121(此處是字符串拼接),foo的類型爲String。

 

11.看代碼給答案。

1
2
3
4
5
6
<span style= "font-family: verdana, geneva;" > var  a =  new  Object();
a.value = 1;
b = a;
b.value = 2;
alert(a.value);
</span>

答案:2(考察引用數據類型細節)

 

12.已知數組var stringArray = [「This」, 「is」, 「Baidu」, 「Campus」],Alert出」This is Baidu Campus」。

答案:alert(stringArray.join(" "))

 

那麼問題來了,已知有字符串foo="get-element-by-id",寫一個function將其轉化成駝峯表示法"getElementById"。

1
2
3
4
5
6
7
8
9
<span style= "font-family: verdana, geneva;" > function  combo(msg){
     var  arr = msg.split( "-" );
     var  len = arr.length;     //將arr.length存儲在一個局部變量能夠提升for循環效率
     for ( var  i=1;i<len;i++){
         arr[i]=arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);
     }
     msg=arr.join( "" );
     return  msg;
}</span>

(考察基礎API)

 

13.var numberArray = [3,6,2,4,1,5]; (考察基礎API)

  1) 實現對該數組的倒排,輸出[5,1,4,2,6,3]

  2) 實現對該數組的降序排列,輸出[6,5,4,3,2,1]

1
2
3
4
5
6
<span style= "font-family: verdana, geneva;" > var  numberArray = [3,6,2,4,1,5];
numberArray.reverse();  // 5,1,4,2,6,3
numberArray.sort( function (a,b){   //6,5,4,3,2,1
    return  b-a;
})
</span>

 

14.輸出今天的日期,以YYYY-MM-DD的方式,好比今天是2014年9月26日,則輸出2014-09-26

1
2
3
4
5
6
7
8
9
10
11
12
<span style= "font-family: verdana, geneva;" > var  d =  new  Date();
// 獲取年,getFullYear()返回4位的數字
var  year = d.getFullYear();
// 獲取月,月份比較特殊,0是1月,11是12月
var  month = d.getMonth() + 1;
// 變成兩位
month = month < 10 ?  '0'  + month : month;
// 獲取日
var  day = d.getDate();
day = day < 10 ?  '0'  + day : day;
alert(year +  '-'  + month +  '-'  + day);
</span>

  

15.將字符串」<tr><td>{id}</td><td>{id}</td><td>{name}</td></tr>」中的{id}替換成10,{id}替換成10,{name}替換成Tony (使用正則表達式)

答案:"<tr><td>{id}</td><td>{id}</td><td>{id}_{$name}</td></tr>".replace(/{\$id}/g, '10').replace(/{\$name}/g, ‘Tony’);

    

16.爲了保證頁面輸出安全,咱們常常須要對一些特殊的字符進行轉義,請寫一個函數escapeHtml,將<, >, &, 「進行轉義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<span style= "font-family: verdana, geneva;" > function  escapeHtml(str) {
return  str.replace(/[<>」&]/g,  function (match) {
     switch  (match) {
                    case  「<」:
                       return  「<」;
                    case  「>」:
                       return  「>」;
                    case  「&」:
                       return  「&」;
                    case  「\」」:
                       return  「"」;
       }
   });
}
</span>

  

17.foo = foo||bar ,這行代碼是什麼意思?爲何要這樣寫?

答案:if(!foo) foo = bar; //若是foo存在,值不變,不然把bar的值賦給foo。

短路表達式:做爲"&&"和"||"操做符的操做數表達式,這些表達式在進行求值時,只要最終的結果已經能夠肯定是真或假,求值過程便了結止,這稱之爲短路求值。

 

18.看下列代碼,將會輸出什麼?(變量聲明提高)

1
2
3
4
5
6
<span style= "font-family: verdana, geneva;" > var  foo = 1;
function (){
     console.log(foo);
     var  foo = 2;
     console.log(foo);
} </span>

答案:輸出undefined 和 2。上面代碼至關於:

1
2
3
4
5
6
7
<span style= "font-family: verdana, geneva;" > var  foo = 1;
function (){
     var  foo;
     console.log(foo);  //undefined
     foo = 2;
     console.log(foo);  // 2;  
} </span>

函數聲明與變量聲明會被JavaScript引擎隱式地提高到當前做用域的頂部,可是隻提高名稱不會提高賦值部分。

 

19.用js實現隨機選取10--100之間的10個數字,存入一個數組,並排序。

1
2
3
4
5
6
7
8
9
<span style= "font-family: verdana, geneva;" > var  iArray = [];
funtion getRandom(istart, iend){
         var  iChoice = istart - iend +1;
         return  Math.floor(Math.random() * iChoice + istart;
}
for ( var  i=0; i<10; i++){
         iArray.push(getRandom(10,100));
}
iArray.sort();</span>

 

20.把兩個數組合並,並刪除第二個元素。

1
2
3
4
5
<span style= "font-family: verdana, geneva;" > var  array1 = [ 'a' , 'b' , 'c' ];
var  bArray = [ 'd' , 'e' , 'f' ];
var  cArray = array1.concat(bArray);
cArray.splice(1,1);
</span>

  

21.怎樣添加、移除、移動、複製、建立和查找節點(原生JS,實在基礎,沒細寫每一步)

1)建立新節點

  • createDocumentFragment() //建立一個DOM片斷
  • createElement() //建立一個具體的元素
  • createTextNode() //建立一個文本節點


2)添加、移除、替換、插入

  • appendChild() //添加
  • removeChild() //移除
  • replaceChild() //替換
  • insertBefore() //插入


3)查找

  • getElementsByTagName() //經過標籤名稱
  • getElementsByName() //經過元素的Name屬性的值
  • getElementById() //經過元素Id,惟一性

  

22.有這樣一個URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,請寫一段JS程序提取URL中的各個GET參數(參數名和參數個數不肯定),將其按key-value形式返回到一個json結構中,如{a:'1', b:'2', c:'', d:'xxx', e:undefined}。

答案:

1
2
3
4
5
6
7
8
9
function  serilizeUrl(url) {
     var  result = {};
     url = url.split( "?" )[1];
     var  map = url.split( "&" );
     for ( var  i = 0, len = map.length; i < len; i++) {
         result[map[i].split( "=" )[0]] = map[i].split( "=" )[1];
     }
     return  result;
}

  

23.正則表達式構造函數var reg=new RegExp("xxx")與正則表達字面量var reg=//有什麼不一樣?匹配郵箱的正則表達式?

答案:當使用RegExp()構造函數的時候,不只須要轉義引號(即\"表示"),而且還須要雙反斜槓(即\\表示一個\)。使用正則表達字面量的效率更高。 

郵箱的正則匹配:

1
var  regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;

  

24.看下面代碼,給出輸出結果。

1
2
3
4
5
for ( var  i=1;i<=3;i++){
   setTimeout( function (){
       console.log(i);   
   },0); 
};

答案:4 4 4。

緣由:Javascript事件處理器在線程空閒以前不會運行。那麼問題來了,如何讓上述代碼輸出1 2 3?

1
2
3
4
5
6
7
8
9
for ( var  i=1;i<=3;i++){
    setTimeout(( function (a){   //改爲當即執行函數
        console.log(a);   
    })(i),0); 
};
 
1            //輸出
2
3

 

25.寫一個function,清除字符串先後的空格。(兼容全部瀏覽器)

使用自帶接口trim(),考慮兼容性:

1
2
3
4
5
6
7
8
9
if  (!String.prototype.trim) {
  String.prototype.trim =  function () {
  return  this .replace(/^\s+/,  "" ).replace(/\s+$/, "" );
  }
}
 
// test the function
var  str =  " \t\n test string " .trim();
alert(str ==  "test string" );  // alerts "true"

 

26.Javascript中callee和caller的做用?

答案:

caller是返回一個對函數的引用,該函數調用了當前函數;

callee是返回正在被執行的function函數,也就是所指定的function對象的正文。

那麼問題來了?若是一對兔子每個月生一對兔子;一對新生兔,從第二個月起就開始生兔子;假定每對兔子都是一雌一雄,試問一對兔子,第n個月能繁殖成多少對兔子?(使用callee完成)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var  result=[];
function  fn(n){   //典型的斐波那契數列
    if (n==1){
         return  1;
    } else  if (n==2){
            return  1;
    } else {
         if (result[n]){
                 return  result[n];
         } else {
                 //argument.callee()表示fn()
                 result[n]=arguments.callee(n-1)+arguments.callee(n-2);
                 return  result[n];
         }
    }
}

 

   中級Javascript:

1.實現一個函數clone,能夠對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值複製

  • 考察點1:對於基本數據類型和引用數據類型在內存中存放的是值仍是指針這一區別是否清楚
  • 考察點2:是否知道如何判斷一個變量是什麼類型的
  • 考察點3:遞歸算法的設計
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 方法一:
Object.prototype.clone =  function () {
     var  o =  this .constructor === Array ? [] : {};
     for  ( var  in  this ) {
         o[e] =  typeof  this [e] ===  "object"  this [e].clone() :  this [e];
     }
     return  o;
}
 
//方法二:
/**
  * 克隆一個對象
  * @param Obj
  * @returns
  */
function  clone(Obj) {
     var  buf;
     if  (Obj  instanceof  Array) {
         buf = [];  //建立一個空的數組
         var  i = Obj.length;
         while  (i--) {
             buf[i] = clone(Obj[i]);
         }
         return  buf;
     else  if  (Obj  instanceof  Object) {
         buf = {};  //建立一個空對象
         for  ( var  in  Obj) {  //爲這個對象添加新的屬性
             buf[k] = clone(Obj[k]);
         }
         return  buf;
     else  //普通變量直接賦值
         return  Obj;
     }
}

 

2.如何消除一個數組裏面重復的元素?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var  arr = [1, 2, 3, 3, 4, 4, 5, 5, 6, 1, 9, 3, 25, 4];
 
function  deRepeat() {
     var  newArr = [];
     var  obj = {};
     var  index = 0;
     var  l = arr.length;
     for  ( var  i = 0; i < l; i++) {
         if  (obj[arr[i]] == undefined) {
             obj[arr[i]] = 1;
             newArr[index++] = arr[i];
         else  if  (obj[arr[i]] == 1)
             continue ;
     }
     return  newArr;
 
}
var  newArr2 = deRepeat(arr);
alert(newArr2);  //輸出1,2,3,4,5,6,9,25

 

3.小賢是一條可愛的小狗(Dog),它的叫聲很好聽(wow),每次看到主人的時候就會乖乖叫一聲(yelp)。從這段描述能夠獲得如下對象:

1
2
3
4
5
6
7
8
function  Dog() {
        this .wow =  function () {
                alert(’Wow’);
       }
        this .yelp =  function () {
               this .wow();
       }
}

小芒和小賢同樣,原來也是一條可愛的小狗,但是忽然有一天瘋了(MadDog),一看到人就會每隔半秒叫一聲(wow)地不停叫喚(yelp)。請根據描述,按示例的形式用代碼來實。(繼承,原型,setInterval)

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function  MadDog() {
     this .yelp =  function () {
           var  self =  this ;         
           setInterval( function () {
                 self.wow();     
           }, 500);
       }
}
MadDog.prototype =  new  Dog();        
 
//for test
var  dog =  new  Dog();
dog.yelp();
var  madDog =  new  MadDog();
madDog.yelp();

 

4.下面這個ul,如何點擊每一列的時候alert其index?(閉包)

1
2
3
4
5
< ul  id=」test」>
     < li >這是第一條</ li >
     < li >這是第二條</ li >
     < li >這是第三條</ li >
</ ul >

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 方法一:
var  lis=document.getElementById( '2223' ).getElementsByTagName( 'li' );
for ( var  i=0;i<3;i++)
{
     lis[i].index=i;
     lis[i].onclick= function (){
         alert( this .index);
     };
}
 
//方法二:
var  lis=document.getElementById( '2223' ).getElementsByTagName( 'li' );
for ( var  i=0;i<3;i++)
{
     lis[i].index=i;
     lis[i].onclick=( function (a){
         return  function () {
             alert(a);
         }
     })(i);
}

 

5.編寫一個JavaScript函數,輸入指定類型的選擇器(僅需支持id,class,tagName三種簡單CSS選擇器,無需兼容組合選擇器)能夠返回匹配的DOM節點,需考慮瀏覽器兼容性和性能。

答案:(過長,點擊打開)

  View Code

 

6.請評價如下代碼並給出改進意見。

1
2
3
4
5
6
7
8
9
10
11
12
if (window.addEventListener){
     var  addListener =  function (el,type,listener,useCapture){
         el.addEventListener(type,listener,useCapture);
   };
}
else  if (document.all){
     addListener =  function (el,type,listener){
         el.attachEvent( "on" +type, function (){
           listener.apply(el);
       });
   
}

評價:

  • 不該該在if和else語句中聲明addListener函數,應該先聲明;
  • 不須要使用window.addEventListener或document.all來進行檢測瀏覽器,應該使用能力檢測;
  • 因爲attachEvent在IE中有this指向問題,因此調用它時須要處理一下

改進以下: 

1
2
3
4
5
6
7
8
9
10
11
12
13
function  addEvent(elem, type, handler) {  
     if  (elem.addEventListener) {    
         elem.addEventListener(type, handler,  false );  
     else  if  (elem.attachEvent) {    
         elem[ 'temp'  + type + handler] = handler;    
         elem[type + handler] =  function () {    
             elem[ 'temp'  + type + handler].apply(elem);  
         };  
         elem.attachEvent( 'on'  + type, elem[type + handler]); 
     else  {  
         elem[ 'on'  + type] = handler;  
     }
}

 

7.給String對象添加一個方法,傳入一個string類型的參數,而後將string的每一個字符間價格空格返回,例如:

addSpace("hello world") // -> 'h e l l o  w o r l d'

1
2
3
String.prototype.spacify =  function () {
     return  this .split( '' ).join( ' ' );
};

接着上述答題,那麼問題來了

1)直接在對象的原型上添加方法是否安全?尤爲是在Object對象上。(這個我沒能答出?但願知道的說一下。) 

2)函數聲明與函數表達式的區別? 

答案:在Javscript中,解析器在向執行環境中加載數據時,對函數聲明和函數表達式並不是是一視同仁的,解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用(能夠訪問),至於函數表達式,則必須等到解析器執行到它所在的代碼行,纔會真正被解析執行。(函數聲明提高)

 

8.定義一個log方法,讓它能夠代理console.log的方法。

可行的方法一:

1
2
3
4
function  log(msg)  {
     console.log(msg);
}
log( "hello world!" // hello world!

若是要傳入多個參數呢?顯然上面的方法不能知足要求,因此更好的方法是:

1
2
3
function  log() {
     console.log.apply(console, arguments);
};

那麼問題來了,apply和call方法的異同?  

答案:

對於apply和call二者在做用上是相同的,便是調用一個對象的一個方法,以另外一個對象替換當前對象。將一個函數的對象上下文從初始的上下文改變爲由 thisObj 指定的新對象。

但二者在參數上有區別的。對於第一個參數意義都同樣,但對第二個參數: apply傳入的是一個參數數組,也就是將多個參數組合成爲一個數組傳入,而call則做爲call的參數傳入(從第二個參數開始)。 如 func.call(func1,var1,var2,var3)對應的apply寫法爲:func.apply(func1,[var1,var2,var3]) 。

 

9.在Javascript中什麼是僞數組?如何將僞數組轉化爲標準數組?

答案:

僞數組(類數組):沒法直接調用數組方法或指望length屬性有什麼特殊的行爲,但仍能夠對真正數組遍歷方法來遍歷它們。典型的是函數的argument參數,還有像調用getElementsByTagName,document.childNodes之類的,它們都返回NodeList對象都屬於僞數組。可使用Array.prototype.slice.call(fakeArray)將數組轉化爲真正的Array對象。

假設接第八題題幹,咱們要給每一個log方法添加一個"(app)"前綴,好比'hello world!' ->'(app)hello world!'。方法以下:

1
2
3
4
5
6
function  log() {
     var  args = Array.prototype.slice.call(arguments);  //爲了使用unshift數組方法,將argument轉化爲真正的數組
     args.unshift( '(app)' );
 
     console.log.apply(console, args);
};

 

10.對做用域上下文和this的理解,看下列代碼:

1
2
3
4
5
6
7
8
9
10
var  User = {
     count: 1,
 
     getCount:  function () {
         return  this .count;
     }
};
console.log(User.getCount());  // what?
var  func = User.getCount;
console.log(func());  // what?

問兩處 console 輸出什麼?爲何?

答案是 1 和 undefined。

func 是在 winodw 的上下文中被執行的,因此會訪問不到 count 屬性。

那麼問題來了,如何確保Uesr老是能訪問到func的上下文,即正確返回1

答案:正確的方法是使用Function.prototype.bind。兼容各個瀏覽器完整代碼以下:

1
2
3
4
5
6
7
8
9
10
Function.prototype.bind = Function.prototype.bind ||  function (context) {
     var  self =  this ;
 
     return  function () {
         return  self.apply(context, arguments);
     };
}
 
var  func = User.getCount.bind(User);
console.log(func());

  

11.原生JS的window.onload與Jquery的$(document).ready(function(){})有什麼不一樣?如何用原生JS實現Jq的ready方法?

window.onload()方法是必須等到頁面內包括圖片的全部元素加載完畢後才能執行。

$(document).ready()是DOM結構繪製完畢後就執行,沒必要等到加載完畢。   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
  * 傳遞函數給whenReady()
  * 當文檔解析完畢且爲操做準備就緒時,函數做爲document的方法調用
  */
var  whenReady = ( function () {  //這個函數返回whenReady()函數
     var  funcs = [];  //當得到事件時,要運行的函數
     var  ready =  false //當觸發事件處理程序時,切換爲true
 
     //當文檔就緒時,調用事件處理程序
     function  handler(e) {
         if  (ready)  return //確保事件處理程序只完整運行一次
 
         //若是發生onreadystatechange事件,但其狀態不是complete的話,那麼文檔還沒有準備好
         if  (e.type ===  'onreadystatechange'  && document.readyState !==  'complete' ) {
             return ;
         }
 
         //運行全部註冊函數
         //注意每次都要計算funcs.length
         //以防這些函數的調用可能會致使註冊更多的函數
         for  ( var  i = 0; i < funcs.length; i++) {
             funcs[i].call(document);
         }
         //事件處理函數完整執行,切換ready狀態, 並移除全部函數
         ready =  true ;
         funcs =  null ;
     }
     //爲接收到的任何事件註冊處理程序
     if  (document.addEventListener) {
         document.addEventListener( 'DOMContentLoaded' , handler,  false );
         document.addEventListener( 'readystatechange' , handler,  false );  //IE9+
         window.addEventListener( 'load' , handler,  false );
     else  if  (document.attachEvent) {
         document.attachEvent( 'onreadystatechange' , handler);
         window.attachEvent( 'onload' , handler);
     }
     //返回whenReady()函數
     return  function  whenReady(fn) {
         if  (ready) {
             fn.call(document);
         else  {
             funcs.push(fn);
         }
     }
})();

若是上述代碼十分難懂,下面這個簡化版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function  ready(fn){
     if (document.addEventListener) {         //標準瀏覽器
         document.addEventListener( 'DOMContentLoaded' function () {
             //註銷事件, 避免反覆觸發
             document.removeEventListener( 'DOMContentLoaded' ,arguments.callee,  false );
             fn();             //執行函數
         },  false );
     } else  if (document.attachEvent) {         //IE
         document.attachEvent( 'onreadystatechange' function () {
             if (document.readyState ==  'complete' ) {
                 document.detachEvent( 'onreadystatechange' , arguments.callee);
                 fn();         //函數執行
             }
         });
     }
};

 

12.(設計題)想實現一個對頁面某個節點的拖曳?如何作?(使用原生JS)

回答出概念便可,下面是幾個要點

  • 給須要拖拽的節點綁定mousedown, mousemove, mouseup事件
  • mousedown事件觸發後,開始拖拽
  • mousemove時,須要經過event.clientX和clientY獲取拖拽位置,並實時更新位置
  • mouseup時,拖拽結束
  • 須要注意瀏覽器邊界的狀況

 

13.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function  setcookie(name, value, days) {  //給cookie增長一個時間變量
       
     var  exp =  new  Date();  
     exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000);  //設置過時時間爲days天
       
     document.cookie = name +  "="  + escape(value) +  ";expires="  + exp.toGMTString();
}
 
function  getCookie(name) {  
     var  result =  "" ;  
     var  myCookie =  ""  + document.cookie +  ";" ;  
     var  searchName =  "+name+"  ";  
     var startOfCookie = myCookie.indexOf(searchName);  
     var endOfCookie;  
     if (satrtOfCookie != -1) {    
         startOfcookie += searchName.length;    
         endOfCookie = myCookie.indexOf(" ; ", startOfCookie);    
         result = (myCookie.substring(startOfCookie, endOfCookie));  
     }  
     return result;
}
(function() {  
     var oTips = document.getElementById('tips'); //假設tips的id爲tips
       
     var page = {  
         check: function() { //檢查tips的cookie是否存在而且容許顯示
                 
             var tips = getCookie('tips');    
             if (!tips || tips == 'show') return true; //tips的cookie不存在
                 
             if (tips == " never_show_again ") return false;  
         },
           hideTip: function(bNever) {    
             if (bNever) setcookie('tips', 'never_show_again', 365);    
             oTips.style.display = " none "; //隱藏
               
         },
           showTip: function() {  
             oTips.style.display = " inline";  //顯示,假設tips爲行級元素
               
         },
           init:  function () {    
             var  _this =  this ;    
             if  ( this .check()) {    
                 _this.showTip();    
                 setcookie( 'tips' 'show' , 1);  
             }  
             oTips.onclick =  function () {    
                 _this.hideTip( true );  
             };  
         }  
     };
     page.init();
})();

 

14.說出如下函數的做用是?空白區域應該填寫什麼?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//define
( function (window) {
     function  fn(str) {
         this .str = str;
     }
 
     fn.prototype.format =  function () {
         var  arg = ______;
         return  this .str.replace(_____,  function (a, b) {
             return  arg[b] ||  "" ;
         });
     }
     window.fn = fn;
})(window);
 
//use
( function () {
     var  t =  new  fn( '<p><a href="{0}">{1}</a><span>{2}</span></p>' );
     console.log(t.format( 'http://www.alibaba.com' 'Alibaba' 'Welcome' ));
})();

答案:訪函數的做用是使用format函數將函數的參數替換掉{0}這樣的內容,返回一個格式化後的結果:

第一個空是:arguments
第二個空是:/\{(\d+)\}/ig

 

15.用面向對象的Javascript來介紹一下本身。

答案: 對象或者Json都是不錯的選擇哦。

 

16.講解原生Js實現ajax的原理。

Ajax 的全稱是Asynchronous JavaScript and XML,其中,Asynchronous 是異步的意思,它有別於傳統web開發中採用的同步的方式。

Ajax的原理簡單來講經過XmlHttpRequest對象來向服務器發異步請求,從服務器得到數據,而後用javascript來操做DOM而更新頁面。

XMLHttpRequest是ajax的核心機制,它是在IE5中首先引入的,是一種支持異步請求的技術。簡單的說,也就是javascript能夠及時向服務器提出請求和處理響應,而不阻塞用戶。達到無刷新的效果。

XMLHttpRequest這個對象的屬性有:

  •  onreadystatechang    每次狀態改變所觸發事件的事件處理程序。
  •  responseText    從服務器進程返回數據的字符串形式。
  •  responseXML    從服務器進程返回的DOM兼容的文檔數據對象。
  •  status    從服務器返回的數字代碼,好比常見的404(未找到)和200(已就緒)
  •  status Text    伴隨狀態碼的字符串信息
  •  readyState    對象狀態值
    •  0 (未初始化) 對象已創建,可是還沒有初始化(還沒有調用open方法)
    •  1 (初始化) 對象已創建,還沒有調用send方法

    •  2 (發送數據) send方法已調用,可是當前的狀態及http頭未知

    •  3 (數據傳送中) 已接收部分數據,由於響應及http頭不全,這時經過responseBody和responseText獲取部分數據會出現錯誤,

    •  4 (完成) 數據接收完畢,此時能夠經過經過responseXml和responseText獲取完整的迴應數據

  下面簡單封裝一個函數:(略長,點擊打開)  

上述代碼大體表述了ajax的過程,釋義自行google,問題未完,那麼知道什麼是Jsonp和pjax嗎?

答案:

Jsonp:(JSON with Padding)是一種跨域請求方式。主要原理是利用了script 標籤能夠跨域請求的特色,由其 src 屬性發送請求到服務器,服務器返回 js 代碼,網頁端接受響應,而後就直接執行了,這和經過 script 標籤引用外部文件的原理是同樣的。JSONP由兩部分組成:回調函數和數據,回調函數通常是由網頁端控制,做爲參數發往服務器端,服務器端把該函數和數據拼成字符串返回。

pjax:pjax是一種基於ajax+history.pushState的新技術,該技術能夠無刷新改變頁面的內容,而且能夠改變頁面的URL。(關鍵點:能夠實現ajax沒法實現的後退功能)pjax是ajax+pushState的封裝,同時支持本地存儲、動畫等多種功能。目前支持jquery、qwrap、kissy等多種版本。

相關文章
相關標籤/搜索