慕課教程筆記-前端 js 面試技巧

課程講解思路:先列題目引發(fā)思考检盼,再詳細(xì)講解知識(shí)點(diǎn),最后解答

[TOC]

前言

關(guān)于面試

前端水平的三個(gè)層次

  • 基層工程師-基礎(chǔ)知識(shí)
  • 高級(jí)工程師-項(xiàng)目經(jīng)驗(yàn)
  • 架構(gòu)師- 解決方案

幾個(gè)面試題

題目很多,做具有代表的題目乍丈,舉一反三

  1. js 中使用 typeof 能得到哪些類型 (==js 變量類型==)
  2. 何時(shí)使用 === 何時(shí)使用 == 衙解? (==強(qiáng)制類型轉(zhuǎn)換==)
  3. window.onload 和 DOMContentLoaded 的區(qū)別 (==瀏覽器渲染過程==)
  4. 用 js 連續(xù)創(chuàng)建 10 個(gè) <a> 標(biāo)簽,點(diǎn)擊的時(shí)候彈出來對(duì)應(yīng)的序號(hào) (==作用域==)
  5. 簡述如何實(shí)現(xiàn)一個(gè)模塊加載器令野,實(shí)現(xiàn)類似 require.js 的基本功能 (==js 模塊化==)
  6. 實(shí)現(xiàn)數(shù)組的隨機(jī)排序 (==JS 基礎(chǔ)算法==)

思考

  • 拿到面試題第一時(shí)間看到的是什么 (==考點(diǎn)==)
  • 如何看待永遠(yuǎn)做不完的題海 (==以不變應(yīng)萬變==)
  • 如何對(duì)待接下來遇到的面試題舀患? (==總結(jié)考點(diǎn)并擴(kuò)展再反思題目==)

基礎(chǔ)知識(shí)

js 基礎(chǔ)三座大山

  • 原型 原型鏈
  • 作用域 閉包
  • 異步 單線程

面試題

1. js 中使用 typeof 能得到哪些類型

2. 何時(shí)使用 === 何時(shí)使用 ==

if (obj.a == null){
    // 這里相當(dāng)于 obj.a === null || obj.a ===undefined ,因?yàn)?undefined == null 值為true
    // 這是 JQuery 中推薦的寫法气破, 其余情況全部用 === (避免代碼風(fēng)險(xiǎn)有代碼潔癖)
}

3. JS 中有哪些內(nèi)置函數(shù)

4. JS 變量按照存儲(chǔ)方式區(qū)分為哪些類型聊浅,并描述其特點(diǎn)

5. 如何理解 JSON

知識(shí)點(diǎn)

  1. 變量類型:值類型 和 引用類型(指針)
  • 引用類型包括: 數(shù)組 函數(shù) 對(duì)象;引用類型公共空間,是指針
        var a=100;
        var b=a;
        a=200;
        console.log(b) //100

        var a={age:20};
        var b=a;
        b.age=21;
        console.log(a.age) //21
  1. typeof只能區(qū)分值類型的詳細(xì)類型现使,對(duì)引用類型無能為力低匙,但可以區(qū)分出函數(shù)來
        typeof undefined;//undefined
        typeof 'abc';//string
        typeof 123;//number
        typeof true;//boolean
        typeof {};//object
        typeof [];//object
        typeof null;//object
        typeof console.log//function
  1. 強(qiáng)制類型轉(zhuǎn)換(值類型的計(jì)算)

    • ①字符串拼接
    • ②==運(yùn)算符
    • ③if語句
    • ④邏輯運(yùn)算 (布爾操作符 邏輯非、邏輯與碳锈、邏輯或)
      • 邏輯非 顽冶! (結(jié)果總是 true/fasle )
        • 如果操作數(shù)是一個(gè)對(duì)象,返回 false
      • 邏輯與 &&
        • ==如果第一個(gè)操作是對(duì)象則返回第二個(gè)操作數(shù)==
        • 如果第二個(gè)操作數(shù)是對(duì)象殴胧,則只有在第一個(gè)操作數(shù)的求值結(jié)果為 true 的情況下才會(huì)返回該對(duì)象
        • 如果兩個(gè)操作數(shù)都是對(duì)象渗稍,則返回第二個(gè)操作數(shù)
        • 如果第一個(gè)操作數(shù)是 null,則返回 null
        • 如果第一個(gè)操作數(shù)是 NaN团滥,則返回 NaN
        • 如果第一個(gè)操作數(shù)是 undefined 竿屹,則返回 undefined存璃。
        • 邏輯與操作符屬于斷路操作玉罐,如果第一個(gè)操作符能夠決定結(jié)果坯台,那么就不會(huì)再對(duì)第二個(gè)操作數(shù)求值默赂。
      • ==邏輯或 ||==
        • 如果第一個(gè)操作數(shù)是對(duì)象叛拷,則返回第一個(gè)操作數(shù)
        • 如果兩個(gè)操作數(shù)都是對(duì)象趾唱,則返回第一個(gè)操作數(shù)
        • 如果第一個(gè)操作數(shù)的求值結(jié)果為 false 奴璃,則返回第二個(gè)操作數(shù)
        • 如果兩個(gè)操作數(shù)都是 NaN/null/undefined 瞒滴,則返回 NaN/null/undefined

