WEB前端面試題彙總整理01

1.JS找字符串中出現最多的字符

例如:求字符串'nininihaoa'中出現次數最多字符javascript

var str = "nininihaoa";
var o = {};
for (var i = 0, length = str.length; i < length; i++) {
    var char = str.charAt(i);
    if (o[char]) {
        o[char]++;  //次數加1
    } else {
        o[char] = 1;    //若第一次出現,次數記爲1
    }
}
console.log(o);   //輸出的是完整的對象,記錄着每個字符及其出現的次數
//遍歷對象,找到出現次數最多的字符的次數
var max = 0;
for (var key in o) {
    if (max < o[key]) {
        max = o[key];   //max始終儲存次數最大的那個
    }
}
for (var key in o) {
    if (o[key] == max) {
        //console.log(key);
        console.log("最多的字符是" + key);
        console.log("出現的次數是" + max);
    }
}

結果以下:css

Object {n: 3, i: 3, h: 1, a: 2, o: 1}
最多的字符是n
出現的次數是3
最多的字符是i
出現的次數是3

方法二,固然還可使用reduce方法來實現:html

var arrString = 'abcdaabc';
arrString.split('').reduce(function(res, cur) {
    res[cur] ? res[cur] ++ : res[cur] = 1
    return res;
}, {})

想詳細瞭解reduce()方法,能夠參考:《JS進階篇--JS數組reduce()方法詳解及高級技巧 》前端

2.JS實現九九乘法表

jQuery實現方式:java

var sum=0;
var wite;
for (var i = 1; i < 10; i++){
        var div=$('<div class="class'+i+'"></div>');
        $("body").append(div);
        for(var j = i; j > 0; j--){
                sum = j * i;
                wite = (j+"X"+i+"="+sum);

                div.prepend($('<span style="padding-right:10px">'+wite+'</span>'));
        }
        
}

實現結果如圖所示:
imagenode

原生js實現方式:
css代碼:css3

html,body,ul,li {
    padding: 0; 
    margin: 0; 
    border: 0; 
}
ul { 
    width: 900px;
    overflow: hidden;
    margin-top: 4px;
    font-size: 12px; 
    line-height: 36px;
}
li { 
    float: left; 
    width: 90px; 
    margin: 0 4px; 
    display: inline-block; 
    text-align: center; 
    border: 1px solid #333; 
    background:yellowgreen; 
}

js代碼:面試

for(var i = 1; i <= 9; i++){
    var myUl = document.createElement('ul');
    for(var j = 1; j <= i; j++){
        var myLi = document.createElement('li');
        var myText = document.createTextNode(j + " × " + i + " = " + i*j);
        myLi.appendChild(myText);
        myUl.appendChild(myLi);
    }
    document.getElementsByTagName('body')[0].appendChild(myUl);
}

原生js實現效果如圖所示:
image算法

3.這幾道前端面試題很繞嗎?作對了幾道?

第一題

var fun = function(){
    this.name = 'peter';
    return {
    name: 'jack'
    };
}
var p = new fun();
//請問p.name是:

第二題

var fun = function(){
    this.name = 'peter';

    return 'jack';    
    }

var p = new fun();
//請問p.name是:

第三題

var fun = function(){}

fun.prototype = {
    info : {
    name : 'peter',
    age : 25
    }
}

var a = new fun();
var b = new fun();

a.info.name = 'jack';
b.info.name = 'tom';

//請問a.info.name和b.info.name分別是:

第四題

var fun = function(){
    this.info = {
    name : 'peter',
    age : 25
    }
}

var a = new fun();
var b = new fun();

a.info.name = 'jack';
b.info.name = 'tom';
//請問a.info.name和b.info.name分別是:

第五題

var fun = function(){}

fun.prototype = {    
    name : 'peter',    
    age : 25    
}

var a = new fun();
var b = new fun();

a.name = 'jack';
b.name = 'tom';
//請問a.name和b.name分別是:

第六題

