【編碼題篇】收集整理來自網絡上的一些常見的 經典前端、H5面試題 Web前端開發面試題


 

編寫一個方法 求一個字符串的字節長度
假設:一個英文字符占用一個字節,一個中文字符占用兩個字節

function GetBytes(str){

        var len = str.length;

        var bytes = len;

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

            if (str.charCodeAt(i) > 255) bytes++;

        }

        return bytes;

    }

alert(GetBytes("你好,as"));

 

實現一個函數clone,可以對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值復制

Object.prototype.clone = function(){

			var o = this.constructor === Array ? [] : {};

			for(var e in this){

					o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];

			}

			return o;
	}

 

79.冒泡排序、快速排序、去重、查找字符串最多值

//冒泡排序
var bubbleSort = function(arr) {
   for (var i = 0; i < arr.length-1; i++) {
     for (var j = i+1; j < arr.length; j++) {
       if (arr[i]>arr[j]) {
         var temp = arr[i];
         arr[i] = arr[j];
         arr[j] = temp;
       }
     }
   }
   return arr;
};

//快速排序
var quickSort = function(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  var len = arr.length;
  var midIndex = Math.floor(len/2);
  var mid = arr.splice(midIndex,1);
  var left = [];
  var right = [];
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] < mid) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return quickSort(left).concat(mid,quickSort(right))
}

// 去重
 var distinct = function(arr) {
   var map = {};
   var result = [];
   for (var i = 0; i < arr.length; i++) {
      if (!map[arr[i]]) {
        map[arr[i]] = true;
        result.push(arr[i]);
      }
   }
   return result;
 }

//查找字符串中最多的值
var search = function(str) {
  var json = {};
  var max = 0;
  var char;
  for (var i = 0; i < str.length; i++) {
    if (!json[str[i]]) {
      json[str[i]]=1;
    } else {
      json[str[i]]++;
    }
  }
  console.log(json);
  for(var i in json){
        if(json[i]>max){
                max = json[i];
                char = i;
        }
}
  console.log(max, char);
}

 

80.函數組合繼承

原型繼承、構造函數繼承、call aplly繼承

var Super = function(name){
  this.name = name;
}
Super.prototype.func1 = function() { console.log('func1'); }
var Sub = function(name,age) {
  Super.call(this, name);
  this.age = age;
}
Sub.prototype = new Super();

 

81.事件綁定

var addEvent = function(e, type, handler, capture ) {
  if (e.addEventListener) {
    e.addEventListener(type, handler, capture);
  } else if (e.attachEvent) {
    e.attachEvent('on'+type, handler);
  } else {
    e['on'+type] = handler;
  }
}

 

82.淺克隆和深度克隆

//淺克隆
function extendCopy(p) {
    var c = {};
    for (var i in p) {
      c[i] = p[i];
    }
    c.uber = p;
    return c;
 }

//深度克隆
var clone = function(v) {
  var o = v.constructor === Array ? [] : {};
  for (var i in v) {
    o[i] = typeof v[i] === "Object" ? clone(v[i]) : v[i];
  }
  return o;
}

 83.實現一個秒針繞一點轉動的效果

  animation: move 60s infinite steps(60); 
 /*設置旋轉的中心點為中間底部*/ 
  transform-origin: center bottom; 
/*旋轉從0度到360度*/ 
@keyframes move { 
    from { 
        transform: rotate(0deg); 
    } 
    to { 
        transform: rotate(360deg); 
    } 
} 

 

72.生成10個20-50之間的隨機數,存在數組中,常見排序方法,數組亂序方法

var arr = [];
for(var i = 0;i<10;i++){
    var num = Math.random()*30 + 20;
    num = parseInt(num, 10);
    arr.push(num);
}
arr.sort(function(a,b){
    return 0.5 - Math.random();
})

 

69.實現一個once函數

function test () {console.log('test')}
 
var once = function (fn) {
  var isFirst = true;
  return function () {
    if (isFirst) {
      isFirst = !isFirst;
      fn();
    }
  };
};
 
var b = once(test);
b(); // 'test'
b(); // nothing

 

65.兩個數組合並成一個數組排序返回

先依次比較兩個數組,按照小的就傳入新的數組。當這次比較完之后可能有一個數組的長度很長,留下一些數組,然后在新數組的末尾插入即可。

functiongetRes(arr1, arr2){
   var len1 = arr1.length,
       len2 = arr2.length,
       i = 0,
       j = 0,
       k = 0,
       res = new Array(len1+len2);
  
       while(i < len1 && j <len2){
res[k++] = arr[(arr[i] > arr[j]) ? j++ : i++];
}
While(i < len1)   res[k++]= arr1[i++];
While(j < len2)   res[k++]= arr2[j++];
Return res;
}

 

62.將url的查詢參數解析成字典對象

function getQueryObject(url) {
    url = url == null ? window.location.href : url;
    var search = url.substring(url.lastIndexOf("?") + 1);
    var obj = {};
    var reg = /([^?&=]+)=([^?&=]*)/g;
    search.replace(reg, function (rs, $1, $2) {
        var name = decodeURIComponent($1);
        var val = decodeURIComponent($2);              
        val = String(val);
        obj[name] = val;
        return rs;
    });
    return obj;
}
  
getQueryObject("http://www.cnblogs.com/leee/p/4456840.html?name=1&dd=ddd**")
Object {name: "1", dd: "ddd**"}

 

53:圖片預加載和懶加載

預加載:

function loadImage(url, callback) {
    var img = new Image();
    img.src = url;
    if (img.complete) { // 如果圖片已經存在於瀏覽器緩存,直接調用回調函數 防止IE6不執行onload BUG
        callback.call(img);
        return;
    }
    img.onload = function () {
        callback.call(img);//將回調函數的this替換為Image對象
    };
};

懶加載:

當網頁滾動的事件被觸發 -> 執行加載圖片操作 -> 判斷圖片是否在可視區域內 -> 在,則動態將data-src的值賦予該圖片。

 

var aImages = document.getElementById("SB").getElementsByTagName('img'); //獲取id為SB的文檔內所有的圖片
loadImg(aImages);
window.onscroll = function() { //滾動條滾動觸發
loadImg(aImages);
};
//getBoundingClientRect 是圖片懶加載的核心
function loadImg(arr) {
for(var i = 0, len = arr.length; i < len; i++) {
 if(arr[i].getBoundingClientRect().top < document.documentElement.clientHeight && !arr[i].isLoad) {
 arr[i].isLoad = true; //圖片顯示標志位
 //arr[i].style.cssText = "opacity: 0;";
 (function(i) {
  setTimeout(function() {
  if(arr[i].dataset) { //兼容不支持data的瀏覽器
   aftLoadImg(arr[i], arr[i].dataset.imgurl);
  } else {
   aftLoadImg(arr[i], arr[i].getAttribute("data-imgurl"));
  }
  arr[i].style.cssText = "transition: 1s; opacity: 1;" //相當於fadein
  }, 500)
 })(i);
 }
}
}
 
function aftLoadImg(obj, url) {
var oImg = new Image();
oImg.onload = function() {
 obj.src = oImg.src; //下載完成后將該圖片賦給目標obj目標對象
}
oImg.src = url; //oImg對象先下載該圖像
}

 

46:聖杯布局和雙飛翼布局