上面四種操作可能導(dǎo)致強(qiáng)制類型轉(zhuǎn)換

       var a=100+10;//110
       var b=100+'10'//'10010'

       100 =='100'//true
       0==''//true
       null==undefined//true

       var a=true;
       if(a){
          //...
       }
       var b=100;
       if(b){
          //...
       }
       var c='';
       if(c){
          //...
       } 

       console.log(10&&0)//0
       console.log(''||'abc')//abc
       console.log(!window.abc)//true
       
       var a=100;
       console.log(!!a)//true

面試題解答 1

    面試題1、JS中使用typeof能得到的哪些類型哮缺?
            typeof undefined;//undefined
            typeof 'abc';//string
            typeof 123;//number
            typeof true;//boolean
            typeof {};//object
            typeof [];//object
            typeof null;//object
            typeof console.log//function

            typeof只能區(qū)分值類型的詳細(xì)類型弄跌,對(duì)引用類型無能為力,但可以區(qū)分出函數(shù)來
     面試題2尝苇、何時(shí)使用===何時(shí)使用==铛只?
            if(obj.a==null){
                //這里相當(dāng)于obj.a===null||obj.a===undefined,簡寫形式
                //這是jquery源碼中推薦的方法,其他的都用===
            }
     面試題3糠溜、JS中有哪些*內(nèi)置函數(shù)*--數(shù)據(jù)封裝類對(duì)象淳玩?
          //JS作為單純語言的內(nèi)置函數(shù)
            Object
            Array
            Boolean
            Number
            String
            Function
            Date
            RegExp
            Error
            //Global瀏覽器內(nèi)置對(duì)象
            //Math是對(duì)象,不是函數(shù)
     面試題4非竿、JS變量按照存儲(chǔ)方式區(qū)分為哪些類型蜕着,并描述其特點(diǎn)
            //分為值類型和引用類型
            //值類型
            var a=10
            var b=a
            a=11
            console.log(b)//10

            //引用類型
            var obj1={x:100}
            var obj2=obj1
            obj1.x=200
            console.log(obj2.x)//200
            值類型直接存儲(chǔ)的是值
            引用類型存儲(chǔ)的是指向值的指針,這樣做是為了節(jié)省內(nèi)存
            值類型的值賦值后不會(huì)相互干預(yù)
            引用類型的賦值是變量指針的賦值红柱,不是真的值的拷貝承匣,他們的賦值是相互干預(yù)的。
     面試題5锤悄、如何理解JSON?
            //JSON只不過是一個(gè)JS對(duì)像而已悄雅,和MATH一樣
            JSON.stringfy({a:10,b:20})
            JSON.parse('{"a":10,"b":20}')
            //注意:JS中為false的為 0 NaN null undefined '' false

原型和原型鏈

  *構(gòu)造函數(shù)*
     function Foo(name,age){
        this.name=name;
        this.age=age;
        this.class="class-1";
        //return this;//默認(rèn)有這一行
     }
     var f=new Foo('zhangsan',20)
     var f1=new Foo('lisi',22)//創(chuàng)建多個(gè)對(duì)象
     //new對(duì)象時(shí)函數(shù)中的this初始化為空對(duì)象,參數(shù)賦值完后返回this給f和f1
  *構(gòu)造函數(shù)--擴(kuò)展*
     var a={}其實(shí)是var a=new Object()的語法糖
     var a=[]其實(shí)是var a=new Array()的語法糖
     function Foo(){...}其實(shí)是var Foo=new Function(...)
     //使用instanceof判斷一個(gè)函數(shù)是否是一個(gè)變量的構(gòu)造函數(shù)
     //對(duì)象铁蹈,數(shù)組,函數(shù)的構(gòu)造函數(shù)其實(shí)是Object,Array,Function
     //判斷一個(gè)變量是否是'數(shù)組'  變量 instanceof Array   

原型規(guī)則(是學(xué)習(xí)原型鏈的基礎(chǔ))

  • 所有的引用類型(數(shù)組众眨,對(duì)象握牧,函數(shù)),都具有對(duì)像特性娩梨,即可自由擴(kuò)展屬性(除了null)
  • 所有的引用類型(數(shù)組沿腰,函數(shù),對(duì)象)狈定,都有一個(gè) _proto_ 屬性颂龙,屬性值是一個(gè)普通對(duì)象
  • 所有的函數(shù),都有一個(gè) prototype 屬性纽什,屬性值也是一個(gè)普通的對(duì)象
  • 函數(shù)的 prototype 稱顯式原型措嵌,引用類型的 _proto 成為隱式原型
  • 所有的引用類型(數(shù)組,函數(shù)芦缰,對(duì)象)企巢,其 _proto_ 屬性值都指向其構(gòu)造函數(shù)的 prototype 屬性值
  • 當(dāng)試圖獲取一個(gè)對(duì)象的某個(gè)屬性時(shí),如果這個(gè)對(duì)象本身沒有這個(gè)屬性让蕾,那么會(huì)去它的_prot__(即它的構(gòu)造函數(shù)的prototype)
image
         var obj={};obj.a=100;
         var arr=[];arr.a=100;
         function fn(){}
         fn.a=100;

         console.log(obj.__proto__);
         console.log(arr.__proto__);
         console.log(fn.__proto__);

         console.log(fn.prototype)

         console.log(obj.__proto__===Object.prototype)


        function Foo(name,age){
            this.name=name;
        }             
        Foo.prototype.alertName=function(){
             alert(this.name)
        }
        var f=new Foo('zhangsan');
        f.printName=function(){
            console.log(this.name);
        }
        f.printName();
        f.alertName();

        //循環(huán)對(duì)象自身的屬性
        var item;
        for(item in f){
          //高級(jí)瀏覽器已經(jīng)在for in中屏蔽了來自原型的屬性
          //但是這里建議大家還是加上這個(gè)判斷浪规,保證程序的健壯性
          if(f.hasOwnProperty(item))
              console.log(item);
        }

  *原型鏈*
     f.toString()//要去f.__proto__.__proto__中去找
  *instanseof*
     **注意:** //用于判斷引用類型屬于哪個(gè)構(gòu)造函數(shù)的方法
      f instanceof Foo的判斷邏輯是:
         f的__proto__一層一層向上找或听,能否對(duì)應(yīng)到Foo.prototype
      f instanceof Object也是正確的