var fun = function(){
    this.info = {
    name : 'peter',
    age : 25
    }
}

fun.prototype = {
    info : {
    name : 'peter',
    age : 25
    }
}

var a = new fun();
var b = new fun();

a.info.name = 'jack';
b.info.name = 'tom';
//請問a.info.name和b.info.name分別是:

解答:canvas

1,2題考察的是構造函數的返回值的問題。

每一個函數都有返回值,若是使用了return語句,則返回return後跟的值,若是沒有使用return,則默認返回undefined.
特別的,若是這個函數是構造函數,則默認返回this對象,若是構造函數內使用了return語句,而且return後跟的是一個對象,則這個構造函數返回的是這個對象,不然返回this.
因此1題中的p = {name: 'jack'},而2題中的p = {name: 'peter'}.

3, 4, 5, 6題都是考察prototype的知識。

3.兩個都輸出tom。首先你要知道原型模式的執行流程:

1.先查找構造函數實例裏的屬性或方法,若是有,就當即返回。
2.若是構造函數的實例沒有,就去它的原型對象裏找,若是有,就當即返回

4 .a.info.name 爲jack,b.info.name爲tom。緣由我想你從第三題已經得出來了。

5.a.name輸出jack,b.name輸出tom。緣由我想你從第三題已經得出來了。

4.經過示例搞懂js閉包

例1

function sayHello(name) 
{
 var text = 'Hello ' + name;
 var sayAlert = function() { console.log(text); }
 sayAlert();
}
sayHello("Bob") // 輸出"Hello Bob"

在sayHello()函數中定義並調用了sayAlert()函數;sayAlert()做爲內層函數,能夠訪問外層函數sayHello()中的text變量。

例2

function sayHello2(name) 
{
 var text = 'Hello ' + name; // 局部變量
 var sayAlert = function() { console.log(text); }
 return sayAlert;
}

var say2 = sayHello2("Jane");
say2(); // 輸出"Hello Jane"

例3

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push( 
        function() {
            console.log(item + ' ' + list[i]);
        } 
     );
 }
 return result;
}

var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) {
    fnlist[j](); 
}

獲得的結果:連續輸出3個"item3 undefined"
解析:經過執行buildList函數,返回了一個result,那麼這個result存放的是3個匿名函數。然而這三個匿名函數其實就是三個閉包,由於它能夠訪問到父函數的局部變量。因此閉包內的保留的i是最終的值爲3.因此list[3]確定是undefined. item變量值爲item3.

改爲以下代碼:

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push( 
        (function(i) {
            console.log(item + ' ' + list[i]);
        })(i)
     );
 }
 return result;
}

var fnlist = buildList([1,2,3]);

獲得的結果:

item1 1
item2 2
item3 3

解釋:這兒雖然傳遞了一個數組進去,可是返回的是三個自執行的函數。

例4

function newClosure(someNum, someRef) 
{
 var anArray = [1,2,3];
 var num = someNum;
 var ref = someRef;
 return function(x) 
 {
 num += x;
 anArray.push(num);
 console.log('num: ' + num + "; " + 'anArray ' + anArray.toString() + "; " + 'ref.someVar ' + ref.someVar);
 }
}
closure1 = newClosure(40, {someVar: "closure 1"}); 
closure2 = newClosure(1000, {someVar: "closure 2"}); 
closure1(5); // 打印"num: 45; anArray 1,2,3,45; ref.someVar closure 1"
closure2(-10); // 打印"num: 990; anArray 1,2,3,990; ref.someVar closure 2"

每次調用newClosure()都會建立獨立的閉包,它們的局部變量num與ref的值並不相同。

例5

function sayAlice() 
{
 var sayAlert = function() { console.log(alice); }
 var alice = 'Hello Alice';
 return sayAlert;
}

var sayAlice2 = sayAlice();
sayAlice2(); // 輸出"Hello Alice"

alice變量在sayAlert函數以後定義,這並未影響代碼執行。由於返回函數sayAlice2所指向的閉包會包含sayAlice()函數中的全部局部變量,這天然包括了alice變量,所以能夠正常打印」Hello Alice」。

