JavaScript複習

先從幾道面試題提及

  • JS中使用typeof能獲得的哪些類型?
  • 什麼時候使用===什麼時候使用==?
  • window.onload和DOMContentLoaded的區別?
  • 用JS建立10個<a>標籤,點擊的時候彈出來對應的序號
  • 簡述如何實現一個模塊加載器,實現相似require.js的基本功能
  • 實現數組的隨機排序

思考

  • 拿到一個面試題,你第一時間看到的是什麼?
    • 考點
  • 又如何看待網上搜出來的永遠也看不完的題海?
    • 不變應萬變
  • 如何對待接下來遇到的面試題?
    • 題目到知識再到題目

題目考察的知識點

JS變量類型、強制類型轉換、瀏覽器渲染過程、做用域、JS模塊化、JS基礎算法javascript

JS 「三座大山」 —— 原型、做用域和異步php

二、原型

題目

  1. JS中使用typeof能獲得哪些類型
  2. 什麼時候使用===什麼時候使用==
  3. JS中有哪些內置函數
  4. JS變量按照存儲方式區分爲哪些類型,並描述其特色
  5. 如何理解JSON

知識點

  • 變量類型
  • 變量計算

變量類型

  • 值類型vs引用類型
  • typeof運算符詳解

值類型

var a=100
var b=a
a=200
console.log(b) // 100
複製代碼

引用類型

引用類型:對象、數組、函數css

var a={age:20}
var b=a
b.age=21
console.log(a.age)
複製代碼

typeof運算符

typeof undefined // undefined
typeof 'abc' // string
typeof 123 // number
typeof true // boolean
typeof {} // object
typeof [] // object
typeof null // object
typeof console.log // function
複製代碼

變量計算-強制類型轉換

  • 字符串拼接
  • ==運算符
  • if語句
  • 邏輯運算

字符串拼接

var a=100+10 // 110
var b=100+'10' // '10010'
複製代碼

==運算符

100=='100' // true
0=='' // true
null==undefined // true
複製代碼

if語句

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

// 判斷一個變量會被當作true仍是false
var a=100
console.log(!!a);
複製代碼

題目解答

  1. JS中使用typeof能獲得的哪些類型html

    • 見typeof運算符
  2. 什麼時候使用===什麼時候使用==前端

    // 問題:什麼時候使用=== 什麼時候使用==
    if (obj.a==null) {
        // 這裏至關於obj.a===null||obj.a===undefined,簡寫形式
        // 這是jquery源碼中推薦的寫法
    }
    複製代碼
  3. JS中有哪些內置函數java

    // 問題:JS中有哪些內置函數--數據封裝類對象
    Object
    Array
    Boolean
    Number
    String
    Function
    Date
    RegExp
    Error
    複製代碼
  4. JS變量按照存儲方式區分爲哪些類型,並描述其特色node

    • 值類型
    • 引用類型
  5. 如何理解JSONjquery

    // 問題:如何理解JSON
    // JSON只不過是一個JS對象而已
    JSON.stringify({a:10,b:20})
    JSON.parse('{"a":10,"b":20}')
    複製代碼

題目

  1. 如何準確判斷一個變量是數組類型
  2. 寫一個原型鏈繼承的例子
  3. 描述new一個對象的過程
  4. zepto(或其餘框架)源碼中如何使用原型鏈

知識點

  • 構造函數
  • 構造函數-擴展
  • 原型規則和示例
  • 原型鏈
  • instanceof

構造函數

function Foo(name,age){
    this.name=name
    this.age=age
    this.class='class-1'
    // return this 默認有這一行
}
var f=new Foo('zhangsan',20)
// var f1=new Foo('lisi',22) 建立多個對象
複製代碼

構造函數-擴展

  • var a={}實際上是var a=new Object()的語法糖
  • var a=[]實際上是var a=new Array()的語法糖
  • function Foo(){...}實際上是var Foo=new Function(...)
  • 使用instanceof判斷一個函數是不是一個變量的構造函數

🐖:判斷一個變量是否爲「數組」:變量 instanceof Arraylinux

原型規則和示例

5條原型規則git