面試題解答 2

面試題1、如何準(zhǔn)確判斷一個(gè)變量時(shí)數(shù)組類型笋婿?
           var arr=[]
           arr instanceof Array //true
           typeof arr//object,typeof是無法判斷是否是數(shù)組的
    面試題2誉裆、寫一個(gè)原型鏈繼承的例子
       ①function Animal(){
          this.eat=function(){
             console.log('animal eat');
          }
       }
       function Dog(){
          this.bark=function(){
             console.log('dog bark')
          }
       }
       Dog.prototype=new Animal();
       var hashiqi=new Dog()

       ②function Elem(id){
           this.elem=document.getElementById(id);
       }
       Elem.prototype.html=function(val){
          var elem=this.elem;
          if(val){
              elem.innerHTML=val;
              return this;//鏈?zhǔn)讲僮?          }else{
             return elem.innerHTML;
          }
       }
      Elem.prototype.on=function(type,fn){
         var elem=this.elem;
         elem.addEventListener(type,fn);
         return this;
      }
      var elem=new Elem("div1");
      elem.html("<p>hello world</p>").on("click",function(){alert("clicked")}).html("<p>javascript</p>");
    面試題3、描述new一個(gè)對(duì)象的過程
       ①創(chuàng)建一個(gè)新對(duì)象
       ②this指向這個(gè)新對(duì)象
       ③執(zhí)行代碼缸濒,即對(duì)this賦值
       ④返回this
    面試題4足丢、zepto(或其他框架)源碼中如何使用原型鏈
       ①閱讀源碼是高效提高技能的方式
       ②但不能“埋頭苦鉆”有技巧在其中
       ③慕課網(wǎng)搜索“zepto設(shè)計(jì)和源碼分析”

執(zhí)行上下文

js 是解釋型語言不是編譯型語言,所以有些錯(cuò)誤在編寫程序時(shí)不會(huì)報(bào)錯(cuò)绍填,什么時(shí)候執(zhí)行什么時(shí)候報(bào)錯(cuò)

  • 范圍:一段<script>或者一個(gè)函數(shù)之內(nèi)都會(huì)生成一個(gè)上下文
  • 全局:變量定義霎桅,函數(shù)聲明 //執(zhí)行之前,一段<script>會(huì)生成全局上下文
  • 函數(shù):變量定義讨永,函數(shù)聲明滔驶,this,arguments //函數(shù)執(zhí)行之前會(huì)生成函數(shù)上下文
  • 注意:‘函數(shù)聲明’和‘函數(shù)表達(dá)式’的區(qū)別
    console.log(a);//undefined
    var a=100

    fn('zhangsan') //'zhangsan' 20
    function fn(name){
       age=20;
       console.log(name,age);
       var age;
    }

this

  • this要在執(zhí)行時(shí)才能確認(rèn)值卿闹,定義時(shí)無法確認(rèn)
    var a={
       name:"A",
       fn:function(){
           console.log(this.name)
       }
    }
    a.fn()  //this===a
    a.fn.call({name:B}) //this==={name:'B'}
    var fn1=a.fn;
    fn1() //this===window

    使用場景
    ①作為構(gòu)造函數(shù)執(zhí)行
       function Foo(name){
          //this={};
          this.name=name;
          //return this
       }
       var f=new Foo('zhangsan')
    ②作為對(duì)象屬性執(zhí)行
        var obj={
            name:'A',
            printName:function(){
                console.log(this.name)
            }
        }
        obj.printName();
    ③作為普通函數(shù)執(zhí)行
       function fn(){
          console.log(this)  //this===window
       }
       fn()
    ④call apply bind
       function fn1(name,age){
          alert(name);
          console.log(this)  //this===window
       }
       fn1.call({x:100},'zhangsan',20)
       fn1.apply({x:100},['zhangsan',20])
       var fn2=function(name,age){
          alert(name);
          console.log(this)  //this==={x:100}
       }.bind({x:100})//bind只能用函數(shù)表達(dá)式揭糕,函數(shù)聲明不可用,會(huì)報(bào)錯(cuò)
       fn2('zhangsan',200)

作用域

       ①?zèng)]有塊級(jí)作用域
            if(true){
                var name='zhangsan'
            }
            console.log(name)//'zhangsan'
       ②只有全局和函數(shù)作用域
            var a=100;
            function fn(){
                var a=200锻霎;
                console.log('fn',a)
            }
            console.log('global',a)
            fn()