【聖杯布局】

html代碼中  middle部分首先要放在container的最前部分。然后是left,right

1.將三者都 float:left , 再加上一個position:relative (因為相對定位后面會用到)

2.middle部分 width:100%占滿

3.此時middle占滿了,所以要把left拉到最左邊,使用margin-left:-100%

4.這時left拉回來了,但會覆蓋middle內容的左端,要把middle內容拉出來,所以在外圍container加上 padding:0 220px 0 200px

5.middle內容拉回來了,但left也跟着過來了,所以要還原,就對left使用相對定位 left:-200px  同理,right也要相對定位還原 right:-220px

6.到這里大概就自適應好了。如果想container高度保持一致可以給left middle right都加上min-height:130px

【雙飛翼布局】

前幾步都一樣 后邊把外圍padding和相對定位做法換成內層margin

給middle增加一個內層div-- middle-inner, 然后margin:0 220px 0 200px

39: 寫一個組合繼承

var Super = function(name){
  this.name = name;
}
Super.prototype.func1 = function() { console.log('func1'); }
var Sub = function(name,age) {
  Super.call(this, name);
  this.age = age;
}
Sub.prototype = new Super();

 

40:深拷貝方案有哪些,手寫一個深拷貝

var clone = function(v) {
  var o = v.constructor === Array ? [] : {};
  for (var i in v) {
    o[i] = typeof v[i] === "Object" ? clone(v[i]) : v[i];
  }
  return o;
}

 

實現兩欄布局有哪些方法

*{margin:0; padding: 0;}
html,body{
        height: 100%;/*高度百分百顯示*/
}
#left{
    width: 300px;
    height: 100%;
    background-color: #ccc;
    float: left;
}
#right{
    height: 100%;
    margin-left: 300px;
    background-color: #eee;

 

*{margin:0; padding: 0;}
html,body{
        height: 100%;/*高度百分百顯示*/
}
#left{
    width: 300px;
    height: 100%;
    background-color: #ccc;
    float: left;
}
#right{
    height: 100%;
    overflow:hidden;
    background-color: #eee;
}

第二種方法,我利用的是創建一個新的BFC(塊級格式化上下文)來防止文字環繞的原理來實現的。BFC就是一個相對獨立的布局環境,它內部元素的布局不受外面布局的影響。它可以通過以下任何一種方式來創建: 

float 的值不為 none 
position 的值不為 static 或者 relative 
display 的值為 table-cell , table-caption , inline-block , flex , 或者 inline-flex 中的其中一個 
overflow 的值不為 visible

第三種flex布局

在一個UI里有10個li,實現點擊對應的li,輸出對應的下標

var lis = querySelectorAll('li')
for(var i=0;i<10;i++){
   lis[i].onclick = (function(a) {
      return function() {
       alert(a)
    }
  })(i)
}   

如何取出一個數組里的圖片並按順序顯示出來?

function loadImage(imgList,callback){
        if(!$.isArray(imgList) || !$.isFunction(callback)) return ;
        var imageData = [] ;
        $.each(imgList, function(i,src){
            var img = new Image() ;
            img.onload = function(){
                $(imageData.shift()).appendTo("body") ;
                if(!imageData.length){
                    callback() ;
                    return ;
                }
                this.onload = null ;
            } ;
            img.src= src ;
            imageData.push(img) ;
        }) ;
    } ;

如何在頁面上實現一個圓形的可點擊區域?三種解決方案。

1. map+area

<img src="t.jpg" width="1366" height="768" border="0" usemap="#Map" />
<map name="Map" id="Map">
 <area shape="circle" coords="821,289,68" href="www.baidu.com" target="_blank" />
</map>

使用Dreamweaver制作熱點會變得非常的容易,最終會形成上面的代碼,具體的操作,可以參考視頻,http://www.chuanke.com/3885380-190205.html。

2. border-radius(H5)

<style>
 .disc{
     width:100px;
     height:100px;
     background-color:dimgray;
     border-radius: 50%;
     cursor: pointer;
     position: absolute;
     left:50px;
     top:50px;    
     line-height: 100px;
     text-align: center;
     color: white;
 }
</style>
<div class="disc">智學無憂</div>

運行效果

 
3. 純js實現
需要求一個點在不在圓上簡單算法、獲取鼠標坐標等等
兩點之間的距離計算公式  

上面公式對於JavaScript代碼如下: 

|AB|=Math.abs(Math.sqrt(Math.pow(X2-X1),2)+Math.pow(Y2-Y1,2)))

Math.abs()求絕對值Math.pow(底數,指數)

Math.sqrt()求平方根

示例:假設圓心為(100,100),半徑為50,在圓內點擊彈出相應的信息,在圓外顯示不在圓內的信息

document.onclick=function(e){
    var r=50;//圓的半徑
var x1=100,y1=100,x2= e.clientX;y2= e.clientY;
//計算鼠標點的位置與圓心的距離
    var len=Math.abs(Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)));
    if(len<=50){
        console.log("內")
    }else{
        console.log("外")
    }
 }

WEB前端 | H5基礎——(4)流式布局、響應式布局、Viewport

一 、流式布局

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>流式布局</title>
        <style type="text/css">
            body {
                margin: 0;
            }
            .reddiv {
                width: 30%;
                /*
                單位
                    vw ViewWidth
                    vh ViewHeight
                */
                height: 30vw;
                background-color: red;
            }
            .big {
                
            }
            .big span {
                font-size: 2em;
            }
        </style>
    </head>
    <body>
        <!-- 流式布局
            百分比布局
            1、寬高設置百分比
            2、寬高設置VW VH
            3、彈性圖片(給寬度,高度會自適應,不失真)
            4、em/rem(都是倍數,em相對於父級,rem相對於html)
        -->
        <!-- <div class="reddiv"></div> -->
        <img src="http://img.taopic.com/uploads/allimg/121009/235045-12100Z31P150.jpg" width="50%" alt="">
        <div class="big">
            <span>我是span標簽</span>
        </div>
    </body>
</html>

 二、響應式布局

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>響應式布局</title>
        <style type="text/css">

            /*
                @media
                媒體查詢、媒體選擇
                screen 屏幕
                and 后面跟條件
            */
            /*
                通過媒體查詢可以設置多套布局,具體使用哪一套,就是根據媒體查詢的條件來定(條件就是and后面的括號and 和括號之間要有空格)
            */
            @media screen and (max-width:150px) {
                .div1 {
                    background-color: gold;
                }
            }
            @media screen and (min-width: 150px) and (max-width:300px) {
                .div1 {
                    background-color: red;
                }
            }
            @media screen and (min-width: 300px) and (max-width:600px) {
                .div1 {
                    background-color: blue;
                }
            }
            @media screen and (min-width: 600px) and (max-width:900px) {
                .div1 {
                    background-color: green;
                }
            }
            @media screen and (min-width: 900px) and (max-width:1200px) {
                .div1 {
                    background-color: pink;
                }
            }
            @media screen and (min-width:1200px) {
                .div1 {
                    background-color: black;
                }
            }
            .div1 {
                width: 400px;
                height: 400px;
            }
        </style>
    </head>
    <body>
        <div class="div1"></div>
    </body>
</html>

 