原型規則是學習原型鏈的基礎

  1. 全部的引用類型(數組、對象、函數),都具備對象特性,便可自由擴展屬性(除了「null」之外)

    var obj={}; obj.a=100;
    var arr=[]; arr.a=100;
    function fn(){}
    fn.a=100;
    複製代碼
  2. 全部的引用類型(數組、對象、函數),都有一個__proto__屬性,屬性值是一個普通的對象(🐖:即隱式原型)

    console.log(obj.__proto__);
    console.log(arr.__proto__);
    console.log(fn.__proto__);
    複製代碼
  3. 全部的函數,都有一個prototype屬性,屬性值也是一個普通的對象(🐖:即顯示原型)

    console.log(fn.prototype);
    複製代碼
  4. 全部的引用類型(數組、對象、函數),__proto__屬性值指向它的構造函數的「prototype」屬性值

    console.log(obj.__proto__===Object.prototype)
    複製代碼
  5. 當試圖獲得一個對象的某個屬性時,若是這個對象自己沒有這個屬性,那麼會去它的__proto__(即它的構造函數的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()
    複製代碼

this

循環對象自身的屬性

var item
for(item in f){
    // 高級瀏覽器已經在for in 中屏蔽了來自原型的屬性
    // 可是這裏建議你們仍是加上這個判斷,保證程序的健壯性
    if(f.hasOwnProperty(item)){
        console.log(item)
    }
}
複製代碼

原型鏈

f.toString() // 要去f.__proto__.__proto__中查找
複製代碼

instanceof

🐖:用於判斷引用類型屬於哪一個構造函數的方法

  • f instanceof Foo的判斷邏輯是:
  • f的__proto__一層一層往上,可否對應到Foo.prototype
  • 再試着判斷f instanceof Object

解題

  1. 如何準確判斷一個變量是數組類型

    var arr=[]
    arr instanceof Array // true
    typeof arr // object,typeof是沒法判斷是不是數組的
    複製代碼
  2. 寫一個原型鏈繼承的例子

    // 動物
    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()
    // 接下來的代碼演示時,會推薦更加貼近實戰的原型鏈繼承示例!
    複製代碼
  3. 描述new一個對象的過程

    • 建立一個新對象
    • this指向這個新對象
    • 執行代碼,即對this賦值
    • 返回this
  4. zepto(或其餘框架)源碼中如何使用原型鏈

    • 閱讀源碼是高效提升技能的方式
    • 但不能「埋頭苦鑽」有技巧在其中
    • 慕課網搜索「zepto設計和源碼分析」

代碼演示

// 封裝DOM查詢
function Elem(id) {
    this.elem=document.getElementById(id)
}
Elem.prototype.html=function (val) {
    var elem=this.elem
    if (val) {
        elem.innerHTML=val
        return this; // 爲了鏈式操做
    }else{
        return elem.innerHTML
    }
}
Elem.prototype.on=function (type,fn) {
    var elem=this.elem
    elem.addEventListener(type,fn)
    return this
}

Elem.prototype.getStyle=function(elem,attr){
    if (elem.currentStyle) {
        return elem.currentStyle[attr]
    }else {
        return getComputedStyle(elem,false)[attr]
    }
}


Elem.prototype.css=function (attr,val) {
    var elem=this.elem
    if (val) {
        elem.style[attr]=val
        return this
    }else {
        return this.getStyle(elem,attr)
    }
}


var div1=new Elem('box')
div1.html('123').on('click',function () {
    alert('click')
}).css('border','1px solid #f00');
複製代碼

三、 做用域

題目

  1. 說一下對變量提高的理解
  2. 說明this幾種不一樣的使用場景
  3. 建立10個<a>標籤,點擊的時候彈出來對應的序號
  4. 如何理解做用域
  5. 實際開發中閉包的應用

知識點

  • 執行上下文
  • this
  • 做用域
  • 做用域鏈
  • 閉包

執行上下文

  • 範圍:一段<script>或者一個函數
  • 全局:變量定義、函數聲明 🐖:一段<script>
  • 函數:變量定義、函數聲明、this、argument 🐖:函數

PS: 注意「函數聲明」和「函數表達式」的區別

this

  • this要在執行時才能確認值,定義時沒法確認
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
複製代碼
  • 做爲構造函數執行
  • 做爲對象屬性執行
  • 做爲普通函數執行
  • call apply bind

做用域

  • 沒有塊級做用域
  • 只有函數和全局做用域
// 無塊級做用域
if (true) {
    var name='zhangsan'
}
console.log(name);

// 函數和全局做用域
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
    // 當前做用域沒有定義的變量,即「自由變量」
    console.log(a);
    console.log(b);
}
fn()

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

閉包

function F1(){
    var a=100
    // 返回一個函數(函數做爲返回值)
    return function(){
        console.log(a)
    }
}
// f1獲得一個函數
var f1=F1()
var a=200
f1()
複製代碼

閉包的使用場景

  • 函數做爲返回值(上一個demo)
  • 函數做爲參數傳遞(本身思考)