作用域鏈

       var a=100
       function fn(){
               var b=200
               //當(dāng)前作用域沒有定義的變量著角,即'自由變量'
               console.log(a)

               console.log(b)
       }
       fn()


       var a=100;
       function F1(){
          var b=200;
          function F2(){
              var c=300;
              console.log(a);//a是自由變量
              console.log(b);//b是自由變量
              console.log(c);
          }
          F2()
       }
       F1();

  • ==注意==:函數(shù)的父級(jí)作用域是函數(shù)定義時(shí)候的作用域,不是函數(shù)執(zhí)行時(shí)候的作用域,也就是說那個(gè)作用域定義了這個(gè)函數(shù)旋恼,這個(gè)函數(shù)的父級(jí)作用域就是誰吏口,跟函數(shù)執(zhí)行沒有關(guān)系,函數(shù)自由變量要到父級(jí)作用域中找冰更,就形成了作用域鏈

閉包

  1. 實(shí)際開發(fā)中閉包的應(yīng)用:封裝變量产徊,收斂權(quán)限
     function F1(){
          var a=100;
          //返回一個(gè)函數(shù)(函數(shù)作為返回值)
          return function(){
              console.log(a);//自由變量,父作用域?qū)ふ?          }
     }
     //f1得到一個(gè)函數(shù)
     var f1=F1();
     var a=200;
     f1();//100


     閉包使用場景
     ①函數(shù)作為返回值
     ②函數(shù)作為參數(shù)傳遞(函數(shù)自由變量要到父級(jí)作用域中找)
       function F1(){
          var a=100;
          return  function(){
              console.log(a);
          }
       }
       var f1=F1();
       function F2(fn){
           var a=200
           fn();(自由變量要到聲明定義時(shí)的父作用域中找蜀细,和執(zhí)行的作用域沒有關(guān)系)
       }
       F2(f1);//100

面試題解答 3

問題1舟铜、說一下對(duì)變量提升的理解
            ①變量的定義
            ②函數(shù)的聲明(注意和函數(shù)表達(dá)式的區(qū)別)
      問題2、說明this幾種不同的使用場景
             參考上文**this**
      問題3奠衔、創(chuàng)建10個(gè)`<a>`標(biāo)簽谆刨,點(diǎn)擊的時(shí)候彈出來對(duì)應(yīng)的序號(hào)
            var i;
            for(i=0;i<10;i++){
            (function(i){
               var a=document.createElement('a');
               a.innerHTML=i+'<br>';
               a.addEventListener('click',function(e){
               e.preventDefault();
               alert(i);
              })
              document.body.appendChild(a);
              })(i);//相當(dāng)于創(chuàng)建了10個(gè)函數(shù)
            }

      問題4、如何理解作用域
         ①自由變量
         ②作用域鏈归斤,即自由變量的查找
         ③閉包的兩個(gè)場景
      問題5痊夭、實(shí)際開發(fā)中閉包的應(yīng)用
      //閉包實(shí)際應(yīng)用中主要用于封裝變量,收斂權(quán)限
      function isFirstLoad(){
             var _list=[];
              return function(id){
                 if(_list.indexOf(id)>=0){
                     return false;
                 }else{
                    _list.push(id);
                    return true;
                 }
              }
      }
      //使用
      var firstLoad=isFirstLoad();
      firstLoad(10);
      firstLoad(10);
      firstLoad(20);
    //你在 isFirstLoad 函數(shù)外面官册,根本不可能修改掉_list的值

異步

何時(shí)需要異步

  • ①在可能發(fā)生等待的情況下
  • ②等待過程中不能像alert一樣阻塞程序運(yùn)行
  • ③因此生兆,所以的”等待的情況”都需要異步

前端使用異步的場景

  • ①定時(shí)任務(wù):setTimeout,setInterval
  • ②網(wǎng)絡(luò)請(qǐng)求:ajax請(qǐng)求,動(dòng)態(tài)加載
  • ③事件綁定
console.log(100) 
setTimeout(function(){ 
console.log(200) 
},1000) 
console.log(300) //100 300 200

異步示例

console.log('start');
$.get('./data1.json',function(data1){
       console.log(data1);
})
console.log('end')//'start'  'end'   data1



console.log(start);
var img=document.createElement('img')
img.onload=function(){
        console.log('loaded')
}//圖片加載完執(zhí)行
img.src='/xx.png';
console.log('end');//start end loaded


console.log('start')
document.getElementById('btn1').addEventListener('click',function(){
       alert('clicked');
})//點(diǎn)擊時(shí)才會(huì)執(zhí)行
console.log('end');//start clicked end

同步

console.log(100)
alert(200);
console.log(300)  //100 200 300

異步和單線程

js 是單線程的語言鸦难,所以需要異步

console.log(100) 
setTimeout(function(){ 
console.log(200) 
}) 
console.log(300) //100 300 200 

上述異步代碼的執(zhí)行過程如下

  1. 執(zhí)行第一行打印100
  2. setTimeout 異步執(zhí)行根吁,先暫存起來
  3. 打印 300
  4. 待所有程序執(zhí)行完,處于空閑狀態(tài)時(shí)合蔽,拿到暫存的函數(shù)在指定的時(shí)間后執(zhí)行

面試解答 4

問題1击敌、同步和異步的區(qū)別是什么?分別舉一個(gè)同步和異步的例子 
①同步會(huì)阻塞代碼執(zhí)行拴事,而異步不會(huì) 
②alert是同步沃斤,setTimeout是異步

問題2、一個(gè)關(guān)于setTimeout的筆試題 
console.log(1) 
setTimeout(function(){ 
console.log(2) 
},0) 
console.log(3) 
setTimeout(function(){ 
console.log(4) 
},1000) 
console.log(5) 
//1 3 5 2 4

問題3刃宵、前端使用異步的場景有哪些 
①定時(shí)任務(wù):setTimeout衡瓶,setInterval 
②網(wǎng)絡(luò)請(qǐng)求:ajax請(qǐng)求,動(dòng)態(tài)加載 
③事件綁定

其他(日期牲证、Math哮针、各種常用API)

①日期 
Date.now()  //獲取當(dāng)前時(shí)間毫秒數(shù) 
var dt=new Date() 
dt.getTime()   //獲取毫秒數(shù) 
dt.getFullYear()   //年
 dt.getMonth()  //月
(0-31) dt.getHours()   //小時(shí)(0-23) 
dt.getMinutes() //分鐘(0-59) 
dt.getSeconds() //(0-59)

②Math 
Math.random()
random 在實(shí)際中的應(yīng)用有清除緩存的作用,是每次訪問到的都不是緩存

③數(shù)組API
forEach  遍歷所有元素
  var arr=[1,2,3]
     arr.forEach(function(item,index){
     //遍歷數(shù)組的所有元素
     console.log(index,item)
  })

 every  判斷所有元素是否都符合條件
   var arr=[1,2,3]
   var result=arr.every(function(item,index){
      //用來判斷所有的數(shù)組元素坦袍,都滿足一個(gè)條件
        if(item<4){
           return true;
        }
    })
   console.log(result);

some  判斷是否至少一個(gè)元素符合條件
    var arr=[1,2,3]
    var result=arr.some(function(item,index){
      //用來判斷所有的數(shù)組元素十厢,只要有一個(gè)滿足條件即可
        if(item<2){
            return true;
       }
    })
    console.log(result);

sort  排序
   var arr=[1,4,2,3,5]
   var arr2=arr.sort(function(a,b){
         //從小到大排序
         return a-b
         //從大到小排序
         //return b-a
   })
   console.log(arr2)

map  對(duì)元素重新組裝,生成新數(shù)組
   var arr=[1,2,3,4]
   var arr2=arr.map(function(item,index){
        //將元素重新組裝捂齐,并返回
        return '<b>'+item+'</b>'
   })
   console.log(arr2)
filter過濾符合條件的元素
   var arr=[1,2,3]
   var arr2=arr.filter(function(item,index){
       //通過某一個(gè)條件過濾數(shù)組
       if(item>=2){
          return true;
       }
   })
   console.log(arr2)
④對(duì)象API
   var obj={
      x:100,
      y:200,
      z:300
   }
   var key
   for(key in obj){
      //注意這里的hasOwnProperty,再講原型鏈時(shí)講過了
      if(obj.hasOwnProperty(key)){
             console.log(key,obj[key])
      }

    }

面試題解答 5

問題1蛮放、獲取2017-06-10格式的日期 
     function formatDate(dt){
          if(!dt){
              dt=new Date()
          }
          var year=dt.getFullYear();
          var month=dt.getMonth()+1;
          var date=dt.getDate();
          if(month<10){
             //強(qiáng)制類型轉(zhuǎn)換
             month="0"+month;
          }
          if(date<10){
              //強(qiáng)制類型轉(zhuǎn)換
              date="0"+month;
          }
          return year+"-"+month+"-"+date
     }
     var dt=new Date()
     var formatDate=formatDate(dt)
     console.log(formatDate)
問題2、獲取隨機(jī)數(shù)奠宜,要求是長度一直的字符串格式 
      var random=Math.random()
      var random=random+'0000000000'   //后面加上10個(gè)零
      var random=random.slice(0,10)
      console.log(random)
問題3包颁、寫一個(gè)能遍歷對(duì)象和數(shù)組的通用forEach函數(shù)
       function forEach(obj,fn){
           var key
           //準(zhǔn)確判斷是不是數(shù)據(jù)
           if(obj instanceof Array){
                  obj.forEach(function(item,inex){
                         fn(index,item)
                 })
           }else{
                //不是數(shù)組就是對(duì)象
                for(key in obj){
                     fn(key,obj[key])
                }
           }
       }

       var arr=[1,2,3];
       //注意,這里參數(shù)的順序換了压真,為了和對(duì)象的遍歷格式一致
       forEach(arr,function(index,item){
             console.log(index,item)
       })

       var obj={x:100,y:200};
       forEach(obj,function(key,value){
             console.log(key,value)
       })

js-web-api

本期主要內(nèi)容

  1. Dom操作
  2. Bom操作
  3. 事件綁定
  4. Ajax請(qǐng)求(包括http協(xié)議)
  5. 存儲(chǔ)

注意:內(nèi)置函數(shù)和內(nèi)置對(duì)象的區(qū)別

  1. 內(nèi)置函數(shù):Object Array RegExp Function Error Date Number Boolean String…
  2. 內(nèi)置對(duì)象:Math JSON…

注:

  • JS基礎(chǔ)知識(shí):ECMA 262標(biāo)準(zhǔn)
  • JS-WEB-API:W3C標(biāo)準(zhǔn)徘六,它參與規(guī)定任何JS基礎(chǔ)相關(guān)的東西,不管什么變量類型榴都、原型、作用域和異步漠其,只管定義用于瀏覽器JS操作頁面的API和全局變量

DOM

  • html是xml的一種特殊結(jié)構(gòu)

  • DOM 本質(zhì):
    DOM 可以理解為:
    瀏覽器把拿到的html代碼嘴高,結(jié)構(gòu)化一個(gè)瀏覽器能識(shí)別并且js可操作性的一個(gè)模型而已

①獲取DOM節(jié)點(diǎn) 
var div1=document.getElementById(‘div1’);//元素 
var divList=document.getElementsByTagName(‘div’); //集合 
console.log(divList.length) 
console.log(divList[0])

var containerList=document.getElementsByClassName(“.contaner”)//集合 
var pList=document.querySelectorAll(‘p’)//集合 
②property 
var pList=document.querySelectorAll(‘a(chǎn)ll’); 
var p=pList[0]; 
console.log(p.style.width) 
p.style.width=’100px’ 
console.log(p.className) 
p.className=’p1’

//獲取nodeName和nodeType 
console.log(p.nodeName) 
console.log(p.nodeType) 

  • DOM 結(jié)構(gòu)操作
    • 新增節(jié)點(diǎn)
    • 查詢子節(jié)點(diǎn)
    • 查詢父節(jié)點(diǎn)
    • 刪除節(jié)點(diǎn)

面試題解答 6

問題1和屎、dom是哪種基本的數(shù)據(jù)結(jié)構(gòu)拴驮? 
樹 
問題2、Dom操作的常用API有哪些柴信? 
①獲取DOM節(jié)點(diǎn)套啤,以及節(jié)點(diǎn)的property和Attribute 
②獲取父節(jié)點(diǎn),獲取子節(jié)點(diǎn)  childNodes/ parentNode
③新增節(jié)點(diǎn)随常,刪除節(jié)點(diǎn) 
問題3潜沦、Dom節(jié)點(diǎn)的Attribute和Property有和區(qū)別萄涯? 
①property只是一個(gè)JS對(duì)象的屬性的修改 
②Attribute是對(duì)html標(biāo)簽屬性的修改

BOM操作

  • 測試瀏覽器型號(hào) navigator
var ua=navigator.userAgent 
var isChrome=ua.indexOf(‘Chrome’) 
console.log(isChrome) 

  • screen
  • location
  • history
console.log(screen.width) 
console.log(scr)

console.log(location.href) 
console.log(location.protocal) 
console.log(location.pathname) 
console.log(location.search) 
console.log(location.hash)

history.back() 
histort.forward()

面試題解答 7

題目1、如何檢測瀏覽器的類型 
var ua=navigator.userAgent 
var isChrome=ua.indexOf(‘Chrome’) 
console.log(isChrome) 
題目2唆鸡、拆解url的各部分 
參考location

事件

  • 通用事件綁定
var btn=document.getElementById(‘btn1’); 
btn.addEventListener(‘click’,function(event){ 
console.log(‘clicked’) 
})

function bindEvent(elem,type,fn){ 
elem.addEventListener(type,fn) 
}

var a=document.getElementById(‘link1’) 
bindEvent(a,’click’,function(e){ 
e.preventDefault() //阻止默認(rèn)行為 
alert(‘clicked’) 
})

注:關(guān)于IE低版本的兼容性 
①IE低版本使用attachEvent綁定事件涝影,和W3C標(biāo)準(zhǔn)不一樣 
②IE低版本使用量以非常少,很多網(wǎng)站都早已不支持 
建議對(duì)IE低版本的兼容性:了解即可争占,無需深究 
如果遇到對(duì)IE低版本要求苛刻的面試燃逻,果斷放棄

事件冒泡

在父級(jí) div 中定義的事件,會(huì)在子級(jí)的事件執(zhí)行之后冒泡上來執(zhí)行

  • 阻止事件冒泡 e.stopPropagation()
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="div1">
      <p id="p1">激活</p>
      <p id="p2">取消</p>
      <p id="p3">取消</p>
      <p id="p4">取消</p>
    </div>
    <div id="div2">
      <p id="p5">取消</p>
      <p id="p6">取消</p>
    </div>


    <script type="text/javascript">
    // 利用阻止冒泡的機(jī)制實(shí)現(xiàn):只點(diǎn)擊 p1 的時(shí)候彈窗激活
      function bindEvent(elem,type,func) {
        elem.addEventListener(type,func)
      }
      var p1 = document.getElementById('p1')
      bindEvent(p1,'click',function(e){
        e.stopPropagation()
        alert('激活')
      })
      bindEvent(body,'click',function (e) {
        alert('取消')
      })
    </script>
  </body>
</html>
  • 代理
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="div1">
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
      <p>fjdk</p>
      <h1>jfkd</h1>
      <!-- ...隨時(shí)會(huì)新增更多的 a 標(biāo)簽 -->
    </div>
    <script type="text/javascript">
      // 要求用代理的方式實(shí)現(xiàn) 動(dòng)態(tài)事件綁定臂痕,綁定 div1 中的所有 a 標(biāo)簽
      var div = document.getElementById('div1')
      function bindEvent(elem,type,func) {
        elem.addEventListener(type,func)
      }
      bindEvent(div,'click',function(e){
        console.log(e) // MouseEvent
        console.log(e.target) //  完整的 a 標(biāo)簽 對(duì)象 <a href="#">a3</a>
        console.log(e.target.nodeName); // 都是大寫
        if(e.target.nodeName === 'A'){
          alert(e.target.innerHTML)
        }
      })
    </script>
  </body>
</html>

面試題解答 8

問題1伯襟、編寫一個(gè)通用的事件監(jiān)聽函數(shù) bind Event

問題2、描述事件冒泡流程 
①DOM樹形結(jié)構(gòu) 
②事件冒泡 
③阻止冒泡 
④冒泡的應(yīng)用(代理) 
問題3握童、對(duì)于一個(gè)無線下拉加載圖片的頁面姆怪,如何給每個(gè)圖片綁定事件 
①使用代理 
②知道代理的兩個(gè)優(yōu)點(diǎn) 
代碼簡潔 
減少瀏覽器內(nèi)存占用

ajax

// 指定了請(qǐng)求目標(biāo),也明確了如何處理之后舆瘪,就可以發(fā)送請(qǐng)求了
var request = new XMLHttpRequest();
request.open('GET',url,true);// 指定請(qǐng)求目標(biāo)片效,三個(gè)參數(shù),1.GET or POST 2.請(qǐng)求路徑 3.是否異步 (默認(rèn)true英古,可以不寫)
request.onreadystatechange() = function(){

    if(request.readyState === 4){
        // 請(qǐng)求完成
        if(request.status === 200){
            // 請(qǐng)求成功淀衣,獲得一個(gè)成功的響應(yīng),此后可以開始請(qǐng)求成功后的處理
            request.responseText//responseText 保存文本字符串格式
            request.responseXML//responseXML 保存 Content-Type 頭部中指定為 "text/html" 的數(shù)據(jù)
        }else{
            // 請(qǐng)求失敗,根據(jù)響應(yīng)碼判斷失敗原因
            console.log('error,status:'+request.status)
        }
    }else{
        // 請(qǐng)求還在繼續(xù)
    }
}

注:IE兼容性問題

  • ①IE低版本使用ActiveXObject召调,和W3C標(biāo)準(zhǔn)不一樣
  • ②IE低版本使用量非常少膨桥,很多網(wǎng)站都早已不支持
  • ③建議對(duì)IE低版本的兼容性了解即可,無需深究
  • ④如果遇到對(duì)IE低版本要求苛刻的面試唠叛,果斷放棄

http 狀態(tài)碼

0-(未初始化)還沒有調(diào)用send()方法 
1-(載入)已調(diào)用send()方法只嚣,正在發(fā)送請(qǐng)求 
2-(載入完成)send()方法執(zhí)行完成,已經(jīng)接收得到全部響應(yīng)內(nèi)容 
3-(交互)正在解析響應(yīng)內(nèi)容 
4-(完成)響應(yīng)內(nèi)容解析完成艺沼,可以在客戶端調(diào)用了

2xx-表示成功處理請(qǐng)求册舞。如200 
3xx-需要重定向,瀏覽器直接跳轉(zhuǎn) 
4xx-客戶端請(qǐng)求錯(cuò)誤障般,如404 
5xx-服務(wù)器端錯(cuò)誤调鲸,如500

跨域

  • 什么是跨域
  • JSONP
  • 服務(wù)器端設(shè)置http header

存儲(chǔ)

  • cookie
  • localStorage
  • sessionStorage

==區(qū)別:==

  1. 容量 cookie 只有 4 kb localStorage 最大 5MB
  2. 是否會(huì)攜帶到 ajax 中
  3. API 易用性

開發(fā)環(huán)境

前端工程師 IDE

  • webstorm
  • sublime
  • vscode
  • atom (小清新)

Git 版本管理

  • 正式項(xiàng)目都需要版本管理,可以清晰的看到歷史版本
  • 多人協(xié)作開發(fā)
  • Git 和 Linux 是一個(gè)作者

網(wǎng)絡(luò) Git 服務(wù)器

  • github
  • coding.net(國內(nèi))
  • 碼云

常用 git 基本命令

前端構(gòu)建工具

  • grunt
  • gulp
  • fis3
  • webpack

webpack

linux 基礎(chǔ)命令

1. mkdir a      // 在當(dāng)前目錄中創(chuàng)建一個(gè)空文件夾'a'
2. ls           // 查看當(dāng)前目錄下的文件
3. ll           // ls -l 的簡寫
4. cd a         // 進(jìn)入當(dāng)前目錄下的 a 目錄
5. pwd          // 查看當(dāng)前目錄的路徑
6. cd ..        // 返回上層目錄
7. rm -rf a     // 刪除文件夾 a
8. vi a.js      // 或者 vim 藐石;編輯 a.js 文件,寫入新的內(nèi)容并保存則會(huì)創(chuàng)建定拟;鍵入 i 進(jìn)入插入模式于微,ESC 返回剛剛的模式 :w 保存 :q 退出 :wq 保存并退出
9. cp a.js a1.js  // 拷貝 a.js 存入 a1.js 
10. mv a1.js <new dir>  // 將 a1.js 移動(dòng)到新的文件夾下
11. rm a.js         // 刪除 a.js
12. cat a.js    // 查看 a.js 
13. head a.js   // 查看頭部內(nèi)容
14. tail a.js   // 查看尾部內(nèi)容
15. head -n 1 a.js   // 查看第一行
16. tail -n 2 a.js   // 查看后兩行
16. grep '2' a.js    // 搜索 包含 '2'

性能優(yōu)化

原則

  • 多使用內(nèi)存,緩存或者其他
  • 減少 CPU 計(jì)算,減少網(wǎng)絡(luò)請(qǐng)求

從哪里入手

  • (加載資源)頁面資源如何加載更快
    • 靜態(tài)資源的壓縮合并(多個(gè)js文件合成一個(gè)js文件株依,減少請(qǐng)求)壓縮代碼減少體積
    • 使用靜態(tài)資源緩存
    • 使用 CDN 讓資源加載更快
    • 使用 SSR 后端渲染驱证,讓數(shù)據(jù)直接輸出到 HTML 中
  • 對(duì)于頁面的渲染以及動(dòng)態(tài)操作如何更快
    • CSS 放前面,JS 放后面
    • 懶加載(圖片懶加載勺三,下載加載)
    • 減少 DOM 查詢雷滚,對(duì) DOM 查詢做緩存
    • 減少 DOM 操作,多個(gè)操作盡量合并在一起執(zhí)行
    • 事件節(jié)流

幾個(gè)示例


// 1. 懶加載,頁面首次渲染先加載一個(gè)預(yù)覽圖吗坚,再用用DOM操作改變其真實(shí)需要加載的圖片

<img id = 'img1' src="preview.png" data-relsrc="abc.png"/>
<script>
    var img1 = document.getElementById('img1')
    img1.src = img1.getAttribute('data-realsrc')
</script>


// 2. 緩存 DOM 查詢

<script>    
var i
for(i = 0;i<document.getElementsByTagName('p').length;i++){
    // 每次循環(huán)都得執(zhí)行一次 DOM 查詢
}

// 緩存 DOM 查詢是這樣的
var pList = document.getElementById('p')
var i
for(i = 0;i<pList.length;i++){
    //TODO
}

// 3. 合并 DOM 插入
var listNode = document.getElementById('list')

// 要插入 10 個(gè) li 標(biāo)簽
var frag = document.createDocumentFragment()
var i,li
for(i = 0; i < 10; i++){
    li = document.createElement('li')
    li.innerHTML = "list item " + i
    frag.appendChild(li)
}

listNode.appendChild(frag)// 插入不是本身而是所有子孫節(jié)點(diǎn)

// 3. 事件節(jié)流
var textarea = document.getElementById('text')
var timeoutId
textarea.addEventListener('keyup',function{
    if(timeoutId){
        clearTimeout(timeoutId)
    }
    timeoutId = setTimeout(function(){
        // 觸發(fā) change 事件
    },100)
</script>

window.load

頁面的全部資源加載完成才會(huì)執(zhí)行

document.DOMContentLoaded

DOM 渲染完成即可執(zhí)行祈远,此時(shí)圖片,視頻還可能沒有加載完

安全性(了解)

  • XSS (Cross Site Scripting) 跨站請(qǐng)求攻擊
    • 舉例:博客文章中嵌入 script 標(biāo)簽商源,獲取閱讀者的 cookie 信息
    • 解決辦法: 前端替換關(guān)鍵字或者后端替換车份,后端替換的效率高
  • XSRF(Cross-site request forgery) 跨站請(qǐng)求偽造
    • 增加驗(yàn)證流程,指紋牡彻,密碼扫沼,短信等

面試技巧

  • 好看的簡歷,項(xiàng)目經(jīng)歷(貼上==定期維護(hù)==的博客庄吼,個(gè)人開源項(xiàng)目)
  • 簡歷不可造假缎除,貼上的都應(yīng)在能力范圍內(nèi),造假很容易出破綻
  • 如何看待加班总寻,救急 不救 窮
  • 遇到不會(huì)回答的問題器罐,說出知道的部分也可以,轉(zhuǎn)一下問題的也比回答“不知道”好
  • 談?wù)勅秉c(diǎn):說一下最近學(xué)習(xí)的東西
  • 面試過程中面試官傾向于問怎么實(shí)現(xiàn)的渐行,對(duì)于不知道怎么實(shí)現(xiàn)的用法要謹(jǐn)慎說明轰坊,類似 jquery 某個(gè)用法,只知道用法不知道原理很容易被問住
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祟印,隨后出現(xiàn)的幾起案子肴沫,更是在濱河造成了極大的恐慌,老刑警劉巖蕴忆,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驻襟,死亡現(xiàn)場離奇詭異,居然都是意外死亡减牺,警方通過查閱死者的電腦和手機(jī)拔疚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門栋艳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吸占,“玉大人矾屯,你說我怎么就攤上這事初厚∨抛鳎” “怎么了妄痪?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵拌夏,是天一觀的道長障簿。 經(jīng)常有香客問我,道長西篓,這世上最難降的妖魔是什么岂津? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任橱乱,我火速辦了婚禮泳叠,結(jié)果婚禮上危纫,老公的妹妹穿的比我還像新娘种蝶。我一直安慰自己蛤吓,他們只是感情好会傲,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泼疑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪会油。 梳的紋絲不亂的頭發(fā)上翻翩,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音桨仿,去河邊找鬼服傍。 笑死伴嗡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阱扬。 我是一名探鬼主播麻惶,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杀迹?” 一聲冷哼從身側(cè)響起树酪,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤摧茴,失蹤者是張志新(化名)和其女友劉穎苛白,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡民鼓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片路幸。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖砰识,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情予借,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響修噪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脏款,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一剂府、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饮怯,春花似錦蓖墅、人聲如沸教翩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泵肄。三九已至腐巢,卻和暖如春惠豺,著一層夾襖步出監(jiān)牢的瞬間蛹疯,已是汗流浹背饮寞。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工寞钥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓棉胀,卻偏偏與公主長得像畸写,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1.幾種基本數(shù)據(jù)類型?復(fù)雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結(jié)構(gòu)? 基本數(shù)據(jù)類型:Undefined烈评、Nul...
    極樂君閱讀 5,524評(píng)論 0 106
  • ………………………………
    虞漁閱讀 119評(píng)論 0 0
  • 暑山若雪 山巔的暮色 在炎炎夏日里 寒風(fēng)凜冽 夕陽下銀輝一閃 如少年時(shí) 輕聲囈語 未曾相見的離別 離別 沉入最長的...
    濤濤不絕82閱讀 156評(píng)論 0 3