例6

function setupSomeGlobals() {
 var num = 666;
 gAlertNumber = function() { console.log(num); }
 gIncreaseNumber = function() { num++; }
 gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
gAlertNumber(); // 輸出666
gIncreaseNumber();
gAlertNumber(); // 輸出667
gSetNumber(5);
gAlertNumber(); // 輸出5

解釋:首先gAlertNumber,gIncreaseNumber,gSetNumber是三個全局變量,而且其三個值都是匿名函數,然而這三個匿名函數自己都是閉包。他們操做的num都是保存在內存中的同一個num,全部會得出上面的結果。

6.a.info.name 爲jack,b.info.name爲tom。緣由我想你從第三題已經得出來了。

5.JS重複輸出一個給定的字符串

以下:
重複輸出一個給定的字符串(str第一個參數)n 次 (num第二個參數),若是第二個參數num不是正數的時候,返回空字符串。

function repeatStringNumTimes(str, num) {
  return str;
}
repeatStringNumTimes("abc", 3);

提供測試狀況:

repeatStringNumTimes("*", 3) //應該返回 "***".
repeatStringNumTimes("abc", 3) //應該返回 "abcabcabc".
repeatStringNumTimes("abc", 4) //應該返回 "abcabcabcabc".
repeatStringNumTimes("abc", 1) //應該返回 "abc".
repeatStringNumTimes("*", 8) //應該返回 "********".
repeatStringNumTimes("abc", -2) //應該返回 "".

解題思路

我將介紹三種方法:

  • 1.使用 while 循環
  • 2.使用遞歸
  • 3.使用ES6 repeat()

方法1:經過 while 循環重複輸出一個字符串

function repeatStringNumTimes(string, times) {
  var repeatedString = "";
  while (times > 0) {
    repeatedString += string;
    times--;
  }
  return repeatedString;
}
repeatStringNumTimes("abc", 3);

不過這裏還能夠有幾個變種:

對於老前端來講,首先一個可能會將字符串拼接,修改成 數組join()拼接字符串,例如:

function repeatStringNumTimes(string, times) {
  var repeatedArr = []; //
  while (times > 0) {
    repeatedArr.push(string);
    times--;
  }
  return repeatedArr.join("");
}
repeatStringNumTimes("abc", 3)

不少老前端都有用數組join()拼接字符串的「情懷」,由於很早之前廣泛認爲數組join()拼接字符串比字符串+拼接速度要快得多。不過如今未必,例如,V8 下+拼接字符串,要比數組join()拼接字符串快。我用這兩個方法測試了3萬次重複輸出,只相差了幾毫秒。

另外一個變種能夠用 for 循環:

function repeatStringNumTimes(string, times) {
  var repeatedString = "";
  for(var i = 0; i < times ;i++) {
    repeatedString += string;
  }
  return repeatedString;
}
repeatStringNumTimes("abc", 3)

方法2:經過條件判斷和遞歸重複輸出一個字符串

遞歸是一種經過重複地調用函數自己,直到它達到達結果爲止的迭代操做的技術。爲了使其正常工做,必須包括遞歸的一些關鍵特徵。

function repeatStringNumTimes(string, times) {
  if(times < 0) 
    return "";
  if(times === 1) 
    return string;
  else 
    return string + repeatStringNumTimes(string, times - 1);
}
repeatStringNumTimes("abc", 3);

方法3:使用ES6 repeat() 方法重複輸出一個字符串

這個解決方案比較新潮,您將使用 String.prototype.repeat() 方法:

repeat() 方法構造並返回一個新字符串,該字符串包含被鏈接在一塊兒的指定數量的字符串的副本。 這個方法有一個參數 count 表示重複次數,介於0和正無窮大之間的整數 : [0, +∞) 。表示在新構造的字符串中重複了多少遍原字符串。重複次數不能爲負數。重複次數必須小於 infinity,且長度不會大於最長的字符串。

function repeatStringNumTimes(string, times) {
  if (times > 0)
    return string.repeat(times);
  else
    return "";
}
repeatStringNumTimes("abc", 3);

您可使用三元表達式做爲 if/else 語句的快捷方式,以下所示:

function repeatStringNumTimes(string, times) {
  return times > 0 ? string.repeat(times) : "";
}
repeatStringNumTimes("abc", 3);

轉載地址:http://www.css88.com/archives/7045

6.函數聲明相關

var x=1,
    y=0,
    z=0;
function add(n){
    n=n+1;
}
y=add(x);
z=x+y;
console.log("y1:"+y);
console.log("z1:"+z);

function add(n){
    n=n+3;
}
y=add(x);
z=x+y;
console.log("y2:"+y);
console.log("z2:"+z);

求y,z的值。

結果爲:

y1:undefined
z1:NaN
y2:undefined
z2:NaN

變化一下:

var x=1,
    y=0,
    z=0;
function add(n){
    return n=n+1;
}
y=add(x);
z=x+y;
console.log("y1:"+y);
console.log("z1:"+z);

function add(n){
   return n=n+3;
}
y=add(x);
z=x+y;
console.log("y2:"+y);
console.log("z2:"+z);

求y,z的值

答案:

y1:4
z1:5
y2:4
z2:5

7.做用域範圍(Scope)

思考如下代碼:

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

控制檯(console)會打印出什麼?

答案
上述代碼會打印出5
這個問題的陷阱就是,在當即執行函數表達式(IIFE)中,有兩個命名,可是其中變量是經過關鍵詞var來聲明的。這就意味着a是這個函數的局部變量。與此相反,b是在全局做用域下的。

這個問題另外一個陷阱就是,在函數中他沒有使用"嚴格模式" ('use strict';)。若是 嚴格模式 開啓,那麼代碼就會報出未捕獲引用錯誤(Uncaught ReferenceError):b沒有定義。記住,嚴格模式要求你在須要使用全局變量時,明確地引用該變量。所以,你須要像下面這麼寫:

(function(){
    'use strict'
    var a = window.b = 5;
})();
console.log(b);

再看以下一個例子:

var a = 6;
setTimeout(function () {
    alert(a);
    a = 666;
}, 1000);
a = 66;

結果:66

8.建立 「原生(native)」 方法

String對象上定義一個repeatify函數。這個函數接受一個整數參數,來明確字符串須要重複幾回。這個函數要求字符串重複指定的次數。舉個例子:

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*/
};