三、Viewport
<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>viewport</title>
        <!-- 
            viewport 可視區域 
            width 寬度,可以理解為設置我們的網頁一個屏幕能看到的寬度
            maximum-scale 放大的最大值(網頁能放大幾倍)
            minimum-scale 縮小的倍數(網頁最小能縮小多少倍)
            initial-scale=1.0 頁面初始值(一般是1.0)
            user-scalable=0 是否允許用戶縮放(1可以,0不可以)
            (蘋果設備,需要的圖片像素一般是物理像素的2倍,或3倍)
            target-densitydpi  值越高看的越清楚
            device-dpi  設備原本的dpi
            high-dpi    高dpi
            low-dpi        低dpi
            value 指定一個具體數值,取值范圍 70 - 400
         -->
        <meta name="viewport" content="width=device-width,maximum-scale=2.0,minimum-scale=1.0,initial-scale=1.0,user-scalable=1,target-densitydpi=high-dpi">
        <style type="text/css">
            body {
                margin: 0;
            }
            .reddiv {
                width: 210px;
                height: 80px;
                background-color: red;
                border: 1px solid blue;
            }
        </style>
    </head>
    <body>
        <label for="name">姓名</label>
        <input type="text" id="name"/>
        <div class="reddiv"></div>
    </body>
</html>
 
(內容1)——————

5個經典的前端面試問題,你行嗎?

JavaScript開發人員在IT界的需求量一直很大。如果你非常精通神這門語言,你會有很多機會換工作,漲薪水。但是在一家公司錄用你之前,你必須順利通過面試,證明你的技能。在本文中,我將向您展示5個關於前端相關的問題,以測試侯選者的JavaScript技能和他們解決問題的能力。有將會非常有趣!

問題1:Scope作用范圍

考慮下面的代碼:

(function() {
var a = b = 5;
})();
console.log(b);

什么會被打印在控制台上?回答上面的代碼會打印5。這個問題的訣竅是,這里有兩個變量聲明,但a使用關鍵字
var聲明的。代表它是一個函數的局部變量。與此相反,b變成了全局變量。這個問題的另一個訣竅是,它沒有使用嚴格模式 ('use strict';)。如果啟用了嚴格模式,代碼就會引發ReferenceError的錯誤:B沒有定義(b is not defined)。請記住,嚴格模式,則需要明確指定,才能實現全局變量聲明。比如,你應該寫:

(function() {
'use strict';
var a = window.b = 5;
})();
console.log(b);問題2:創建“原生”(native)方法

給字符串對象定義一個repeatify功能。當傳入一個整數n時,它會返回重復n次字符串的結果。例如:

console.log('hello'.repeatify(3));

應打印hellohellohello。回答一個可能的實現如下所示:

String.prototype.repeatify = String.prototype.repeatify ||
function(times) {
var str = '';
for (var i = 0; i < times; i++) {
str += this;
}
return str;
};

現在的問題測試開發者有關JavaScript繼承和prototype的知識點。這也驗證了開發者是否知道該如果擴展內置對象(盡管這不應該做的)。這里的另一個要點是,你要知道如何不覆蓋可能已經定義的功能。通過測試一下該功能定義之前並不存在:

String.prototype.repeatify = String.prototype.repeatify ||
function(times) {
/* code here */
};

當你被要求做好JavaScript函數兼容時這種技術特別有用。

問題3:聲明提升(Hoisting)

執行這段代碼,輸出什么結果。

function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();

回答這段代碼的結果是undefined和2。原因是,變量和函數的聲明都被提前了(移到了函數的頂部),但變量不分配任何值。因此,在打印變量的時候,它在函數中存在(它被聲明了),但它仍然是undefined。表示換句話說,上面的代碼等同於以下內容:

function test() {
var a;
function foo() {
return 2;
}
console.log(a);
console.log(foo());
a = 1;
}
test();

問題4:this在JavaScript中如何工作的

下面的代碼會輸出什么結果?給出你的答案。

var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());

回答答案是Aurelio De Rosa和John Doe。原因是,在一個函數中,this的行為,取決於JavaScript函數的調用方式和定義方式,而不僅僅是看它如何被定義的。在第一個console.log()調用中,getFullname()被調用作為obj.prop對象的函數。所以,上下文指的是后者,函數返回該對象的fullname。與此相反,當getFullname()被分配到test變量時,上下文指的是全局對象(window)。這是因為test是被隱式設置為全局對象的屬性。出於這個原因,該函數返回window的fullname,即定義在第一行的那個值。

問題5:call()和apply()

現在讓你解決前一個問題,使最后的console.log()打印Aurelio De Rosa。回答該問題可以通過強制使用call()或者apply()改變函數上下文。在下面我將使用call(),但在這種情況下,apply()會輸出相同的結果:

console.log(test.call(obj.prop));結論

在這篇文章中,我們已經討論了用來測試JavaScript開發者的五個經典問題。面試的概念和涵蓋的主題通常是非常相似的。如果你不知道的一些問題的答案,不必擔心:學習和經驗可以慢慢積累。如果你有其他一些有趣的問題,不要猶豫,與我們分享。它會幫助很多開發者。

11.b繼承a的方法12.寫一個獲取非行間樣式的函數
function getStyle(obj, attr, value)

{

if (!value)

{

if (obj.currentStyle)

{

return obj.currentStyle(attr);

}

else

{

obj.getComputedStyle(attr, false);

}

}

else

{

obj.style[attr] = value;

}

}

22.編寫一個數組去重的方法
function oSort(arr)   {

var result = {};

var newArr = [];

for (var i = 0; i < arr.length; i++)

{

if (!result[arr[i]])

{

newArr.push(arr[i]);

result[arr[i]] = 1;

}

}

return newArr;

  
}
23.排序算法

“快速排序”的思想很簡單,整個排序過程只需要三步:
  (1)在數據集之中,找一個基准點
  (2)建立兩個數組,分別存儲左邊和右邊的數組
  (3)利用遞歸進行下次比較

function quickSort(arr){
            if(arr.length<=1){
                return arr;//如果數組只有一個數,就直接返回;
            }

            var num = Math.floor(arr.length/2);//找到中間數的索引值,如果是浮點數,則向下取整

            var numValue = arr.splice(num,1);//找到中間數的值
            var left = [];
            var right = [];

            for(var i=0;i<arr.length;i++){
                if(arr[i]<numValue){
                    left.push(arr[i]);//基准點的左邊的數傳到左邊數組
                }
                else{
                   right.push(arr[i]);//基准點的右邊的數傳到右邊數組
                }
            }

            return quickSort(left).concat([numValue],quickSort(right));//遞歸不斷重復比較
        }

        alert(quickSort([32,45,37,16,2,87]));//彈出“2,16,32,37,45,87”

 

/**冒泡排序 */
function bubbleSort() {  
var array = [5, 4, 3, 2, 1];

  
var temp = 0;

  
for (var i = 0; i < array.length; i++)

   {

    
for (var j = 0; j < array.length - i; j++)

     {

      
if (array[j] > array[j + 1])

       {

        temp = array[j + 1];

        array[j + 1] = array[j];

        array[j] = temp;

      
}      
}  

}
}

(內容3)——————

http: //bbs.blueidea.com/thread-3107428-1-1.html以下都是網上整理出來的JS面試題,答案僅供參考。
2,截取字符串abcdefg的efg alert('abcdefg'.substring(4));