解題

  1. 說一下對變量提高的理解

    • 變量定義
    • 函數聲明(注意和函數表達式的區別)
  2. 說明this幾種不一樣的使用場景

    • 做爲構造函數執行
    • 做爲對象屬性執行
    • 做爲普通函數執行
    • call apply bind
  3. 建立10個<a>標籤,點擊的時候彈出來對應的序號 🐖:自執行函數,就是不用調用,只要定義完成,當即執行的函數

    // 這是一個錯誤的寫法!!!
    var i,a
    for(i=0;i<10;i++){
        a=document.createElement('a')
        a.innerHTML=i+'<br>'
        a.addEventListener('click',function(e){
            e.preventDefault()
            alert(i)
        })
        document.body.appendChild(a)
    }
    // 這是正確的寫法!!!
    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)
    }
    複製代碼
  4. 如何理解做用域

    • 自由變量
    • 做用域鏈,即自由變量的查找
    • 閉包的兩個場景
  5. 實際開發中閉包的應用

    // 閉包實際開發中主要用於封裝變量,收斂權限
    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) // true
    firstLoad(10) // false
    firstLoad(20) // true
    複製代碼

四、異步

題目

  1. 同步和異步的區別是什麼?分別舉一個同步和異步的例子
  2. 一個關於setTimeout的筆試題
  3. 前端使用異步的場景有哪些

知識點

  • 什麼是異步(對比同步)
  • 前端使用異步的場景
  • 異步和單線程

什麼是異步

console.log(100);
setTimeout(function(){
    console.log(200);
},1000)
console.log(300);
複製代碼

對比異步

console.log(100);
alert(200) // 1秒鐘以後點擊確認
console.log(300);
複製代碼

什麼時候須要異步

  • 在可能發生等待的狀況
  • 等待過程當中不能像alert同樣阻塞程序運行
  • 所以,全部的「等待的狀況」都須要異步

前端使用異步的場景

  • 定時任務:setTimeout,setInterval
  • 網絡請求:ajax請求,動態<img>加載
  • 事件綁定

<img>加載示例

console.log('start');
var img=document.createElement('img')
img.onload=function(){
    console.log('loaded');
}
img.src='/xxx.png'
console.log('end');
複製代碼

事件綁定示例

console.log('start');
document.getElementById('btn1').addEventListener('click',function(){
    alert('clicked')
})
console.log('end');
複製代碼

異步和單線程

// 示例1 定時器
console.log(100);
setTimeout(function(){
    console.log(200);
},1000)
console.log(300);
複製代碼
  • 執行第一行,打印100
  • 執行setTimeout後,傳入setTimeout的函數會被暫存起來,不會當即執行(單線程的特色,不能同時幹兩件事)
  • 執行最後一行,打印300
  • 待全部程序執行完,處於空閒狀態時,會立馬看有沒有暫存起來的要執行。
  • 發現暫存起來的setTimeout中的函數無需等待時間,就當即過來執行
// 示例2 ajax請求
console.log('start');
$.get('./data1.json',function(data1){
    console.log(data1);
})
console.log('end');
複製代碼

解題

  1. 同步和異步的區別是什麼?分別舉一個同步和異步的例子

    • 同步會阻塞代碼執行,而異步不會
    • alert是同步,setTimeout是異步
  2. 一個關於setTimeout的筆試題

    console.log(1);
    setTimeout(function(){
        console.log(2);
    },0)
    console.log(3);
    setTimeout(function(){
        console.log(4);
    },1000)
    console.log(5);
    複製代碼
  3. 前端使用異步的場景有哪些

    • 見知識點

重點

  • 異步和同步的區別
  • 異步和單線程的關係
  • 異步在前端的引用場景

4.一、 其它知識點

題目

  1. 獲取2017-06-10格式的日期
  2. 獲取隨機數,要求是長度一致的字符串格式
  3. 寫一個能遍歷對象和數組的通用forEach函數

知識點

  • 日期
  • Math
  • 數組API
  • 對象API

日期

Date.now() // 獲取當前時間毫秒數
var dt=new Date()
dt.getTime() // 獲取毫秒數
dt.getFullYear() // 年
dt.getMonth() // 月(0-11)
dt.getDate() // 日(0-31)
dt.getHours() // 小時(0-23)
dt.getMinutes() // 分鐘(0-59)
dt.getSeconds() // 秒(0-59)
複製代碼

Math

  • 獲取隨機數Math.random()

數組API

  • forEach遍歷全部元素
  • every判斷全部元素是否都符合條件
  • some判斷是否有至少一個元素符合條件
  • sort排序
  • map對元素從新組裝,生成新數組
  • filter過濾符合條件的元素