當你須要爲舊瀏覽器實現向後兼容的函數時,這一技巧十分有用。

9.變量提高(Hoisting)

執行如下代碼會有什麼結果?爲何?

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

答案
這段代碼的執行結果是 undefined 2

這個結果的緣由是,變量和函數都被提高了(hoisted)。所以,在a被打印的時候,它已經在函數做用域中存在(即它已經被聲明瞭),可是它的值依然是 undefined。換言之,上述代碼和如下代碼是等價的。

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

再看以下代碼:

(function() {
   console.log(typeof foo); 
   console.log(typeof bar); 

   var foo = 'hello',
       bar = function() {
           return 'world';
       };

   function foo() {
       return 'hello';
   }

}());

結果:

function
undefined

10.this 在 JavaScript 中是如何工做的

如下代碼的結果是什麼?請解釋你的答案。

var fullname = 'John Doe';
var obj = {
    fullname: 'Colin Thrig',
    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。緣由是在 JavaScript 中,一個函數的上下文環境,也就是this關鍵詞所引用對象,是依賴於函數是如何被調用的,而不是依賴於函數如何被定義的。

在第一個 console.log() 調用中, getFullname() 是做爲 obj.prop 的函數被調用的。所以,這裏的上下文環境指向後者而且函數返回this對象的 fullname 屬性。相反,當 getFullname() 被賦爲test變量的值時,那個語境指向全局對象(window)。這是由於,test 被隱式設置爲全局對象的屬性。所以,函數調用返回 window 的 fullname 屬性值,在此段代碼中,這個值是經過第一行賦值語句設置的。

11.call() 和 apply()

修復上一個問題,讓最後一個 console.log() 打印出 Aurelio De Rosa。
要解決這個問題,能夠經過爲函數 call() 或者 apply() 強制函數調用的上下文環境。若是你不知道 call() 和 apply() 之間的區別,在如下代碼中,我會用 call(),可是在這裏,用 apply() 也能夠得到相同的結果:

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

12.閉包(Closures)

考慮下面的代碼:

var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener('click', function() {
      console.log('You clicked element #' + i);
   });
}