3,判斷一個字符串中出現次數最多的字符,統計這個次數
var str = 'asdfssaaasasasasaa';
var json = {};

for (var i = 0; i < str.length; i++) {
if (!json[str.charAt(i)]) {
json[str.charAt(i)] = 1;
} else {
json[str.charAt(i)]++;
}
};
var iMax = 0;
var iIndex = '';
for (var i in json) {
if (json[i] > iMax) {
iMax = json[i];
iIndex = i;
}
}
alert('出現次數最多的是:' + iIndex + '出現' + iMax + '次');

6,javascript面向對象中繼承實現

function Person(name) {
this.name = name;
}

Person.prototype.showName = function() {
alert(this.name);
}

function Worker(name, job) {
Person.apply(this, arguments) this.job = job;
}
for (var i in Person.prototype) {
Worker.prototype = Person.prototype;
}
new Worker('sl', 'coders').showName();

7,FF下面實現outerHTML
var oDiv = document.createElement('div');
var oDiv1 = document.getElementById('div1');
var oWarp = document.getElementById('warp');

oWarp.insertBefore(oDiv, oDiv1);
oDiv.appendChild(oDiv1);
var sOut = oDiv.innerHTML;
oWarp.insertBefore(oDiv1, oDiv);
oWarp.removeChild(oDiv);
alert(sOut);

8,編寫一個方法求一個字符串的字節長度假設一個中文占兩個字節
var str = '22兩是';

alert(getStrlen(str))

function getStrlen(str) {
var json = {
len: 0
};
var re = /[\u4e00-\u9fa5]/;
for (var i = 0; i < str.length; i++) {
if (re.test(str.charAt(i))) {
json['len']++;
}
};
return json['len'] + str.length;
}

11、如何深度克隆
var arr = [1, 2, 43];
var json = {
a: 6,
b: 4,
c: [1, 2, 3]
};
var str = 'sdfsdf';

var json2 = clone(json);

alert(json['c']) function clone(obj) {
var oNew = new obj.constructor(obj.valueOf());
if (obj.constructor == Object) {
for (var i in obj) {
oNew[i] = obj[i];
if (typeof(oNew[i]) == 'object') {
clone(oNew[i]);
}
}
}
return oNew;
}

12,JavaScript中如何檢測一個變量是一個String類型?請寫出函數實現typeof(obj) == 'string'obj.constructor == String;

13,網頁中實現一個計算當年還剩多少時間的倒數計時程序,要求網頁上實時動態顯示“××年還剩××天××時××分××秒”
var oDate = new Date();
var oYear = oDate.getFullYear();

var oNewDate = new Date();
oNewDate.setFullYear(oYear, 11, 31, 23, 59, 59);
var iTime = oNewDate.getTime() - oDate.getTime();

var iS = iTime / 1000;
var iM = oNewDate.getMonth() - oDate.getMonth();
var iDate = iS

 

 

2017.8.31收集

JavaScript-有意思的30題_題目

來源:溫故js系列(13.2)-有意思的30題_解析

之前在學習時把問題和答案分開了,這兒也分開吧。這樣在看得時候無意識的會多思考一下。茶余飯后,來杯咖啡

1.以下表達式的運行結果是:

["1","2","3"].map(parseInt)
A.["1","2","3"]
B.[1,2,3]
C.[0,1,2]
D.其他

D

map對數組的每個元素調用定義的回調函數並返回包含結果的數組。["1","2","3"].map(parseInt)對於數組中每個元素調用paresInt。但是該題目不同於:

function testFuc(a){
    return parseInt(a);
}
console.info(["1","2","3"].map(testFuc));

題目等同於:

function testFuc(a,x){
    return parseInt(a,x);
}
console.info(["1","2","3"].map(testFuc));

map中回調函數的語法如下所示:function callbackfn(value, index, array1),可使用最多三個參數來聲明回調函數。第一參數value,數組元素的值;第二個參數index,數組元素的數組所以;array1,包含該元素的數組對象。
因此,題目等同於[parseInt(1,0),parseInt(2,1),parseInt(3,2)] 最終返回[1, NaN, NaN]。

2.以下表達式的運行結果是:

[typeof null, null instanceof Object]
A.["object",false]
B.[null,false]
C.["object",true]
D.其他

A

typeof用以獲取一個變量或者表達式的類型,typeof一般只能返回如下幾個結果:

number,boolean,string,function(函數),object(NULL,數組,對象),undefined

instanceof 表示某個變量是否是某個對象的實例,null是個特殊的Object類型的值 ,表示空引用的意思 。但null返回object這個其實是最初JavaScript的實現的一個錯誤, 
然后被ECMAScript沿用了,成為了現在的標准,不過我們把null可以理解為尚未存在的對象的占位符,這樣就不矛盾了 ,雖然這是一種“辯解”。
對於我們開發人員 還是要警惕這種“語言特性”。最終返回:["object", false]

3.以下表達式的運行結果是:

[[3,2,1].reduce(Math.pow),[].reduce(Math.pow)]
A.報錯
B.[9,0]
C.[9,NaN]
D.[9,undefined]

A

pow() 方法可返回 x 的 y 次冪的值。[3,2,1].reduce(Math.pow);等同於:

function testFuc(x,y){
    console.info(x +" : "+y);
    return Math.pow(x,y);
}
console.info([3,2,1].reduce(testFuc));

執行Math.pow(3,2)和Math.pow(2,1),最終返回9和9。
但是要注意pow的參數都是必須的,[].reduce(Math.pow),等同於執行Math.pow();會導致錯誤。

4.以下表達式的運行結果是:

var val = 'value';
console.info('Value id '+(val === 'value')?'Something':'Nothing');
A.Something
B.Nothing
C.NaN
D.其他

A

先執行字符串拼接,再執行校驗

var val = 'value';
console.info('Value id '+(val === 'value123')?'Something':'Nothing');

同樣會返回something

 

5.以下表達式的運行結果是:

var name = 'World';
(function(){
    if(typeof name === 'undefined'){
    var name = "Jack";
    console.info('Goodbye '+ name);
}else{
    console.info('Hello ' + name);
}
})();
A.Goodbye Jack
B.Hello Jack
C.Goodbye undefined
D.Hello undefined

A

判斷語句被包裹在立即調用函數里,函數內部無法訪問外部值為'World'的name,因此typeof name === 'undefined'為真,執行下一步操作,最終輸出Goodbye Jack

6.以下表達式的運行結果是:

var START = END -100;
var count = 0;
for(var i = START ; i <= END ;i++){
    count ++;
}
console.info(count);
A.0
B.100
C.101
D.其他

D

END = 9007199254740992 ,START = 9007199254740892目的是計算的END和START之間的差。但是2的53次方計算出的結果由於精度問題使得i++失效。

7.以下表達式的運行結果是:

var arr = [0,1,2];
arr[10] = 10;
arr.filter(function(x){return x === undefined});
A.[undefined x 7]
B.[0,1,2,10]
C.[]
D.[undefined]

C

filter會接觸到沒有被賦值的元素,即在arr中,長度為10但實際數值元素列表為[0, 1, 2, 10],因此,最終返回一個空的數組[]。

8.以下表達式的運行結果是:

var two = 0.2;
var one = 0.1;
var eight = 0.8;
var six = 0.6;
[two -one == one,eight- six == two];
A.[true,true]
B.[false,false]
C.[true,false]
D.其他