forEach

var arr=[1,2,3]
arr.forEach(function(item,index){
    // 遍歷數組的全部元素
    console.log(index,item);
})
複製代碼

every

var arr=[1,2,3]
var result=arr.every(function(item,index){
    // 用來判斷全部的數組元素,都知足一個條件
    if(item<4){
        return true
    }
})
console.log(result);
複製代碼

some

var arr=[1,2,3]
var result=arr.some(function(item,index){
    // 用來判斷全部的數組元素,只要有一個知足條件便可
    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

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){
    // 經過某一個條件過濾數組
    if(item>=2){
        return true
    }
})
console.log(arr2);
複製代碼

對象API

var obj={
    x:100,
    y:200,
    z:300
}
var key
for (key in obj) {
    // 注意這裏的hasOwnProperty,再講原型鏈的時候講過了
    if (obj.hasOwnProperty(key)) {
        console.log(key,obj[key]);
    }
}
複製代碼

解題

  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) {
            // 強制類型轉換
            month='0'+month
        }
        if (date<10) {
            // 強制類型轉換
            date='0'+date
        }
        // 強制類型轉換
        return year+'-'+month+'-'+date
    }
    var dt=new Date()
    var formatDate=formatDate(dt)
    console.log(formatDate);
    複製代碼
  2. 獲取隨機數,要求是長度一致的字符串格式

    var random=Math.random()
    var random=random+'0000000000' // 後面加上10個0
    var random=random.slice(0,10)
    console.log(random);
    複製代碼
  3. 寫一個能遍歷對象和數組的通用forEach函數

    function forEach(){
        var key
        if(obj instanceof Array){
            // 準確判斷是否是數組
            obj.forEach(function(item,index){
                fn(index,item)
            })
        }else{
            // 不是數組就是對象
            for(key in obj){
                fn(key,obj[key])
            }
        }
    }
    var arr=[1,2,3]
    // 注意,這裏參數的順序換了,爲了和對象的遍歷格式一致
    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(上)

回顧JS基礎知識

  • 變量類型和計算
  • 原型和原型鏈
  • 閉包和做用域
  • 異步和單線程
  • 其餘(如日期、Math、各類經常使用API)
  • 特色:表面看來並不能用於工做中開發代碼
  • 內置函數:Object Array Boolean String ......
  • 內置對象:Math JSON .....
  • 咱們連在網頁彈出一句hello world都不能實現

JS-WEB-API

  • JS基礎知識:ECMA 262 標準
  • JS-WEB-API: W3C標準
  • W3C標準中關於JS的規定有:
    • DOM操做
    • BOM操做
    • 事件綁定
    • ajax請求(包含http協議)
    • 存儲
  • 頁面彈框是window.alert(123),瀏覽器須要作:
    • 定義一個window全局變量,對象類型
    • 給它定義一個alert屬性,屬性值是一個函數
  • 獲取元素document.getElementById(id),瀏覽器須要:
    • 定義一個document全局變量,對象類型
    • 給它定義一個getElementById的屬性,屬性值是一個屬性
  • 可是W3C標準沒有規定任何JS基礎相關的東西
  • 無論什麼變量類型、原型、做用域和異步
  • 只管定義用於瀏覽器中JS操做頁面的API和全局變量
  • 全面考慮,JS內置的全局函數和對象有哪些?
  • 以前講過的Object Array Boolean String Math JSON等
  • 剛剛提到的window document
  • 接下來還有繼續講到的全部未定義的全局變量,如navigator.userAgent

總結

  • 常說的JS(瀏覽器執行的JS)包含兩部分:
    • JS基礎知識(ECMA262標準)
    • JS-WEB-API(W3C標準)

5.一、DOM操做

Document Object Model

題目

  1. DOM是哪一種基本的數據結構?
  2. DOM操做的經常使用API有哪些
  3. DOM節點的attr和property有何區別

知識點

  • DOM本質
  • DOM節點操做
  • DOM結構操做

DOM的本質

<!-- xml -->
<?xml version="1.0" encoding="UTF-8"?>
<note>
    <to>Tove</to>
    <from>Jani</form>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
    <other>
        <a></a>
        <b></b>
    </other>
</note>
<!-- html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <p>this is p</p>
    </div>
</body>
</html>
複製代碼

DOM節點操做

DOM能夠理解爲:瀏覽器把拿到的html代碼,結構化一個瀏覽器能識別而且js可操做的一個模型而已。

  • 獲取DOM節點
  • prototype
  • Attribute

