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.四、技巧

  • 简历
  • 过程当中。。。

简历

  • 简洁明了,重点突出项目经历和解决方案
  • 把我的博客放在简历上,而且按期维护更新博客
  • 把我的的开源项目放在简历中,并维护开源项目
  • 简历千万不要造假,要保持能力和经历上的真实性

面试过程当中

  • 如何看待加班?加班就像借钱,救急不救穷
  • 千万不可挑战面试官,不要反考面试官
  • 学会给面试官惊喜,但不要太多
  • 遇到不会回答的问题,说出你知道的也能够
  • 谈谈你的缺点----说一下你最近正在学什么
相关文章
相关标签/搜索