C

兩個浮點數相加或者相減,將會導致一定的正常的數據轉換造成的精度丟失問題eight-six = 0.20000000000000007。
JavaScript中的小數采用的是雙精度(64位)表示的,由三部分組成: 符 + 階碼 + 尾數,在十進制中的 1/10,在十進制中可以簡單寫為 0.1 ,但在二進制中,他得寫成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循環)。因為浮點數只有52位有效數字,從第53位開始,就舍入了。這樣就造成了“浮點數精度損失”問題。 
更嚴謹的做法是(eight-six ).totoFiexd(1)或者用用Math.round方法回歸整數運算。判斷兩個浮點數是否相等,還是建議用逼近的比較,比如if((a-b) < 1E-10)

9.以下表達式的運行結果是:

function showCase(value){
    switch(value){
        case 'A':
            console.info('Case A');
            break;
        case 'B':
            console.info('Case B');
            break;
        case undefined :
            console.info('undefined');
            break;
        default:
            console.info('Do not know!');
    }
}
showCase(new String('A'));
A.Case A
B.Case B
C.Do not know
D.undefined

C

使用new String()使用構造函數調用講一個全新的對象作為this變量的值,並且隱式返回這個新對象作為調用的結果,因此showCase()接收的參數為String {0: "A"}為不是我們所認為的“A”

10.以下表達式的運行結果是:

function showCase(value){
    switch(value){
        case 'A':
            console.info('Case A');
            break;
        case 'B':
            console.info('Case B');
            break;
        case undefined :
            console.info('undefined');
            break;
        default:
        console.info('Do not know!');
    }
}
showCase(String('A'));
A.Case A
B.Case B
C.Do not know
D.undefined

A

直接調用String("A")創建的變量和"A"無異。

 
var a="123"    '只是設置變量
b=new String('123') '設置一個成員

var a="123";
a.sex=1;
alert(a.sex);//輸出未定義,因為不是成員,沒有這屬性

b=new String('123');
b.sex=1;
alert(b.sex);//輸出1,成員的屬性

11.以下表達式的運行結果是:

function isOdd(num){
    return num % 2 == 1;
}
function isEven(num){
    return num % 2 == 0;
}
function isSane(num){
    return isEven(num)||isOdd(num);
}
var values = [7,4,'13',-9,Infinity];
values.map(isSane);
A.[true, true, true, true, true]
B.[true, true, true, true, false]
C.[true, true, true, false, false]
D.[true, true, false, false, false]

C

function isSane(num){
    return isEven(num)||isOdd(num);
}

該函數判斷num是否為正整數,'13'被強制轉換為數值13,-9%2結果為-1,Infinity %2為NaN

12.以下表達式的運行結果是:

[parseInt(3,8),parseInt(3,2),parseInt(3,0)]
A.[3,3,3]
B.[3,3,NaN]
C.[3,NaN,NaN]
D.其他

D

最終結果為[3, NaN, 3];
parseInt() 函數可解析一個字符串,並返回一個整數。當參數 radix 的值為 0,或沒有設置該參數時,parseInt() 會根據 string 來判斷數字的基數。

 

13.以下表達式的運行結果是:

 

Array.isArray(Array.prototype)
A.true
B.false
C.報錯
D.其他

A

Array.prototype為[],Array.isArray(a)是一個判斷a是否為數組的方法。
判斷對象是否為數組的方法:
1)ES5函數isArray(),該函數測試對象的內部[[Class]]屬性是否為Array:Arrray.isArray(a);
2)判斷對象的構造函數是否為Array:a.constructor === Array
3)使用對象內部[[Class]]屬性創建結果字符串:Object.prototype.toString.call(a)
4)使用instanceof操作符測試對象是否繼承自Array:(但由於,一個頁面的iframe不會繼承自另外一個頁面的iframe,該方法不可靠)

 
a instanceof Array

14.以下表達式的運行結果是:

var a = [0];
if([0]){
    console.info(a == true);
}else{
    console.info("false");
}
A.true
B.false
C."else"
D.其他

B

在if條件判斷語句相對於==比較寬松中,只要if(n),n不為null,0,undefined數值,都會轉換為true。進入console.info(a == true);最終返回false。

15.以下表達式的運行結果是:

[]==[]
A.true
B.false
C.報錯
D.其他

B

數組,在 Javascript 中是對象,對象使用 == 比較都是比較的引用。簡單的說,就是,如果是同一個對象,就相等,如果不是同一個對象,就不等。每次使用 [] 都是新建一個數組對象,所以 [] == [] 這個語句里建了兩個數據對象,它們不等。

16.以下表達式的運行結果是:

[('5'+3),('5'-3)]
A.["53",2]
B.[8,2]
C.報錯
D.其他

A

執行'5'+3,加號具備拼接字符串功能,會將3強制轉換為字符串'3'和'5'拼接。
執行'5'-3,減號只具備數值運算的功能,因此會將'5'轉化為數值,進行5-3的數值運算

17.以下表達式的運行結果是:

1+-+++-+1
A.true
B.false
C.報錯
D.其他

C

18.以下表達式的運行結果是:

var arr = Array(3);
arr[0] = 2
arr.map(function(elem){return '1';});
A.[2,1,1]
B.["1","1","1"]
C.[2,"1","1"]
D.其他

D

區分賦值和聲明。雖然var arr = Array(3);創建一個長度為3的數組,但是實際只有一個元素被賦值,因此arr的實際長度為1,即最終參與map的只有一個元素,返回[1]

19.以下表達式的運行結果是:

function sidEffecting(arr){
    arr[0] = arr[2];
}
function bar(a,b,c){
    c = 10;
    sidEffecting(arguments);
    return a+b+c;
}
bar(1,1,1);
A.3
B.12
C.報錯
D.其他

D

按照執行步驟,無需多疑,最終結果為10+1+10

20.以下表達式的運行結果是:

var a = 111111111111111110000;
b = 1111;
console.info(a+b);
A.111111111111111111111
B.111111111111111110000
C.NaN
D.Infinity

B

js的精確整數最大為:Math.pow(2,53)-1 =9007199254740991.
var a = 111111111111111110000,
max = 9007199254740992;
a的值大於javascript所能表示的最大整數精度,因此和任何數值相加將會導致失真。

21.以下表達式的運行結果是:

var x = [].reverse;
x();
A.[]
B.undefined
C.報錯
D.window

C

正確調用方式為x.call([])

22.以下表達式的運行結果是:

Number.MIN_VALUE>0
A.true
B.false
C.報錯
D.其他

A

Number.MIN_VALUE表示的最小值為5e-324,MIN_VALUE代表的並不是負最小,而是最接近0的一個數,因此Number.MIN_VALUE>0。
負最小值可以使用-Number.MAX_VALUE表示。

23.以下表達式的運行結果是:

[1<2<3,3<2<1]
A.[true,true]
B.[true,false]
C.報錯
D.其他

A

1<2,返回true,執行true<3,會強制將true轉換為1,1<3,最終返回true。
3<2,返回false,執行false<1,會強制將false轉換為0,0<1,最終返回true。

24.以下表達式的運行結果是:

2 == [[[2]]]
A.true
B.false
C.undefined
D.其他

A