獲取DOM節點

var div1=document.getElementById('div1') // 元素
var divList=document.getElementsByTagName('div') // 集合
console.log(divList.length);
console.log(divList[0]);

var containerList=document.getElementsByClassName('.container') // 集合
var pList=document.querySelectorAll('p') // 集合
複製代碼

property

var pList=document.querySelectorAll('p') // 集合
var p=pList[0]
console.log(p.style.width); // 獲取樣式
p.style.width='100px' // 修改樣式
console.log(p.className); // 獲取class
p.className='p1' // 修改class

// 獲取nodeName和nodeType
console.log(p.nodeName);
console.log(p.nodeType);
複製代碼

Attribute

var pList=document.querySelectorAll('p') // 集合
var p=pList[0]
p.getAttribute('data-name')
p.getAttribute('data-name','imooc')
p.getAttribute('style')
p.getAttribute('style','font-size:30px;')
複製代碼

DOM結構操做

  • 新增節點
  • 獲取父元素
  • 獲取子元素
  • 刪除節點

新增節點

var div1=document.getElementById('div1')
// 添加新節點
var p1=document.createElement('p')
p1.innerHTML='this is p1'
div1.appendChild(p1) // 添加新建立的元素
// 移動已有節點
var p2=document.getElementById('p2')
div1.appendChild(p2)
複製代碼

獲取父元素和子元素

var div1=document.getElementById('div1')
var parent=div1.parentElement

var child=div1.childNodes
div1.removeChild(child[0])
複製代碼

刪除節點

var div1=document.getElementById('div1')
var child=div1.childNodes
div1.removeChild(child[0])
複製代碼

DOM是哪一種基本的數據結構

DOM操做的經常使用API有哪些

  • 獲取DOM節點,以及節點的property和Attribute
  • 獲取父節點,獲取子節點
  • 新增節點,刪除節點

DOM節點的Attribute和property有何區別

  • property只是一個JS對象的屬性的修改
  • Attribute是對html標籤屬性的修改

重點總結

  • DOM本質
  • DOM節點操做
  • DOM結構操做

5.二、BOM操做

Browser Object Model

題目

  • 如何檢測瀏覽器的類型
  • 拆解url的各部分

知識點

  • navigator
  • screen
  • location
  • history

navigator&screen

// navigator
var ua=navigator.userAgent
var isChrome=ua.indexOf('Chrome')
console.log(isChrome);

// screen
console.log(screen.width);
console.log(screen.height);
複製代碼

location&history

// location
console.log(location.href);
console.log(location.protocol); // 'http:','https:'
console.log(location.pathname); // '/learn/199'
console.log(location.search);
console.log(location.hash);

// history
history.back()
history.forward()
複製代碼

解答

  • 如何檢測瀏覽器的類型

  • 拆解url的各部分

6.一、事件

題目

  1. 編寫一個通用的事件監聽函數
  2. 描述事件冒泡流程
  3. 對於一個無限下拉加載圖片的頁面,如何給每一個圖片綁定事件

知識點

  • 通用事件綁定
  • 事件冒泡
  • 代理

通用事件綁定

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() // 阻止默認行爲
    alert('clicked')
})
複製代碼

關於IE低版本的兼容性

  • IE低版本使用attachEvent綁定事件,和W3C標準不同
  • IE低版本使用量已經很是少,不少網站都早已不支持
  • 建議對IE低版本的兼容性:瞭解便可,無需深究
  • 若是遇到對IE低版本要求苛刻的面試,果斷放棄

事件冒泡

<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="5">取消</p>
    <p id="6">取消</p>
</div>
<script> var p1 = document.getElementById('p1') var body = document.body bindEvent(p1, 'click', function (e) { e.stopPropatation() alert('激活') }) bindEvent(body, 'click', function (e) { alert('取消') }) </script>
複製代碼

事件代理

<div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <a href="#">a3</a>
    <a href="#">a4</a>
    <!-- 會隨時新增更多a標籤 -->
</div>
<script> var div1=document.getElementById('div1') div1.addEventListener('click',function(e){ var target=e.target if(target.nodeName==='A'){ alert(target.innetHTML) } }) </script>
複製代碼

完善通用綁定事件的函數

// 使用代理
var div1=document.getElementById('div1')
bindEvent(div1,'click','a',function(e){
    console.log(this.innerHTML);
})
// 不使用代理
var a=document.getElementById('a1')
bindEvent(div1,'click',function(e){
    console.log(a.innerHTML);
})
複製代碼

代理的好處

  • 代碼簡潔
  • 減小瀏覽器內存佔用