請問,若是用戶點擊第一個和第四個按鈕的時候,控制檯分別打印的結果是什麼?爲何?

答案:
兩次打印都是nodes.length的值。

那麼修復上題的問題,使得點擊第一個按鈕時輸出0,點擊第二個按鈕時輸出1,依此類推。
有多種辦法能夠解決這個問題,下面主要使用兩種方法解決這個問題。

第一個解決方案使用當即執行函數表達式(IIFE)再建立一個閉包,從而獲得所指望的i的值。實現此方法的代碼以下:

var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener('click', (function(i) {
      return function() {
         console.log('You clicked element #' + i);
      }
   })(i));
}

另外一個解決方案不使用IIFE,而是將函數移到循環的外面。這種方法由下面的代碼實現:

function handlerWrapper(i) {
   return function() {
      console.log('You clicked element #' + i);
   }
}
 
var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
   nodes[i].addEventListener('click', handlerWrapper(i));
}

代碼片斷一:

var name = "The Window";
var object = {
  name : "My Object",
  getNameFunc : function(){
    return function(){
       return this.name;
    };
   }
  };
alert(object.getNameFunc()());

結果:The Window

代碼片斷二:

var name = "The Window";
var object = {
  name : "My Object",
  getNameFunc : function(){
    var that = this;
    return function(){
      return that.name;
    };
  }
};

alert(object.getNameFunc()());

結果:My Object
文章地址:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

13.數據類型問題

考慮以下代碼:

console.log(typeof null);
console.log(typeof {});
console.log(typeof []);
console.log(typeof undefined);

答案:

object
object
object
undefined

14.事件循環

下面代碼運行結果是什麼?請解釋。

function printing() {
   console.log(1);
   setTimeout(function() { console.log(2); }, 1000);
   setTimeout(function() { console.log(3); }, 0);
   console.log(4);
}
printing();

答案:

1
4
3
2

想知道爲何輸出順序是這樣的,你須要弄瞭解setTimeout()作了什麼,以及瀏覽器的事件循環原理。瀏覽器有一個事件循環用於檢查事件隊列,處理延遲的事件。UI事件(例如,點擊,滾動等),Ajax回調,以及提供給setTimeout()setInterval()的回調都會依次被事件循環處理。所以,當調用setTimeout()函數時,即便延遲的時間被設置爲0,提供的回調也會被排隊。回調會呆在隊列中,直到指定的時間用完後,引擎開始執行動做(若是它在當前不執行其餘的動做)。所以,即便setTimeout()回調被延遲0毫秒,它仍然會被排隊,而且直到函數中其餘非延遲的語句被執行完了以後,纔會執行。

15.算法問題

寫一個isPrime()函數,當其爲質數時返回true,不然返回false

答案:

我認爲這是面試中最多見的問題之一。然而,儘管這個問題常常出現而且也很簡單,可是從被面試人提供的答案中能很好地看出被面試人的數學和算法水平。

首先, 由於JavaScript不一樣於C或者Java,所以你不能信任傳遞來的數據類型。若是面試官沒有明確地告訴你,你應該詢問他是否須要作輸入檢查,仍是不進行檢查直接寫函數。嚴格上說,應該對函數的輸入進行檢查。