使用a==b判斷a和b對象是否相等,可以會將b對象強制轉換為a對象的類型,即執行2 == [[[2]]],會隱式調用parseInt([[[2]]])將[[[2]]]強制轉化為數字基本量,即2,2==2,最終返回true。

25.以下表達式的運行結果是:

[3.toString(),3..toString(),3...toString()]
A.["3",error,error]
B.["3","3.0",error]
C.[error,"3",error]
D.其他

C

Number中的toString(a),能夠將數值轉化成為a進制的值。但a缺省時,默認轉化為十進制。
一般使用方法為:var n = 3;3.toString();
執行3.toString(),因為3只是為數值型變量,為非Number實例,因此對於3不能直接調用Number方法。而執行3..toString(),會強制將3轉化為數字實例,因此能夠被解釋,輸出3,同樣可以使用(3).toString()。

26.以下表達式的運行結果是:

(function(){
    var x1 =y1 =1;
})();
console.info(y1);
console.info(x1);
A.1,1
B.error,error
C.1,error
D.其他

C

在立即調用函數內執行,var x1 =y1 =1;創建局部變量x1和全局變量y1。函數外部試圖訪問函數內部的變量,將會導致錯誤。

27.列舉IE和FF腳本兼容性的問題列舉IE和FF腳本兼容性的問題

(1)window.event
表示當前的事件對象,IE有這個對象,FF沒有


(2)獲取事件源
IE用srcElement獲取事件源,而FF用target獲取事件源


(3)添加、移除事件
IE:element.attachEvent("onclick",function)
element.detachEvent("onclick",function)
FF:element.addEventListener("click",function,true)
element.removeEventListener("click",function,true)

28.以下函數有什么問題?如何改進?

function initButtons(){
    var body = document.body,button,i;
    for(i =0;i<5;i++){
        button = document.createElement("button");
        button.innerHTML = "Button" + i;
        button.addEventListener("click",function(e){
            alert(i);
        },false);
        body.appendChild(button);
    }
}
initButtons();

題目所給出的代碼,除了有addEventListener不兼容IE瀏覽器的問題之外,最突出的一個問題是:
雖然在頁面上會顯示值為button+i的按鈕,但是點擊任意一個按鈕,最終都會顯示5。
要想點擊相關按鈕,彈出相應的1,2,3,4,5的值,需要理解閉包原理實現和使用立即回調函數。修改后的代碼如下:



function initButtons(){ 
    var body = document.body,button,i;          
    for(i =0;i<5;i++){ 
        (function(i){ 
             button = document.createElement("button"); 
             button.innerHTML = "Button" + i; 
             button.addEventListener("click",function(e){ 
                  alert(i); 
             },false); 
             body.appendChild(button); 
          })(i);                      
    }          
} 
initButtons(); 

涉及綁定和賦值得到區別。在運行時,進入一個作用域,javascript會為每一個綁定到該作用域的變量在內存中分配一個“槽”(slot)。函數中,創建變量document.body,button,i,因此當函數體(創建按鈕,並為按鈕綁定事件)被調用時,函數會為每個變量分配一個“槽”。在循環的每次迭代中,循環體都會為嵌套函數分配一個閉包。我們可能理解為,該函數存儲的是嵌套函數創建時變量i的值。但事實上,他存儲的是i的引用。由於每次函數創建后變量i的值都發生變化,因此函數內部最終看到的是變量i的引用。閉包存儲的是外部變量的引用而非值。
立即調用的函數表達式,是一種不可或缺的解決javascript缺少塊級作用域的方法。
需要深入理解,可以查看《Effective JavaScript》第13條:使用立即調用的函數表達式創建局部作用域

29.寫一段代碼

判斷一個字符串中出現次數最多的字符,並統計出現的次數。

使用常規方法和正則表達式匹配兩種算法

 

/*寫一段代碼。判斷一個字符串中出現次數最多的字符串,並統計出現的次數*/ 

function toGetTheMostCharsByArray(s){ 
var r={}; for(var i=0;i<s.length;i++){ if(!r[s[i]]){ r[s[i]] = 1; }else{ r[s[i]]++; } } var max = { "value " :s[0], "num" : r[s[0]] }; for(var n in r){//對象使用in關鍵字,因為沒有length if(r[n]>max.num){ max.num = r[n]; max.value = n; } } return max; } function toGetTheMostCharsByRegex(s){ var a = s.split(''); a.sort(); s = a.join(''); var regex = /(\w)\1+/g ;//\1代表重復的 var max = { "value " :s[0], "num" : 0 }; s.replace(regex,function(a,b){ if(max.num < a.length){ max.num = a.length; max.value= b; } }); return max; } var test = "efdfssssfrhth"; console.info("使用常規方法 ,出現最多的字符串為:"+toGetTheMostCharsByArray(test).value+" ,出現次數:"+toGetTheMostCharsByArray(test).num); console.info("使用字符串匹配,出現最多的字符串為:"+toGetTheMostCharsByRegex(test).value+" ,出現次數:"+toGetTheMostCharsByRegex(test).num);

 

30.請問一下兩段代碼有什么不同?

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

 

javascript的引擎是單線程的
javascript的引擎是基於事件驅動的
setTimeout和setInterval都是往事件隊列中增加一個待處理時間而已,setTimeout只觸發一次,而setInterval是循環觸發

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

上段代碼可使得setTimeout循環觸發。但是,執行完這段代碼塊才掛起時間,所以兩次執行時間會大於10毫秒

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

而上段代碼,是自動在10的時候掛上這個事件,所以兩次事件的相隔會小於等於10毫秒。
當線程阻塞在一個事件的時候,不管是使用setInterval還是setTimeout都需要等待當前事件處理完才能執行。

原文鏈接:一道常被人輕視的前端JS面試題

年前剛剛離職了,分享下我曾經出過的一道面試題,此題是我出的一套前端面試題中的最后一題,用來考核面試者的JavaScript的綜合能力,很可惜到目前為止的將近兩年中,幾乎沒有人能夠完全答對,並非多難只是因為大多面試者過於輕視他。

題目如下:

function Foo() {
    getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);} //請寫出以下輸出結果: Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();

 

答案是:

function Foo() {
    getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);} //答案: Foo.getName();//2 getName();//4 Foo().getName();//1 getName();//1 new Foo.getName();//2 new Foo().getName();//3 new new Foo().getName();//3

此題是我綜合之前的開發經驗以及遇到的JS各種坑匯集而成。此題涉及的知識點眾多,包括變量定義提升、this指針指向、運算符優先級、原型、繼承、全局變量污染、對象屬性及原型屬性優先級等等。

此題包含7小問,分別說下。

第一問

先看此題的上半部分做了什么,首先定義了一個叫Foo的函數,之后為Foo創建了一個叫getName的靜態屬性存儲了一個匿名函數,之后為Foo的原型對象新創建了一個叫getName的匿名函數。之后又通過函數變量表達式創建了一個getName的函數,最后再聲明一個叫getName函數。

第一問的 Foo.getName 自然是訪問Foo函數上存儲的靜態屬性,自然是2,沒什么可說的。

第二問

第二問,直接調用 getName 函數。既然是直接調用那么就是訪問當前上文作用域內的叫getName的函數,所以跟1 2 3都沒什么關系。此題有無數面試者回答為5。此處有兩個坑,一是變量聲明提升,二是函數表達式。