解答

  1. 編寫一個通用的事件監聽函數
  2. 描述事件冒泡流程
    • DOM樹形結構
    • 事件冒泡
    • 阻止冒泡
    • 冒泡的應用
  3. 對於一個無限下拉加載圖片的頁面,如何給每一個圖片綁定事件
    • 使用代理
    • 知道代理的兩個優勢

重點總結

  • 通用事件綁定
  • 事件冒泡
  • 代理

6.二、Ajax

題目

  1. 手動編寫一個ajax,不依賴第三方庫
  2. 跨域的幾種實現方式

知識點

  • XMLHttpRequest
  • 狀態碼說明
  • 跨域

XMLHttpRequest

var xhr=new XMLHttpRequest()
xhr.open('get','/api',false)
xhr.onreadystatechange=function () {
    // 這裏的函數異步執行,可參考以前JS基礎中的異步模塊
    if (xhr.readyState === 4) {
        if (xhr.statusCode === 200) {
            alert(xhr.responseText)
        }
    }
}
xhr.send(null)
複製代碼

IE兼容性問題

  • IE低版本使用ActiveXObject,和W3C標準不同
  • IE低版本使用量已經很是少,不少網站都早已不支持
  • 建議對IE低版本的兼容性:瞭解便可,無需深究
  • 若是遇到對IE低版本要求苛刻的面試,果斷放棄

狀態碼說明

xhr.readyState==4

  • 0-(未初始化) 尚未調用send()方法
  • 1-(載入) 已調用send()方法,正在發送請求
  • 2-(載入完成) send()方法執行完成,已經接收到所有響應內容
  • 3-(交互) 正在解析響應內容
  • 4-(完成) 響應內容解析完成,能夠在客戶端調用了

status

  • 2xx - 表示成功處理請求。如200
  • 3xx - 須要重定向,瀏覽器直接跳轉
  • 4xx - 客戶端請求錯誤,如404
  • 5xx - 服務器端錯誤

關於代碼演示

  • 以上是ajax的實現原理,後續會使用jQuer演示代碼

6.三、跨域

題目

  1. 什麼是跨域
  2. JSONP
  3. 服務器端設置http header