第二點要記住:負數不是質數。一樣的,1和0也不是,所以,首先測試這些數字。此外,2是質數中惟一的偶數。沒有必要用一個循環來驗證4,6,8。再則,若是一個數字不能被2整除,那麼它不能被4,6,8等整除。所以,你的循環必須跳過這些數字。若是你測試輸入偶數,你的算法將慢2倍(你測試雙倍數字)。能夠採起其餘一些更明智的優化手段,我這裏採用的是適用於大多數狀況的。例如,若是一個數字不能被5整除,它也不會被5的倍數整除。因此,沒有必要檢測10,15,20等等。

最後一點,你不須要檢查比輸入數字的開方還要大的數字。我感受人們會遺漏掉這一點,而且也不會由於此而得到消極的反饋。可是,展現出這一方面的知識會給你額外加分。

如今你具有了這個問題的背景知識,下面是總結以上全部考慮的解決方案:

function isPrime(number) {
   // If your browser doesn't support the method Number.isInteger of ECMAScript 6,
   // you can implement your own pretty easily
   if (typeof number !== 'number' || !Number.isInteger(number)) {
      // Alternatively you can throw an error.
      return false;
   }
   if (number < 2) {
      return false;
   }
 
   if (number === 2) {
      return true;
   } else if (number % 2 === 0) {
      return false;
   }
   var squareRoot = Math.sqrt(number); //平方根,好比Math.sqrt(9)爲3
   for(var i = 3; i <= squareRoot; i += 2) {
      if (number % i === 0) {
         return false;
      }
   }
   return true;
}

其中代碼中用到了Number.isInteger(),該方法是ES6方法,用來判斷一個值是否爲整數。

例如:

Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("15") // false
Number.isInteger(true) // false

須要注意的是,在JavaScript內部,整數和浮點數是一樣的儲存方法,因此2525.0被視爲同一個值。

16.記騰訊一次糟糕的筆試面試經歷(轉)

JS考察

一、基本數據類型:undefined、null、String、Number、boolean
二、有如下兩個函數,定義一個對象使其擁有這兩個函數屬性。

function mobile(){
    return  'mobile';
}
function phone(){
    return 'phone';
}
var a = {};
a.mobile = mobile();
a.phone = phone();
console.log(a);

三、(考察了對象變量和堆內存)

var a = {n:10,m:20};
var b = a;
b.n = 30;
console.log(a.n);
console.log(b);

結果:

30
Object {n: 30, m: 20}

四、(考察閉包)

var x = 20;
var a = {
    x : 15,
    fn : function(){
        var x = 30;
        return function(){
            return this.x;
        };
    }
};
console.log(a.fn());
console.log((a.fn())());
console.log(a.fn()());
console.log(a.fn()() == (a.fn())());
console.log(a.fn().call(this));
console.log(a.fn().call(a));

結果:

1)、function(){return this.x;}
2)、20
3)、20
4)、true
5)、20
6)、15

五、(數組去重複項)

var arr = ['a','g','q','d','a','e','q'];
Array.prototype.unique = function(){
    for(var i = 0; i < this.length; i++){
        for(var j = i+1; j < this.length; j++){
            if(this[i] == this[j]){
                this.splice(j,1);
            }
        }
    }
    return this;
};
console.log(arr.unique());

此方法有缺陷,好比var arr = ['a','a','a','g','q','d','a','e','q']; 那麼獲得的結果:["a", "a", "g", "q", "d", "e"]。知道緣由吧?不知道請查看數組去重的方法《JS基礎篇--JS實現數組去重方法整理》

六、編寫一個函數fn(Number n),將數字轉爲大寫輸出,如輸入123,輸出一百二十三