變量聲明提升

即所有聲明變量或聲明函數都會被提升到當前函數的頂部。

例如下代碼:

console.log('x' in window);//true
var x;
x = 0;

代碼執行時js引擎會將聲明語句提升至代碼最上方,變為:

var x;
console.log('x' in window);//true
x = 0;

函數表達式

 var getName 與 function getName 都是聲明語句,區別在於 var getName 是函數表達式,而 function getName 是函數聲明。關於JS中的各種函數創建方式可以看 大部分人都會做錯的經典JS閉包面試題 這篇文章有詳細說明。

函數表達式最大的問題,在於js會將此代碼拆分為兩行代碼分別執行。

例如下代碼:

console.log(x);//輸出:function x(){}
var x=1;
function x(){}

實際執行的代碼為,先將 var x=1 拆分為 var x; 和 x = 1; 兩行,再將 var x; 和 function x(){} 兩行提升至最上方變成:

var x;
function x(){}
console.log(x);
x=1;

所以最終函數聲明的x覆蓋了變量聲明的x,log輸出為x函數。

同理,原題中代碼最終執行時的是:

function Foo() {
    getName = function () { alert (1); }; return this; } var getName;//只提升變量聲明 function getName() { alert (5);}//提升函數聲明,覆蓋var的聲明  Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; getName = function () { alert (4);};//最終的賦值再次覆蓋function getName聲明  getName();//最終輸出4

第三問

第三問的 Foo().getName(); 先執行了Foo函數,然后調用Foo函數的返回值對象的getName屬性函數。

Foo函數的第一句  getName = function () { alert (1); };  是一句函數賦值語句,注意它沒有var聲明,所以先向當前Foo函數作用域內尋找getName變量,沒有。再向當前函數作用域上層,即外層作用域內尋找是否含有getName變量,找到了,也就是第二問中的alert(4)函數,將此變量的值賦值為 function(){alert(1)}。 

此處實際上是將外層作用域內的getName函數修改了。

注意:此處若依然沒有找到會一直向上查找到window對象,若window對象中也沒有getName屬性,就在window對象中創建一個getName變量。

之后Foo函數的返回值是this,而JS的this問題博客園中已經有非常多的文章介紹,這里不再多說。

簡單的講,this的指向是由所在函數的調用方式決定的。而此處的直接調用方式,this指向window對象。

遂Foo函數返回的是window對象,相當於執行 window.getName() ,而window中的getName已經被修改為alert(1),所以最終會輸出1

此處考察了兩個知識點,一個是變量作用域問題,一個是this指向問題。

第四問

直接調用getName函數,相當於 window.getName() ,因為這個變量已經被Foo函數執行時修改了,遂結果與第三問相同,為1

第五問

第五問 new Foo.getName(); ,此處考察的是js的運算符優先級問題。

 

js運算符優先級:

image_thumb

參考鏈接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

 

通過查上表可以得知點(.)的優先級高於new操作,遂相當於是:

new (Foo.getName)();

所以實際上將getName函數作為了構造函數來執行,遂彈出2。

第六問

第六問 new Foo().getName() ,首先看運算符優先級括號高於new,實際執行為

(new Foo()).getName()

遂先執行Foo函數,而Foo此時作為構造函數卻有返回值,所以這里需要說明下js中的構造函數返回值問題。

構造函數的返回值

在傳統語言中,構造函數不應該有返回值,實際執行的返回值就是此構造函數的實例化對象。

而在js中構造函數可以有返回值也可以沒有。

1、沒有返回值則按照其他語言一樣返回實例化對象。

image_thumb1

2、若有返回值則檢查其返回值是否為引用類型。如果是非引用類型,如基本類型(string,number,boolean,null,undefined)則與無返回值相同,實際返回其實例化對象。

image_thumb2

3、若返回值是引用類型,則實際返回值為這個引用類型。

image_thumb3

原題中,返回的是this,而this在構造函數中本來就代表當前實例化對象,遂最終Foo函數返回實例化對象。

之后調用實例化對象的getName函數,因為在Foo構造函數中沒有為實例化對象添加任何屬性,遂到當前對象的原型對象(prototype)中尋找getName,找到了。

遂最終輸出3。

第七問

第七問, new new Foo().getName(); 同樣是運算符優先級問題。

最終實際執行為:

new ((new Foo()).getName)();

先初始化Foo的實例化對象,然后將其原型上的getName函數作為構造函數再次new。

遂最終結果為3

===2016年03月23日更新===

這里引用 @於明昊 的評論,更詳細的解釋了第7問:

這里確實是(new Foo()).getName(),但是跟括號優先級高於成員訪問沒關系,實際上這里成員訪問的優先級是最高的,因此先執行了 .getName,但是在進行左側取值的時候, new Foo() 可以理解為兩種運算:new 帶參數(即 new Foo())和函數調用(即 先 Foo() 取值之后再 new),而 new 帶參數的優先級是高於函數調用的,因此先執行了 new Foo(),或得 Foo 類的實例對象,再進行了成員訪問 .getName。

最后

就答題情況而言,第一問100%都可以回答正確,第二問大概只有50%正確率,第三問能回答正確的就不多了,第四問再正確就非常非常少了。其實此題並沒有太多刁鑽匪夷所思的用法,都是一些可能會遇到的場景,而大多數人但凡有1年到2年的工作經驗都應該完全正確才對。

只能說有一些人太急躁太輕視了,希望大家通過此文了解js一些特性。

並祝願大家在新的一年找工作面試中膽大心細,發揮出最好的水平,找到一份理想的工作。

來源:javascript小記一筆——(高階函數、map、reduce、filter、sort、reverse)

高階函數就是可以將函數作為另一個函數的參數。
例如:將兩個數的平方相加,這里匿名函數fn就是函數被作為參數。

function add(a,b,fn){
return fn(a)+fn(b);
}
var fn=function (a){
return a*a;
}
add(2,3,fn);


1.map作用在數組的每個元素上的函數。
例如:將數組arr的每個元素都加上10。

var arr=[5,6,7,8,9];
var fn=function(a){
return a+10;
}
console.log(arr.map(fn));


2.reduce也作用在數組上,但是每次只能接受兩個參數。
例如:將數組arr的每個元素相加,因為元素為字符串,所以連接在一起。

var arr=["小","明","喜","歡","學","習"];
var fn=function(a,b){
return a+b;
}
console.log(arr.reduce(fn));

也可以寫成:

var arr=["小","明","喜","歡","學","習"];
function fn(arr){
return arr.reduce(function(a,b){
return a+b;
})
}
console.log(fn(arr));


3.filter用於過濾數組的元素。
例如:過濾掉arr內的偶數。

var arr=[1,2,3,4,5,6,7,8,9,10];
var fn=arr.filter(function(x){
return x%2!=0;
})
console.log(fn);


4.sort用於將數組進行排序,此函數默認會將數組內的元素轉換成字符串類型進行排序,且按照大寫在前的規律排序。

var arr=["X","y","Z","A","b","C"];
console.log(arr.sort());


忽略大小寫進行排序。


如果倒敘的話將1與-1的值交換。

function fn(a,b){
var a1=a.toLowerCase();
var b1=b.toLowerCase()
if(a1>b1){
return -1;
}
if(a1<b1){
return 1;
}
return 0;
}
var newArr=arr.sort(fn);
console.log(newArr);