解答

  1. 什麼是跨域

    • 瀏覽器有同源策略,不容許ajax訪問其餘域接口
    • 跨域條件:協議、域名、端口,有一個不一樣就算跨域
  2. 能夠跨域的三個標籤

    • 可是有三個標籤容許跨域加載資源
    • <img src=xxx>
    • <link href=xxxx>
    • <script src=xxx>
  3. 三個標籤的場景

    • <img>用於打點統計,統計網站多是其餘域
    • <link><script>可使用CDN,CDN的也是其餘域
    • <script>能夠用於JSONP
  4. 跨域的注意事項

    • 全部的跨域請求都必須通過信息提供方容許
    • 若是未經容許便可獲取,那是瀏覽器同源策略出現漏洞
  5. JSONP實現原理

    • 加載http://coding.m.imooc.com/classindex.html
    • 不必定服務器端真正有一個classindex.html文件
    • 服務器能夠根據請求,動態生成一個文件,返回
    • 同理於<script src="http://coding.m.imooc.com/api.js">
    • 例如你的網站要跨域訪問慕課網的一個接口
    • 慕課網給你一個地址http://coding.m.imooc.com/api.js
    • 返回內容格式如callback({x:100,y:200}) (可動態生成)
    <script> window.callback=function(data){ // 這是咱們跨域獲得的信息 console.log(data); } </script>
    <script src="http://coding.m.imooc.com/api.js"></script>
    <!-- 以上將返回callback({x:100,y:200}) -->
    複製代碼
  6. 服務器端設置http header

    • 另一個解決跨域的簡潔方法,須要服務器端來作
    • 可是做爲交互方,咱們必須知道這個方法
    • 是未來解決跨域問題的一個趨勢

關於代碼演示

  • 以上是JSONP的實現原理,後續會使用jQuery演示代碼
  • 後端設置http header不演示代碼,瞭解便可

手動編寫一個ajax

  • 見ajax章節

跨域的幾種實現方式

  • JSONP
  • 服務器端設置http header

6.四、存儲

題目

  1. 請描述一下cookie,sessionStorage和localStorage的區別?

知識點

  • cookie
  • sessionStorage和localStorage

cookie

  • 自己用於客戶端和服務器端通訊
  • 可是它有本地存儲的功能,因而就被「借用」
  • 使用document.cookie=...獲取和修改便可

cookie用於存儲的缺點

  • 存儲量過小,只有4KB
  • 全部http請求都帶着,會影響獲取資源的效率
  • API簡單,須要封裝才能用document.cookie=...

sessionStorage和localStorage

  • HTML5專門爲存儲而設計,最大容量5M
  • API簡單易用:
    • localStorage.setItem(key,value)
    • localStorage.getItem(key)
  • iOS safari隱藏模式下
    • localStorage.getItem 會報錯
    • 建議統一使用try-catch封裝

區別

  • 容量
  • 是否會攜帶到ajax中
  • API易用性

七、開發環境

關於開發環境

  • 面試官經過開發環境瞭解面試者的經驗
  • 開發環境,最能體現工做產出的效率
  • 會以聊天的形式爲主,而不是出具體的問題
  • IDE(寫代碼的效率)
  • git(代碼版本管理,多人協做開發)
  • JS模塊化
  • 打包工具
  • 上線回滾的流程

IDE

  • webstorm
  • sublime
  • vscode
  • atom
  • 插件 插件 插件!!!
  • 若是你要走大牛、大咖、逼格的路線,就用webstorm
  • 若是你走普通、屌絲、低調路線,就用sublime
  • 若是你走小清新、個性路線,就用vscode或者atom
  • 若是你面試,最好有一個用的熟悉,其餘都會一點
  • 千萬不要說你使用Dreamweaver或者notepad++
  • 不作.net也不要用Visual Studio
  • 不作java也不要用eclipse

Git

  • 正式項目都須要代碼版本管理
  • 大型項目須要多人協做開發
  • Git和linux是一個做者
  • 網絡Git服務器如 coding.net github.com
  • 通常公司代碼非開源,都有本身的Git服務器
  • 搭建Git服務器無需你瞭解太多
  • Git的基本操做必須很熟練

經常使用Git命令

  • git add
  • git checkout xxx
  • git commit -m "xxx"
  • git push origin master
  • git pull origin master
  • git branch
  • git checkout -b xxx / git checkout xxx
  • git merge xxx

7.一、模塊化

  • 這自己就是一個面試的問題

知識點

  • 不使用模塊化的狀況
  • 使用模塊化
  • AMD
  • CommonJS

不使用模塊化

  • util.js getFormatDate函數
  • a-util.js aGetFormatDate函數 使用getFormatDate
  • a.js aGetFormatDate

代碼

// util.js
function getFormatDate(date,type){
    // type===1 返回2017-06-15
    // type===2 返回2017年6月15日
    // ...
}
// a-util.js
function aGetFormatDate(date){
    // 要求返回2017年6月15日 格式
    return getFormatDate(date,2)
}
// a.js
var dt=new Date()
console.log(aGetFormatDate(dt));
複製代碼

使用

使用模塊化

AMD

  • require.js requirejs.org
  • 全局define函數
  • 全局require函數
  • 依賴JS會自動、異步加載

使用require.js

Common.js

  • nodejs 模塊化規範,如今被大量用前端,緣由:
  • 前端開發依賴的插件和庫,均可以從npm中獲取
  • 構建工具的高度自動化,使得使用npm的成本很是低
  • CommonJS不會異步加載JS,而是同步一次性加載出來

使用CommonJS

  • 代碼演示下一節介紹
  • 須要構建工具支持
  • 通常和npm一塊兒使用

AMD和CommonJS的使用場景

  • 須要異步加載JS,使用AMD
  • 使用了npm以後建議使用CommonJS

重點總結

  • AMD
  • CommonJS
  • 二者的區別

7.二、上線和回滾

  • 不會有具體的問題,交流詢問的方式

知識點

  • 上線和回滾的基本流程
  • linux基本命令

上線回滾流程介紹

  • 是很是重要的開發環節
  • 各個公司的具體流程不一樣
  • 由專門的工具後者系統完成,咱們無需關心細節
  • 若是你沒有參與過,面試時也要說出要點
  • 只講要點,具體實現沒法講解

上線流程要點

  • 將測試完成的代碼提交到git版本庫的master分支
  • 將當前服務器的代碼所有打包並記錄版本號,備份
  • 將master分支的代碼提交覆蓋到線上服務器,生成新版本號

回滾流程要點

  • 將當前服務器的代碼打包並記錄版本號,備份
  • 將備份的上一個版本號解壓,覆蓋到線上服務器,並生成新的版本號

7.三、linux基本命令

  • 服務器使用linux居多,server版,只有命令行
  • 測試環境要匹配線上環境,所以也是linux
  • 常常須要登陸測試機來本身配置、獲取數據

八、運行環境

  • 瀏覽器就能夠經過訪問連接來獲得頁面的內容
  • 經過繪製和渲染,顯示出頁面的最終的樣子
  • 整個過程當中,咱們須要考慮什麼問題?

知識點

  • 頁面加載過程
  • 性能優化
  • 安全性

8.一、頁面加載

題目

  1. 從輸入url到獲得html的詳細過程
  2. window.onload和DOMContentLoaded的區別

知識點

  • 加載資源的形式
  • 加載一個資源的過程
  • 瀏覽器渲染頁面的過程

加載資源的形式

  • 輸入url(或跳轉頁面)加載html
  • coding.m.imooc.m
  • 加載html中的靜態資源
  • <script src="/static/js/jquery.js"></script>

加載一個資源的過程

  • 瀏覽器根據DNS服務器獲得域名的IP地址
  • 向這個IP的機器發送http請求
  • 服務器收到、處理並返回http請求
  • 瀏覽器獲得返回內容

瀏覽器渲染頁面的過程

  • 根據HTML結構生成DOM Tree
  • 根據CSS生成CSSOM
  • 將DOM和CSSOM整合造成RenderTree
  • 根據RenderTree開始渲染和展現
  • 遇到<script>時,會執行並阻塞渲染

示例一

示例二

思考

  • 爲何要把css放在head中?
  • 爲何要把js放在body最下面?

示例四

window.onload和DOMContentLoaded

解答

  1. 從輸入url到獲得html的詳細過程
    • 見「加載一個資源的過程」
  2. window.onload和DOMContentLoaded的區別
    • 見「window.onload和DOMContentLoaded」

8.2 性能優化

  • 這自己就是一個綜合性的問題
  • 沒有標準答案,若是要很是全面,能寫一本書。。。
  • 只關注核心點,針對面試

原則

  • 多使用內存、緩存或者其餘方法
  • 減小CPU計算、減小網絡

從哪裏入手

  • 加載頁面和靜態資源
  • 頁面渲染

加載資源優化

  • 靜態資源的壓縮合並
  • 靜態資源緩存
  • 使用CDN讓資源加載更快
  • 使用SSR後端渲染,數據直接輸出到HTML中

渲染優化

  • CSS放前面,JS放後面
  • 懶加載(圖片懶加載、下載加載更多)
  • 減小DOM查詢,對DOM查詢作緩存
  • 減小DOM操做,多個操做盡可能合併在一塊兒執行
  • 事件節流
  • 儘早執行操做(如DOMContentLoaded)

資源合併

緩存

  • 經過鏈接名稱控制緩存
  • <script src="abc_1.js"></script>
  • 只有內容改變的時候,連接名稱纔會改變
  • <script src="abc_2.js"></script>

CDN

使用SSR後端渲染

  • 如今Vue React 提出了這樣的概念
  • 其實jsp php asp 都屬於後端渲染

懶加載

緩存DOM查詢

合併DOM插入

事件節流

儘早操做

8.三、安全性

  • 綜合性的問題:場景的前端安全問題有哪些

知識點

  • XSS跨站請求攻擊
  • XSRF跨站請求僞造

XSS

  • 在新浪微博寫一篇文章,同時偷偷插入一段<script>
  • 攻擊代碼中,獲取cookie,發送本身的服務器
  • 發佈博客,有人查看博客內容
  • 會把查看者的cookie發送到攻擊者的服務器

XSS預防

  • 前端替換關鍵字,例如替換<&lt;
  • 後端替換

XSRF

  • 你已登陸一個購物網站,正在瀏覽商品
  • 該網站付費接口是xxx.com/pay?id=100 可是沒有任何驗證
  • 而後你收到一封郵件,隱藏着<img src=xxx.com/pay?id=100>
  • 你查看郵件的時候,就已經悄悄的付費購買了

XSRF預防

  • 增長驗證流程,如輸入指紋、密碼、短信驗證碼

8.四、技巧

  • 簡歷
  • 過程當中。。。

簡歷

  • 簡潔明瞭,重點突出項目經歷和解決方案
  • 把我的博客放在簡歷上,而且按期維護更新博客
  • 把我的的開源項目放在簡歷中,並維護開源項目
  • 簡歷千萬不要造假,要保持能力和經歷上的真實性

面試過程當中

  • 如何看待加班?加班就像借錢,救急不救窮
  • 千萬不可挑戰面試官,不要反考面試官
  • 學會給面試官驚喜,但不要太多
  • 遇到不會回答的問題,說出你知道的也能夠
  • 談談你的缺點----說一下你最近正在學什麼
相關文章
相關標籤/搜索