function fn(n){
    if(!/^([1-9]\d*)/.test(n)){
        return '非法數據';
    }
    var unit = '千百十億千百十萬千百十個';
    if(n.length > unit.length){
        return '數據過長';
    }
    var newStr = '';
    var nlength = n.length;
    unit = unit.substr(unit.length - nlength);
    for(var i = 0; i < nlength; i++){
        newStr += '零一二三四五六七八九'.charAt(n[i]) + unit.charAt(i);
    }
    newStr = newStr.substr(0,newStr.length-1);
    newStr = newStr.replace(/零(千|百|十)/g,'零').replace(/(零)+/g,'零').replace(/零(億|萬)/g,'$1');
    return newStr;
}
console.log(fn('205402002103'));

CSS

一、考察了盒子模型
二、內聯元素、塊元素
三、css3的貝塞爾曲線(張鑫旭大神的解說
四、彈性盒子flexbox

綜合考察

一、js跨域問題

算法考察

一、有36輛自動賽車和6條跑道,沒有計時器的前提下,最少用幾回比賽能夠篩選出最快的三輛賽車?

二、一面牆,單獨工做時,A花18小時砌好,B花24小時,C花30小時,現A, B, C的順序輪流砌,每人工做1小時換班,完工時,B總共幹了多少小時?

  1. 9小時
  2. 8小時
  3. 7小時
  4. 6小時48分

答案:B,C

緣由:

按照A,BC輪流砌,沒有說明誰先開始。
1/18 + 1/24 + 1/30 = 47/360;
共同完成7小時:7*47/360 = 329/360,還差31/360;
若是A先砌:則B砌了7小時44分鐘。
若是B先砌:則B砌了8小時。
若是C先砌:則B砌了7小時。

17.語義化標籤

1)tite與h1的區別
2)b與strong的區別
3)i與em的區別
PS:不要小看這些題,80%人答不上來

title與h1的區別
定義:title是網站標題,h1是文章主題

做用:title歸納網站信息,能夠直接告訴搜索引擎和用戶這個網站是關於什麼主題和內容的,是顯示在網頁Tab欄裏的;h1突出文章主題,面對用戶,更突出其視覺效果,指向頁面主體信息,是顯示在網頁中的。

b與strong的區別
定義:b(bold)是實體標籤,用來給文字加粗,而strong是邏輯標籤,做用是增強字符語氣

區別:b標籤只是加粗的樣式,沒有實際含義,經常使用來表達無強調或着重意味的粗體文字,好比文章摘要中的關鍵詞、評測文章中的產品名稱、文章的導言; 而strong表示標籤內字符重要,用以強調,其默認格式是加粗,可是能夠經過CSS添加樣式,使用別的樣式強調。

建議:爲了符合CSS3的規範,b應儘可能少用而改用strong

i與em的區別

定義:i(italic)是實體標籤,用來使字符傾斜,而em(emphasis)是邏輯標籤,做用是強調文本內容

區別:i標籤只是斜體的樣式,沒有實際含義,經常使用來表達無強調或着重意味的斜體,好比生物學名、術語、外來語(好比「de facto」這樣的英語裏經常使用的拉丁語短語);而em表示標籤內字符重要,用以強調,其默認格式是斜體,可是能夠經過CSS添加樣式

建議:爲了符合CSS3的規範,i應儘可能少用而改用em

下面擴展一些其它的標籤屬性區別:

img中的alt與title屬性

alt屬性是在你的圖片由於某種緣由不能加載時在頁面顯示的提示信息,它會直接輸出在本來加載圖片的地方

title屬性是在你鼠標懸停在該圖片上時顯示一個小提示,鼠標離開就沒有了,有點相似jQuery的hover

src與href的區別

定義:href指定網絡資源的位置創建連接或關係,用在link和a等元素上。src將外部資源嵌入到當前標籤所在位置,如img圖片和js腳本等

區別:咱們在可替換的元素上使用src,然而把href用於在涉及的文檔和外部資源之間創建一個關係。 瀏覽器解析src屬性時,會暫停其餘資源的下載和處理,直至將該資源加載,編譯,執行完畢。 瀏覽器解析到href的時候會識別該連接內容,對其進行下載不會中止對當前文檔的處理

18.事件綁定相關

addEventListener,第三個參數是用來表示事件是以事件冒泡仍是事件捕獲這個各位都知道!可是他問的問題是:
咱們給一個dom同時綁定兩個點擊事件,一個用捕獲,一個用冒泡,你來講下會執行幾回事件,而後會先執行冒泡仍是捕獲!!!
來吧,誰能說出來。。。。

19.CSS選擇器問題

考察優先級問題,反正會出不少莫名其妙的變形,好比將style標籤寫在body後與body前有什麼區別,好比同一dom應用多個class其應該如何表現,好比class a定義顏色爲blue,class b定義顏色爲red,同時應用到dom上,dom做何顯示。。。

好吧各位去回答吧。。。。。

20.一段關於JS中this應用奇葩代碼引起的思考

function DemoFunction(){
    this.init = function(){
        var func = (function(va){
        this.va = va;
        return function(){
            va += this.va;
            return va;
        }
        })(function(va1, va2){
            var va3 = va1 + va2;
            return va1;
        }(1,2));
        
        console.log(func(20));

        this.func = func;
        console.log(this.func(100));
    }
}
var a = new DemoFunction();
a.init();

首先咱們得有以下幾個概念:

詳細解釋此段代碼

1、首先看DemoFunction的構造函數

這是代碼的重點,第一層代碼能夠縮減爲以下:

function DemoFunction(){
    this.init = function(){
        //省略代碼....
    }
}

表示爲DemoFunction的實例提供init方法(聲明:此處有誤導成份,方法應儘量放在原型連接上,也就是prototype上。),對外公開的接口。

2、在init方法中,再次省略代碼以下:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(/*省略代碼...*/);

//省略代碼....

上面代碼介紹:

  • 首先定義了一個當即執行函數,並把此函數的執行結果賦值給func。
  • 須要注意當即執行函數中this.va=va這行代碼,因爲當即執行函數沒有調用者,因此在進入可執行上下文時,this會被賦值爲Global(瀏覽器中爲window對象)。
  • 更須要注意當即執行函數,返回的是一個匿名函數,也是一個閉包,在這裏必定要注意一個問題:this是在進入可執行上下文時建立的。

3、在init方法中,注意以下代碼:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(function(va1, va2){
    var va3 = va1 + va2;
    return va1;
}(1,2));
//省略代碼....

va的實際參數是一個自執行匿名函數,這個匿名函數接受了兩個參數va1,va2,但只返回了va1。以此爲據,那麼能夠肯定va的值也就爲1。接着就執行this.va=va這句代碼,因爲當前this爲window,因此參數va的值被賦值到了window的一個叫va的屬性上。

4、在init方法中,加上輸出語句:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
    })(function(va1, va2){
        var va3 = va1 + va2;
        return va1;
    }(1,2));
    
    console.log(func(20));

    this.func = func;
    console.log(this.func(100));
}

結果分析:

  • 第一個console.log輸出的是func(20),這裏必定要注意調用者是沒有具體指定的,此時默認的就是Global(也就是widnow對象),所以輸出爲:2
  • 第二個console.log輸出的是this.func(100),能夠看到this.func與func是指向同一個函數的引用,但此時的調用者則指定爲this,也就是當前對象的實例,所以輸出爲:NaN。緣由:this(當前對象的實例)做爲調用者,在func的函數中va += this.va這句代碼中的this是指向當前對象的實例,但當前對象的實例上是沒有va屬性的。可是va是有值的,當前值爲2了。是由於閉包把va值存到內存中了。那麼如何讓第二次獲得的值也是2呢,結果很簡單,以下:
function DemoFunction(){
        this.va = 0;
        this.init = function(){
            var func = (function(va){
            this.va = va;
            return function(){
                va += this.va;
                return va;
            }
            })(function(va1, va2){
                var va3 = va1 + va2; 
                return va1;
            }(1,2));
            console.log(func(20));
            
            this.func = func;
           
            console.log(this.func(100));
        }
    }
    var a = new DemoFunction();
    a.init();
相關文章
相關標籤/搜索