當然也有一個倒敘的函數

console.log(newArr.reverse());

 

webSocket例子
[http://www.cnblogs.com/wei2yi/archive/2011/03/23/1992830.html]
是下一代客戶端-服務器的異步通信方法,該通信取代了單個的TCP套接字,使用ws或wss協議,可用於任意的客戶端和服務器程序;而且有一個優秀的第三方API,名為Socket.IO
服務器和客戶端可以在給定的時間范圍內的任意時刻,相互推送信息;
與ajax的區別:
WebSocket並不限於以Ajax(或XHR)方式通信,因為Ajax技術需要客戶端發起請求,而WebSocket服務器和客戶端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允許跨域通信

// 創建一個Socket實例
var socket = new WebSocket('ws://localhost:8080'); //ws表示socket協議
// 打開Socket 
socket.onopen = function(event) { 
// 發送一個初始化消息
socket.send('I am the client and I\'m listening!'); 
// 監聽消息
socket.onmessage = function(event) { 
console.log('Client received a message',event); 
}; 
// 監聽Socket的關閉
socket.onclose = function(event) { 
console.log('Client notified socket has closed',event); 
}; 
// 關閉Socket.... 
socket.close() 
};

 

 

(內容5)——————

10個最常見的 HTML5 面試題及答案

1、新的 HTML5 文檔類型和字符集是?

HTML5 文檔類型很簡單:<!doctype html>

HTML5 使用 UTF-8 編碼示例:

<meta charset=”UTF-8″>

2、HTML5 中如何嵌入音頻?

HTML5 支持 MP3、Wav 和 Ogg 格式的音頻,下面是在網頁中嵌入音頻的簡單示例:

<audio controls>
    <source src=”jamshed.mp3″ type=”audio/mpeg”>
    Your browser does’nt support audio embedding feature.
</audio>

3、HTML5 中如何嵌入視頻?

和音頻類似,HTML5 支持 MP4、WebM 和 Ogg 格式的視頻,下面是簡單示例:

1
2
3
4
<video width=”450″ height=”340″ controls>
   <source src=”jamshed.mp4″ type=”video/mp4″>
    Your browser does’nt support video embedding feature.
</video>

更新時間: 2015-10-9

HTML

HTML5的離線儲存怎么使用,工作原理能不能解釋一下?

在用戶沒有與因特網連接時,可以正常訪問站點或應用,在用戶與因特網連接時,更新用戶機器上的緩存文件。
原理:HTML5的離線存儲是基於一個新建的.appcache文件的緩存機制(不是存儲技術),通過這個文件上的解析清單離線存儲資源,這些資源就會像cookie一樣被存儲了下來。之后當網絡在處於離線狀態下時,瀏覽器會通過被離線存儲的數據進行頁面展示。

如何使用:
1、頁面頭部像下面一樣加入一個manifest的屬性;
2、在cache.manifest文件的編寫離線存儲的資源;
    CACHE MANIFEST
    #v0.11
    CACHE:
    js/app.js
    css/style.css
    NETWORK:
    resourse/logo.png
    FALLBACK:
    / /offline.html
3、在離線狀態時,操作window.applicationCache進行需求實現。

詳細的使用請參考:有趣的HTML5:離線存儲

寫一個通用的事件偵聽器函數。

    // event(事件)工具集,來源:github.com/markyun
    markyun.Event = {
        // 頁面加載完成后
        readyEvent : function(fn) {
            if (fn==null) {
                fn=document;
            }
            var oldonload = window.onload;
            if (typeof window.onload != 'function') {
                window.onload = fn;
            } else {
                window.onload = function() {
                    oldonload();
                    fn();
                };
            }
        },
        // 視能力分別使用dom0||dom2||IE方式 來綁定事件
        // 參數: 操作的元素,事件名稱 ,事件處理程序
        addEvent : function(element, type, handler) {
            if (element.addEventListener) {
                //事件類型、需要執行的函數、是否捕捉
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + type, function() {
                    handler.call(element);
                });
            } else {
                element['on' + type] = handler;
            }
        },
        // 移除事件
        removeEvent : function(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.datachEvent) {
                element.detachEvent('on' + type, handler);
            } else {
                element['on' + type] = null;
            }
        },
        // 阻止事件 (主要是事件冒泡,因為IE不支持事件捕獲)
        stopPropagation : function(ev) {
            if (ev.stopPropagation) {
                ev.stopPropagation();
            } else {
                ev.cancelBubble = true;
            }
        },
        // 取消事件的默認行為
        preventDefault : function(event) {
            if (event.preventDefault) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
        },
        // 獲取事件目標
        getTarget : function(event) {
            return event.target || event.srcElement;
        },
        // 獲取event對象的引用,取到事件的所有信息,確保隨時能使用event;
        getEvent : function(e) {
            var ev = e || window.event;
            if (!ev) {
                var c = this.getEvent.caller;
                while (c) {
                    ev = c.arguments[0];
                    if (ev && Event == ev.constructor) {
                        break;
                    }
                    c = c.caller;
                }
            }
            return ev;
        }
    };

什么是閉包(closure),為什么要用它?

執行say667()后,say667()閉包內部變量會存在,而閉包內部函數的內部變量不會存在.使得Javascript的垃圾回收機制GC不會收回say667()所占用的資源,因為say667()的內部函數的執行需要依賴say667()中的變量。這是對閉包作用的非常直白的描述.

  function say667() {
    // Local variable that ends up within closure
    var num = 666;
    var sayAlert = function() { alert(num); }
    num++;
    return sayAlert;
}

 var sayAlert = say667();
 sayAlert()//執行結果應該彈出的667

模塊化怎么做?

立即執行函數,不暴露私有成員

    var module1 = (function(){
        var _count = 0;
        var m1 = function(){
          //...
        };
        var m2 = function(){
          //...
        };
        return {
          m1 : m1,
          m2 : m2
        };
      })();

.call() 和 .apply() 的區別?

  例子中用 add 來替換 sub,add.call(sub,3,1) == add(3,1) ,所以運行結果為:alert(4);

  注意:js 中的函數其實是對象,函數名是對 Function 對象的引用。

    function add(a,b)
    {
        alert(a+b);
    }

    function sub(a,b)
    {
        alert(a-b);
    }

    add.call(sub,3,1);

 

用jQuery實現數組轉字符串
jQuery中沒有提供這個功能,所以你需要先編寫兩個jQuery的擴展:

 

    $.fn.stringifyArray = function(array) {
        return JSON.stringify(array)
    }

    $.fn.parseArray = function(array) {
        return JSON.parse(array)
    }

    然后調用:
    $("").stringifyArray(array)

針對 jQuery 的優化方法?

*基於Class的選擇性的性能相對於Id選擇器開銷很大,因為需遍歷所有DOM元素。

*頻繁操作的DOM,先緩存起來再操作。用Jquery的鏈式調用更好。
 比如:var str=$("a").attr("href");

*for (var i = size; i < arr.length; i++) {}
 for 循環每一次循環都查找了數組 (arr) 的.length 屬性,在開始循環的時候設置一個變量來存儲這個數字,可以讓循環跑得更快:
 for (var i = size, length = arr.length; i < length; i++) {}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM