# Javascript一些基础面试题

By [MarkTang's Blog](https://paragraph.com/@marktang-s-blog) · 2022-08-26

---

JS面试
----

### 一些使Javascript更加简洁的小技巧

> 清空或截断数组

    
    const arr = [11, 22, 33, 44, 55, 66];
    
    // truncanting
    
    arr.length = 3;
    
    console.log(arr); // => [11, 22, 33]
    
    //clearing
    
    arr.length = 0;
    
    console.log(arr); // => []
    
    console.log(arr[2]); // => undefined
    

### 几个面试题

1.  JS中使用 typeof 能得到的哪些类型？ 考点：JS变量类型
    
2.  何时使用 === 何时使用 == ? 考点：强制类型转换
    
3.  window.onload和DOMContentLoaded的区别? 考点：浏览器渲染过程
    
4.  用JS创建10个标签，点击的时候弹出来对应的序号 考点：作用域
    
    *   简述如何实现一个模块加载器，实现类似require.js的基本功能 考点：JS模块化
        
    *   实现数组的随机排序 考点：JS基础算法
        
5.  变量类型和计算
    
    > 题目
    
    1.  JS中使用 typeof 能得到的哪些类型？ 考点：JS变量类型
        
    2.  何时使用 === 何时使用 == ? 考点：强制类型转换
        
    3.  JS中有哪些内置函数
        
    4.  JS变量按照存储方式区分为哪些类型，并描述其特点
        
    5.  如何理解JSON
        
    
    > 解答
    
    1.  undefined、string、number、boolean、object、function
        
    2.  obj.a == null 除了判断null和undefined外，都需要使用全等符
        
    3.  数据封装类对象- Object、Array、Boolean、Number、String、Function、Date、RegExp、Error
        
    4.  值类型、引用类型
        
    5.  JSON 只不过是一个 JS 对象而已, 也是一个数据格式
        
    
    > 知识点
    
    1.  变量类型
        
    2.  变量计算
        
    
    #### 变量类型
    
    *   值类型 vs 引用类型
        
    *   typeof 运算符详解
        
    
    #### 变量计算 - 强制类型转换
    
    *   字符串拼接
        
    *   \== 运算符
        
    *   if语句
        
    *   逻辑运算
        
    
    ### 原型和原型链
    
    > 题目
    
    *   如何准确判断一个变量是数组类型
        
    *   写一个原型链继承的例子
        
    *   描述new一个对象的过程
        
    *   zepto(或其他框架) 源码中如何使用原型链
        
    
    > 解答
    
    *   arr instanceof Array
        
    
        
        // 动物
        
        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()
        
        // 接下来代码演示时，会推荐更加贴近实战的原型继承示例！
        
    
    > 描述new 一个对象的过程
    
    1.  创建一个新对象
        
    2.  this 指向这个新对象
        
    3.  执行代码，即对this 赋值
        
    4.  返回 this
        
    
    > zepto (或其他框架) 源码中如何使用原型链
    
    *   阅读源码是高效提高技能的方式
        
    *   但不能 "埋头苦钻" 有技巧在其中
        
    *   慕课网搜索 "zepto设计和源码分析"
        
    
    > 知识点
    
    *   构造函数
        
    *   构造函数 - 扩展
        
    *   原型规则和示例
        
    *   原型链
        
    *   instanceof
        
    
    #### 原型规则和示例
    
    *   所有的引用类型(数组、对象、函数)，都具有对象特性，即可自由扩展属性(除了 "null" 以外)
        
    *   所有的引用(数组、对象、函数)，都有一个\_\_proto\_\_ (隐式原型)属性,属性值是一个普通的对象
        
    *   所有的函数，都有一个 prototype (显式原型) 属性，属性值也是一个普通对象
        
    *   所有的引用类型(数组、对象、函数), \_\_ proto \_\_ 属性值指向它的构造函数的 "prototype" 属性值
        
    
        
        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)
        
    
    *   当试图得到一个对象的某个属性时，如果这个对象本身没有这个属性，那么会去它的\_\_ 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(); // zhangsan
        
        f.alertName(); // zhangsan
        
        var item;
        
        for (item in f) {
        
        //高级浏览器已经在 for in 中屏蔽了来自原型的属性
        
        //但是这里建议大家还是加上这个判断，保证程序的健壮性
        
        if (f.hasOwnProperty(item)) {
        
        console.log(item)
        
        }
        
        }
        
    
    #### 原型链
    
        
        //构造函数
        
        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()
        
        f.toString() // 要去 f.__proto__.__proto__中查找
        
    
    > instanceof
    
    *   用于判断 引用类型 属于哪个 构造函数 的方法
        
    *   f instanceof Foo 的判断逻辑是：
        
    *   f的 \_\_ proto \_\_ 一层一层往上，能否对应到 Foo.prototype
        
    *   再试着判断 f instanceof Object
        
    
    ### 作用域和闭包-执行上下文
    
    > 题目
    
    1.  说一下对变量提升的理解
        
    
    *   变量定义
        
    *   函数声明(注意和函数表达式的区别)
        
    
    1.  说明 this 几种不同的使用场景
        
    
    *   作为构造函数执行
        
    *   作为对象属性执行
        
    *   作为普通函数执行
        
    *   call apply bind
        
    
    1.  创建10个标签，点击的时候弹出来对应的序号
        
    2.  // 这是一个错误的写法!!! 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) }
        
        1.  如何理解作用域
            
        
        *   自由变量
            
        *   作用域链，即自由变量的查找
            
        *   闭包的两个场景
            
        
        1.  实际开发中闭包的应用
            
        
            
            // 闭包实际应用中主要用于封装变量，收敛权限
            
            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
            
        
        > 知识点
        
        *   执行上下文
            
        *   this
            
        *   作用域
            
        *   作用域链
            
        *   闭包
            
        
        #### 执行上下文
        
            
            console.log(a) // undefined
            
            var a = 100
            
            fn('zhangsan') // 'zhangsan' 20
            
            function fn(name) {
            
            age = 20
            
            console.log(name, age)
            
            var age
            
            }
            
        
        *   范围:一段
            
            *   全局: 变量定义、函数声明 ==一段
                
                *   函数: 变量定义、函数声明、this、arguments ==函数==
                    
                *   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()
                
            
            #### 闭包
            
                
                function F1() {
                
                var a = 100
                
                // 返回一个函数 (函数作为返回值)
                
                return function () {
                
                console.log(a)
                
                }
                
                }
                
                // f1 得到一个函数
                
                var f1 = F1()
                
                var a = 200
                
                f1()
                
            
            *   函数作为返回值
                
            *   函数作为参数传递
                
            
            ### 异步和单线程
            
            #### 什么是异步
            
            > 题目
            
            1.  同步和异步的区别是什么？分别举一个同步和异步的例子
                
            
            *   同步会阻塞代码执行，而异步不会
                
            *   alert是同步，setTimeout是异步
                
            
            1.  一个关于setTimeout的笔试题
                
            
                
                console.log(1)
                
                setTimeout(function () {
                
                console.log(2)
                
                }, 0)
                
                console.log(3)
                
                setTimeout(function () {
                
                console.log(4)
                
                }, 1000)
                
                console.log(5)
                
            
            1.  前端使用异步的场景有哪些
                
            
            *   定时任务：setTimeout, setInverval
                
            *   网络请求：ajax请求，动态加载
                
            *   事件绑定
                
            
            > 知识点
            
            *   什么是异步(对比同步)
                
            *   前端使用异步的场景
                
            *   异步和单线程
                
            
                
                // 异步-不阻塞
                
                console.log(100)
                
                setTimeout(function() {
                
                console.log(200)
                
                }, 1000)
                
                console.log(300)
                
                // 同步-阻塞
                
                console.log(100)
                
                alert(200)
                
                console.log(300)
                
            
            #### 何时需要异步
            
            *   在可能发生等待的情况
                
            *   等待过程中不能像 alert 一样阻塞程序运行
                
            *   因此，所有的 "等待的情况" 都需要异步
                
            
            #### 前端使用异步的场景
            
            *   定时任务：setTimeout, setInverval
                
            *   网络请求：ajax请求，动态加载
                
            *   事件绑定
                
            
                
                // ajax请求代码示例
                
                console.log('start')
                
                $.get('./data1.json', function(data1) {
                
                console.log(data1)
                
                })
                
                console.log('end')
                
                // <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')
                
            
            #### 单线程
            
            *   执行第一行，打印100
                
            *   执行setTimeout后，传入setTimeout的函数会被暂存起来，不会立即执行(单线程的特点,不能同时干两件事)
                
            *   执行最后一行，打印300
                
            *   待所有程序执行完，处于空闲状态时，会立马看有没有暂存起来的要执行。
                
            *   发现暂存起来的setTimeout中的函数无需等待时间，就立即拿过来执行
                
            
            ### 其他知识
            
            > 题目
            
            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)
                
            
            1.  获取随机数，要求是长度一致的字符串格式
                
            
                
                var random = Math.random()
                
                var random = random + '0000000000' // 后面加上10个零
                
                var random = random.slice(0, 10)
                
                console.log(random)
                
            
            1.  写一个能遍历对象和数组的通用forEach函数
                
            
                
                function forEach(obj, fn) {
                
                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)
                
                })
                
            
            > 知识点
            
            *   日期
                
            *   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,4]
                
                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])
                
                }
                
                }
                
            
            ### JS-Web-API
            
            *   JS基础知识: ECMA 262 标准
                
            *   JS-Web-API: W3C 标准
                
            *   W3C标准中关于JS的规定有：
                
            *   DOM操作
                
            *   BOM操作
                
            *   事件绑定
                
            *   ajax请求(包括http协议)
                
            *   存储
                
            
            ### DOM操作
            
            > 题目
            
            1.  DOM 是哪种基本的数据结构？
                
            
            *   树
                
            
            1.  DOM 操作的常用API有哪些
                
            
            *   获取DOM节点，以及节点的property和Attribute
                
            *   获取父节点，
                
            *   新增节点，删除节点
                
            
            1.  DOM 节点的Attribute 和 property有何区别
                
            
            *   property 只是一个JS对象的属性的修改
                
            *   Attribute 是对html标签属性的修改
                
            
            > 知识点
            
            *   DOM本质
                
            *   DOM节点操作
                
            *   DOM结构操作
                
            
            #### DOM节点操作
            
            *   获取DOM节点
                
            *   property
                
            *   Attribute
                
            
                
                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)
                
                p.className = 'p1'
                
                // 获取 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.setAttribute('data-name', 'sss')
                
                p.getAttribute('style')
                
                p.setAttribute('style', 'font-size:28px;')
                
            
            #### 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])
                
            
            #### BOM操作
            
            > 题目
            
            1.  如何检测浏览器的类型
                
            
                
                var ua = navigator.userAgent
                
                var isChrome = ua.indexOf('Chrome')
                
                console.log(isChrome)
                
            
            1.  拆解url的各部分
                
            
                
                location.href
                
                location.protocol
                
                location.pathname
                
                location.search
                
                location.hash
                
            
            > 知识点
            
            *   navigator
                
            *   screen
                
            *   location
                
            *   history
                
            
                
                // navigator
                
                var ua = navigator.userAgent
                
                var isChrome = ua.indexOf('Chrome')
                
                console.log(isChrome)
                
                // screen
                
                console.log(screen.width)
                
                console.log(screen.height)
                
            
                
                // location
                
                console.log(location.href)
                
                console.log(location.protocol) // 'http:' 'https:'
                
                console.log(location.pathname) // user/api
                
                console.log(location.search)
                
                console.log(location.hash)
                
                // history
                
                history.back()
                
                history.forward()
                
            
            #### 事件
            
            > 题目
            
            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低版本要求苛刻的面试，果断放弃
                
            
            #### 代理
            
                
                var div1 = document.getElementById('div1')
                
                div1.addEventListener('click', function(e) {
                
                var target = e.target
                
                if (target.nodeName === 'A') {
                
                alert(target.innerHTML)
                
                }
                
                })
                
            
            #### 完善通用绑定事件的函数
            
                
                function bindEvent(elem, type, selector, fn) {
                
                if (fn == null) {
                
                fn = selector
                
                selector = null
                
                }
                
                elem.addEventListener(type, function (e) {
                
                var target
                
                if (selector) {
                
                target = e.target
                
                if (target.matches(selector)) {
                
                fn.call(target, e)
                
                }
                
                } else {
                
                fn(e)
                
                }
                
                })
                
                }
                
            
            #### 代理的好处
            
            *   代码简洁
                
            *   减少浏览器内存占用
                
            
            #### 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.status == 200) {
                
                alert(xhr.responseText)
                
                }
                
                }
                
                }
                
                xhr.send(null)
                
            
            #### IE兼容性问题
            
            *   IE低版本使用 ActiveXObject, 和W3C标准不一样
                
            *   IE低版本使用量以非常少，很多网站都早已不支持
                
            *   建议对IE低版本的兼容性: 了解即可，无需深究
                
            *   如果遇到对IE低版本要求苛刻的面试，果断放弃
                
            
            #### readyState
            
            *   0 - (未初始化)还没有调用send()方法
                
            *   1 - (载入)已调用send()方法，正在发送请求
                
            *   2 - (载入完成)send()方法执行完成，已经接收到全部响应内容
                
            *   3 - (交互) 正在解析响应内容
                
            *   4 - (完成) 响应内容解析完成，可以在客户端调用了
                
            
            #### status
            
            *   2xx - 表示成功处理请求。如200
                
            *   3xx - 需要重定向，浏览器直接跳转
                
            *   4xx - 客户端请求错误，如404
                
            *   5xx - 服务器端错误
                
            
            #### 跨域
            
            *   什么是跨域
                
            *   JSONP
                
            *   服务器端设置 http header (cors)
                
            
            #### 什么是跨域
            
            *   浏览器有同源策略，不允许ajax访问其他域接口
                
            *   跨域条件：协议、域名、端口、有一个不同就算跨域
                
            
            #### 可以跨域的三个标签
            
            *   但是有三个标签允许跨域加载资源
                
            *     
                
            *     
                
            *     
                
            *   三个标签的场景
                
                *   用于打点统计，统计网站可能是其他域
                    
                *   跨域注意事项
                    
                    *   所有的跨域请求都必须经过信息提供方允许
                        
                    *   如果未经允许即可获取，那是浏览器同源策略出现漏洞
                        
                    
                    #### JSONP实现原理
                    
                    *   加载 [http://coding.m.test.com/classindex.html](http://coding.m.test.com/classindex.html)
                        
                    *   不一定服务器端真正有一个 classindex.html 文件
                        
                    *   服务器可以根据请求，动态生成一个文件，返回
                        
                    *   同理于
                        
                    *   存储
                        
                        > 题目
                        
                        1.  请描述一下 cookie, sessionStorage 和 localStorage的区别？
                            
                        
                        *   容量
                            
                        *   是否会携带到ajax中
                            
                        *   API易用性
                            
                        
                        > 知识点
                        
                        *   cookie
                            
                        *   localStorage 和 sessionStorage
                            
                        
                        #### cookie
                        
                        *   本身用于客户端和服务器端通信
                            
                        *   但是它有本地存储的功能，于是就被 "借用"
                            
                        *   使用 document.cookie = .... 获取和修改即可
                            
                        
                        #### cookie 用于存储的缺点
                        
                        *   存储量太小，只有4kb
                            
                        *   所有http请求都带着，会影响获取资源的效率
                            
                        *   API简单，需要封装才能用 document.cookie = ....
                            
                        
                        #### localStorage 和 sessionStorage
                        
                        *   HTML5专门为存储而设计，最大容量5M
                            
                        *   API简单易用
                            
                        *   localStorage.setItem(key, value); localStorage.getItem(key);
                            
                        *   IOS safari 隐藏模式下
                            
                        *   localStorage.getItem 会报错
                            
                        *   建议统一使用 try-catch 封装
                            
                        
                        #### 关于开发环境
                        
                        *   面试官想通过开发环境了解面试者的经验
                            
                        *   开发环境，最能提现工作产出的效率
                            
                        
                        #### 模块化
                        
                        > 知识点
                        
                        *   不使用模块化的情况
                            
                        *   使用模块化
                            
                        *   AMD
                            
                        *   CommonJS
                            
                        
                        ### 运行环境
                        
                        #### 页面加载 - 渲染过程
                        
                        > 题目
                        
                        1.  从输入url到得到html的详细过程
                            
                        2.  window.onload 和 DOMContentLoaded的区别
                            
                        
                        > 知识点
                        
                        *   加载资源的形式
                            
                        *   加载一个资源的过程
                            
                        *   浏览器渲染页面的过程
                            
                        
                        #### 加载资源的形式
                        
                        *   输入url(或跳转页面)加载html
                            
                        *   [http://coding.m.test.com](http://coding.m.test.com)
                            
                        *   加载html中的静态资源
                            
                        *     
                            
                        
                        #### 加载一个资源的过程
                        
                        1.  浏览器根据DNS服务器得到域名的IP地址
                            
                        2.  向这个IP的机器发送http 请求
                            
                        3.  服务器收到、处理并返回http 请求
                            
                        4.  浏览器得到返回内容
                            
                        
                        #### 浏览器渲染页面的过程
                        
                        答案
                        
                        1.  根据HTML结构生成DOM Tree
                            
                        2.  根据CSS生成 CSSOM
                            
                        3.  将DOM和CSSOM整合形成RenderTree
                            
                        4.  根据 RenderTree 开始渲染和展示
                            
                        5.  遇到
                            
                        6.  window.onload // 页面的全部资源加载完才会执行，包括图片、视频等 DOMContentLoaded // DOM渲染完即可执行，此时图片、视频还可能没有加载完
                            
                            #### 性能优化
                            
                            > 原则
                            
                            *   多使用内存、缓存或者其他方法
                                
                            *   减少CPU计算、减少网络
                                
                            
                            > 从哪里入手
                            
                            *   加载页面和静态资源
                                
                            *   页面渲染
                                
                            
                            > 加载资源优化
                            
                            *   静态资源的压缩合并
                                
                            *   静态资源缓存
                                
                            *   使用CDN让资源加载更快
                                
                            *   使用SSR后端渲染，数据直接输出到HTML中
                                
                            
                            > 渲染优化
                            
                            *   CSS放前面，JS放后面
                                
                            *   懒加载(图片懒加载、下拉加载更多)
                                
                            *   减少DOM查询，对DOM查询做缓存
                                
                            *   减少DOM操作，多个操作尽量合并在一起执行
                                
                            *   事件节流
                                
                            *   尽早执行操作(如DOMContentLoaded)
                                
                            
                            #### 合并DOM插入
                            
                                
                                //合并DOM插入
                                
                                var listNode = document.getElementById('list')
                                
                                // 要插入10个 li 标签
                                
                                var frag = document.createDocumentFragment() // 不触发DOM操作
                                
                                var x, li;
                                
                                for (x = 0; x < 10; x++) {
                                
                                li = document.createElement("li")
                                
                                li.innerHTML = "list item " + x
                                
                                frag.appendChild(li)
                                
                                }
                                
                                listNode.appendChild(frag) //触发DOM操作
                                
                            
                            #### 事件节流
                            
                                
                                var textarea = document.getElementById('text')
                                
                                var timeoutId
                                
                                textarea.addEventListener('keyup', function () {
                                
                                if (timeoutId) {
                                
                                clearTimeout(timeoutId)
                                
                                }
                                
                                timeoutId = setTimeout(function () {
                                
                                // 触发 change 事件
                                
                                }, 100)
                                
                                })
                                
                            
                            ### 安全性
                            
                            > 知识点
                            
                            *   XSS跨站请求攻击
                                
                            *   XSRF 跨站请求伪造
                                
                            
                            #### XSS
                            
                            *   在新浪博客写一篇文章，同时偷偷插入一段
                                
                                *   攻击代码中，获取cookie, 发送自己的服务器
                                    
                                *   发布博客，有人查看博客内容
                                    
                                *   会把查看者的cookie发送到攻击者的服务器
                                    
                            *   预防
                                
                                *   前端替换关键字，例如替换 为>
                                    
                                    *   后端替换
                                        
                                *   XSRF
                                    
                                    *   你已登录一个购物网站，正在浏览器商品
                                        
                                    *   [该网站付费接口是xxx.com/pay?id=100](http://xn--xxx-er9dp4usp0ab8dbn6cfoi8u5a7bd.com/pay?id=100) 但是没有任何验证
                                        
                                    *   然后你收到一封邮件，隐藏着 src=xxx.com/pay?id=100
                                        
                                    *   \>
                                        
                                *   你查看邮件的时候，就悄悄付费。
                                    
                                
                                > 预防
                                
                                *   增加验证流程，如输入指纹、密码、短信验证码
                                    
                                
                                #### 浏览器中的线程
                                
                                *   GUI渲染线程
                                    
                                *   javascript引擎线程
                                    
                                *   HTTP请求线程
                                    
                                *   浏览器事件触发线程
                                    
                                
                                #### 异步API
                                
                                *   DOM Events
                                    
                                *   XMLHttpRequest(ajax)
                                    
                                *   fetch
                                    
                                *   WebSockets
                                    
                                *   Service Worker
                                    
                                *   Timer
                                    
                                
                                #### Promise
                                
                                *   异步处理方案
                                    
                                *   异步数据的链式处理
                                    
                                *   异步代码同步化
                                    
                                *   catch 获取异常
                                    
                                *   then 正常结束
                                    
                                
                                #### event-loop
                                
                                > 事件轮巡
                                
                                *   异步队列
                                    
                                
                                #### jquery-deferred
                                
                                *   dtd的API可分成两类，用意不同
                                    
                                *   第一类：dtd.resolve dtd.reject
                                    
                                *   第二类：dtd.then dtd.done dtd.fail
                                    
                                *   这两类应该分开，否则后果严重
                                    
                                *   使用 返回dtd.promise() 解决随意在监听范围调用reject
                                    
                                
                                #### async/await
                                
                                > ES7提案
                                
                                *   then 只是将 callback拆分了
                                    
                                *   async/await 是最直接的同步写法
                                    
                                
                                > 用法
                                
                                *   使用 await , 函数必须用async标识
                                    
                                *   await 后面跟的是一个Promise实例
                                    
                                *   需要babel-polyfill
                                    
                                
                                #### 虚拟dom Virtual Dom
                                
                                > 问题
                                
                                *   v-dom 是什么？
                                    
                                *   v-dom 如何运用？
                                    
                                *   介绍Diff算法
                                    
                                
                                > v-dom 是什么？
                                
                                *   用js模拟dom结构
                                    
                                *   如果dom有变化，对比出变化的地方，只修改这个变化的地方
                                    
                                *   提高重绘性能
                                    
                                *   JS是前端中唯一:图灵完备语言
                                    
                                *   将DOM对比操作放在JS层，提高效率
                                    
                                
                                > 遇到的问题
                                
                                *   DOM操作是 "昂贵"的，js运行效率高
                                    
                                *   尽量减少DOM操作，而不是 "推倒重来"
                                    
                                *   项目越复杂，影响越严重
                                    
                                *   vdom即可解决这个问题
                                    
                                
                                #### snabbdom
                                
                                *   实现vdom的开源库
                                    
                                *   vue2.0借用了snabbdom
                                    
                                *   h函数、patch函数
                                    
                                *   h函数返回v-node
                                    
                                *   patch函数将vnode patch到一个真实的dom容器中
                                    
                                
                                #### Diff算法
                                
                                > 问题
                                
                                *   什么是diff算法?
                                    
                                *   vdom为何用diff算法?
                                    
                                *   diff算法的实现过程
                                    
                                
                                > vdom为何使用diff算法
                                
                                答案:
                                
                                *   DOM操作是 "昂贵"的，因此尽量减少DOM操作
                                    
                                *   找出本次DOM必须更新的节点来更新，其他的不更新
                                    
                                *   这个 "找出" 的过程，就需要diff算法
                                    
                                
                                > diff算法的实现过程
                                
                                *   patch(container, vnode)
                                    
                                *   patch(vnode, newVnode)
                                    
                                
                                > 什么是diff算法？
                                
                                *   是linux的基础命令 diff git diff
                                    
                                
                                    
                                    {
                                    
                                    tag: 'ul',
                                    
                                    attrs: {
                                    
                                    id: 'list'
                                    
                                    },
                                    
                                    children: [
                                    
                                    {
                                    
                                    tag: 'li',
                                    
                                    attrs: {
                                    
                                    className: 'item'
                                    
                                    },
                                    
                                    children: ['Item 1']
                                    
                                    }
                                    
                                    ]
                                    
                                    }
                                    
                                
                                #### MVVM
                                
                                > 问题
                                
                                *   如何理解MVVM？
                                    
                                *   如何实现MVVM？
                                    
                                *   是否解读过vue的源码?
                                    
                                
                                > 题目
                                
                                *   说一下使用jQuery和使用框架的区别？
                                    
                                *   说一下对MVVM的理解？
                                    
                                *   vue中如何实现响应式？
                                    
                                *   vue中如何解析模板？
                                    
                                *   vue的整个实现流程？
                                    
                                
                                > 从jQuery到框架
                                
                                *   数据和视图的分离,解耦(开放封闭原则)
                                    
                                *   以数据驱动视图，只关心数据变化，DOM操作被封装
                                    
                                
                                > 如何理解 MVVM
                                
                                *   MVVM - Model View ViewModel
                                    
                                *   三者之间的联系，以及如何对应到各段代码
                                    
                                *   ViewModel的理解，联系View和Model
                                    
                                
                                ### vue三要素
                                
                                *   响应式：vue如何监听到data的每个属性变化？
                                    
                                *   模板引擎：vue的模板如何被解析，指令如何处理？
                                    
                                *   渲染：vue的模板如何被渲染成html?以及渲染过程
                                    
                                
                                #### vue中如何实现响应式
                                
                                *   什么是响应式
                                    
                                *   Object.defineProperty
                                    
                                *   模拟
                                    
                                
                                > 什么是响应式
                                
                                *   修改data属性之后，vue立刻监听到
                                    
                                *   data属性被代理到vm上
                                    
                                
                                > 问题解答
                                
                                *   关键是理解 Object.defineProperty
                                    
                                *   将data的属性代理到vm上
                                    
                                
                                #### vue中如何解析模板
                                
                                *   模板是什么
                                    
                                *   render函数
                                    
                                *   render函数与vdom
                                    
                                
                                > 模板是什么？
                                
                                *   本质：字符串
                                    
                                *   有逻辑，如v-if v-for等
                                    
                                *   与html格式很像，但有很大区别
                                    
                                *   最终还要转换为html来显示
                                    
                                *   模板最终必须转换成JS代码，因为：
                                    
                                *   有逻辑(v-if v-for),必须用JS才能实现(图灵完备)
                                    
                                *   转换为html渲染页面，必须用JS才能实现
                                    
                                *   因此，模板最终要转换成一个JS函数(render函数)
                                    
                                
                                > render 函数 - with的用法
                                
                                    
                                    var obj = {
                                    
                                    name: 'zhangsan',
                                    
                                    age: 20,
                                    
                                    getAddress: function () {
                                    
                                    alert('beijing')
                                    
                                    }
                                    
                                    }
                                    
                                    function fn() {
                                    
                                    with(obj){
                                    
                                    console.log(name)
                                    
                                    console.log(age)
                                    
                                    getAddress()
                                    
                                    }
                                    
                                    }
                                    
                                
                                *   从哪里可以看到render函数？
                                    
                                *   复杂一点的例子，render函数是什么样子的？
                                    
                                *   v-if v-for v-on 都是怎么处理的？
                                    
                                *   vm.\_c其实就是snabbvdom的h
                                    
                                
                                > 解答
                                
                                *   模板：字符串，有逻辑，嵌入JS变量.....
                                    
                                *   模板必须转换为JS代码(有逻辑、渲染html、JS变量)
                                    
                                *   render函数是什么样子的
                                    
                                *   render函数执行是返回vnode
                                    
                                *   updateComponent
                                    
                                *   模板中的所有信息都被render函数包含
                                    
                                
                                #### vue的整个实现流程
                                
                                *   第一步：解析模板成render函数
                                    
                                *   第二步：响应式开始监听
                                    
                                *   第三步：首次渲染，显示页面，且绑定依赖
                                    
                                
                                1.  初次渲染，执行updateComponent,执行vm.\_render()
                                    
                                2.  执行render函数，会访问到vm.list和vm.title
                                    
                                3.  会被响应式的get方法监听到
                                    
                                4.  执行updateComponent，会走到vdom的patch方法
                                    
                                5.  patch将vnode渲染成DOM，初次渲染完成
                                    
                                6.  为何要监听get，直接监听set不行吗？
                                    
                                7.  data中有很多属性，有些被用到，有些可能不被用到
                                    
                                8.  被用到的会走到get,没用到就不会走get
                                    
                                
                                *   第四步：data属性变化，触发re-render
                                    
                                
                                ### 组件化
                                
                                > 题目
                                
                                *   说一下对组件化的理解
                                    
                                *   JSX本质是什么？
                                    
                                *   JSX和vdom的关系
                                    
                                *   说一下setState的过程
                                    
                                *   阐述自己对React和Vue的认识
                                    
                                
                                #### 说一下对组件化的理解
                                
                                *   组件的封装
                                    
                                *   组件的复用
                                    
                                
                                > 组件的封装
                                
                                *   视图
                                    
                                *   数据
                                    
                                *   变化逻辑(数据驱动视图变化)
                                    
                                
                                > 组件的复用
                                
                                *   props传递
                                    
                                
                                > 解答
                                
                                *   组件的封装: 封装视图、数据、变化逻辑
                                    
                                *   组件的复用： props传递、复用
                                    
                                
                                #### JSX本质是什么？
                                
                                *   JSX语法
                                    
                                *   JSX解析成JS
                                    
                                *   独立的标准
                                    
                                
                                > JSX语法
                                
                                *   html形式
                                    
                                *   引入JS变量和表达式
                                    
                                *   if...else
                                    
                                *   循环
                                    
                                *   style和className
                                    
                                *   事件
                                    
                                *   JSX语法根本无法被浏览器所解析
                                    
                                *   那么它如何在浏览器运行？
                                    
                                
                                > JSX 解析
                                
                                *   JSX其实是语法糖
                                    
                                *   开发环境会将JSX编译成JS代码
                                    
                                *   JSX的写法大大降低了学习成本和编码工作量
                                    
                                *   同时，JSX也会增加debug成本
                                    
                                
                                > JSX独立的标准
                                
                                *   JSX是React引入的，但不是React独有的
                                    
                                *   React已经将它作为一个独立标准开放，其他项目也可用
                                    
                                *   React.createElement 是可以自定义修改的
                                    
                                *   说明：本身功能已经完备；和其他标准兼容和扩展性没问题
                                    
                                *   另：有机会录制>,就用JSX标准
                                    
                                *   问题解答
                                    
                                    *   JSX语法(标签、JS表达式、判断、循环、事件绑定)
                                        
                                    *   JSX是语法糖，需被解析成JS才能运行
                                        
                                    *   JSX是独立的标准，可被其他项目使用
                                        
                                    
                                    #### JSX和vdom的关系
                                    
                                    *   分析：为何需要vdom
                                        
                                    *   React.createElement和h
                                        
                                    *   何时patch?
                                        
                                    *   自定义组件的解析
                                        
                                    
                                    > 为何需要vdom
                                    
                                    *   vdom 是 React初次推广开来的，结合JSX
                                        
                                    *   JSX就是模板，最终要渲染成html
                                        
                                    *   初次渲染 + 修改 state 后的 re-render
                                        
                                    *   正好符号vdom的应用场景
                                        
                                    
                                    > React.createElement和h
                                    
                                    *   初次渲染 - ReactDOM.render(,container)
                                        
                                    *   会触发patch(container,vnode)
                                        
                                    *   re-render - setState
                                        
                                    *   会触发patch(vnode,newVnode)
                                        
                                    
                                    > 自定义组件的解析
                                    
                                    *   'div' - 直接渲染
                                        
                                        即可,vdom可以做到
                                        
                                        *   Input和List,是自定义组件(class),vdom默认不认识
                                            
                                        *   因此Input和List定义的时候必须声明render函数
                                            
                                        *   根据props初始化实例，然后执行实例的render函数
                                            
                                        *   render函数返回的还是vnode对象
                                            
                                    *   问题解答
                                        
                                        *   为何需要vdom: JSX需要渲染成html,数据驱动视图
                                            
                                        *   React.createElement和h,都生成vnode
                                            
                                        *   何时patch: ReactDOM.render(...) 和 setState
                                            
                                        *   自定义组件的解析：初始化实例，然后执行render
                                            
                                        
                                        #### 说一下 React setState 的过程
                                        
                                        *   setState的异步
                                            
                                        *   vue修改属性也是异步
                                            
                                        *   setState的过程
                                            
                                        
                                        > setState的异步
                                        
                                            
                                            addTitle(title) {
                                            
                                            const currentList = this.state.list
                                            
                                            console.log(this.state.list) // ['a', 'b']
                                            
                                            this.setState({
                                            
                                            list:currentList.concat(title) // 'c'
                                            
                                            })
                                            
                                            console.log(this.state.list) // ['a', 'b']
                                            
                                            }
                                            
                                        
                                        > setState 为何需要异步？
                                        
                                        *   可能会一次执行多次 setState
                                            
                                        *   你无法规定、限制用户如何使用setState
                                            
                                        *   没必要每次setState 都重新渲染，考虑性能
                                            
                                        *   即便是每次重新渲染，用户也看不到中间的效果
                                            
                                        
                                        > vue修改属性也是异步
                                        
                                        *   效果、原因和setState一样
                                            
                                        
                                        > setState的过程
                                        
                                        答案:
                                        
                                        *   每个组件实例，都有renderComponent方法
                                            
                                        *   执行renderComponent会重新执行实例的render
                                            
                                        *   render函数返回newVnode,然后拿到preVnode
                                            
                                        *   执行patch(preVnode,newVnode)
                                            
                                        
                                        > 问题解答
                                        
                                        *   setState的异步：效果、原因
                                            
                                        *   vue修改属性也是异步：效果、原因
                                            
                                        *   setState的过程：最终走到patch(preVnode,newVnode)
                                            
                                        
                                        #### React vs Vue
                                        
                                        *   两者的本质区别
                                            
                                        *   看模板和组件化的区别
                                            
                                        *   两者共同点
                                            
                                        *   总结问题答案
                                            
                                        
                                        > 前言
                                        
                                        *   文无第一武无第二，技术选型没有绝对的对与错
                                            
                                        *   技术选型要考虑的因素非常多
                                            
                                        *   作为面试者，要有自己的主见
                                            
                                        *   和面试官的观点不一致没关系，只要能说出理由
                                            
                                        
                                        > 两者的本质区别
                                        
                                        *   vue - 本质是MVVM框架，由MVC发展而来
                                            
                                        *   React - 本质是前端组件化框架，由后端组件化发展而来
                                            
                                        *   但这并不妨碍他们两者都能实现相同的功能
                                            
                                        
                                        > 模板的区别
                                        
                                        *   vue - 使用模板 (最初由 angular 提出)
                                            
                                        *   React - 使用JSX
                                            
                                        *   模板语法上，我更加倾向于JSX
                                            
                                        *   模板分离上，我更加倾向于vue
                                            
                                        
                                        > 组件化的区别
                                        
                                        *   React本身就是组件化，没有组件化就不是React
                                            
                                        *   vue也支持组件化，不过是在MVVM上的扩展
                                            
                                        *   查阅vue组件化的文档，洋洋洒洒很多(侧面反映)
                                            
                                        *   对于组件化，我更加倾向于React,更加清晰
                                            
                                        
                                        > 两者共同点
                                        
                                        *   都支持组件化
                                            
                                        *   都是数据驱动视图
                                            
                                        
                                        > 问题解答
                                        
                                        *   国内使用，首推vue。文档更易读、易学、社区够大
                                            
                                        *   如果团队水平较高，推荐使用React。组件化和JSX
                                            
                                        
                                        ### hybrid
                                        
                                        *   移动端占大部分流量，已经远远超过PC
                                            
                                        *   一线互联网公司都有自己的App
                                            
                                        *   这些App中有很大比例的前端代码(不要惊讶)
                                            
                                        *   拿微信举例，你每天浏览微信的内容，多少是前端？
                                            
                                        
                                        > 题目
                                        
                                        *   hybrid是什么，为何用hybrid？
                                            
                                        *   介绍一下hybrid更新和上线的流程？
                                            
                                        *   hybrid和h5的主要区别
                                            
                                        *   前端JS和客户端如何通讯？
                                            
                                        
                                        #### hybrid是什么，为何会用hybrid?
                                        
                                        *   hybrid 文字解释
                                            
                                        *   存在价值，为何会用hybrid
                                            
                                        *   webview
                                            
                                        *   file:// 协议
                                            
                                        *   hybrid实现流程
                                            
                                        
                                        > hybrid 文字解释
                                        
                                        *   hybrid 即 "混合"，即前端和客户端的混合开发
                                            
                                        *   需前端开发人员和客户端开发人员配合完成
                                            
                                        *   某些环节也可能涉及到server端
                                            
                                        *   PS:不要以为自己是前端就可以不理会客户端的知识
                                            
                                        
                                        > hybrid存在价值
                                        
                                        *   可以快速迭代更新「关键」(无需app审核，思考为何？)
                                            
                                        *   体验流畅(和NA的体验基本类似)
                                            
                                        *   减少开发和沟通成本，双端公用一套代码
                                            
                                        
                                        > webview
                                        
                                        *   是app中的一个组件(app 可以有webview,也可以没有)
                                            
                                        *   用于加载H5页面，即一个小型的浏览器内核
                                            
                                        
                                        > file:// 协议
                                        
                                        *   其实在一开始接触html开发，就已经使用了file协议
                                            
                                        *   只不过你当时没有 "协议" "标准"等这些概念
                                            
                                        *   再次强调 "协议" "标准"的重要性！！！
                                            
                                        *   file协议: 本地文件，快
                                            
                                        *   http(s)协议: 网络加载，慢
                                            
                                        
                                        > hrbrid 具体实现
                                        
                                        *   不是所有场景都适合使用hybrid:
                                            
                                        *   使用NA: 体验要求极致，变化不频繁 (如头条的首页)
                                            
                                        *   使用hybrid: 体验要求高，变化频繁 (如头条的新闻详情页)
                                            
                                        *   使用h5: 体验无要求， 不常用 (如举报、反馈等页面)
                                            
                                        
                                        > 实现
                                        
                                        *   前端做好静态页面 (html js css), 将文件交给客户端
                                            
                                        *   客户端拿到前端静态页面，以文件形式存储在app中
                                            
                                        *   客户端在一个webview中，通过file协议加载前端文件(html js css)
                                            
                                        
                                        > 具体实现 - 遗留问题
                                        
                                        *   app发布之后，静态文件如何实时更新？
                                            
                                        *   静态页面如何获取内容？
                                            
                                        
                                        > 问题解答
                                        
                                        *   hybrid 是客户端和前端的混合开发
                                            
                                        *   hybrid 存在的核心意义在于快速迭代，无需审核
                                            
                                        *   hybrid实现流程(图)，以及webview和file协议
                                            
                                        
                                        #### hybrid 更新上线流程
                                        
                                        > 思考 (目的，可行途径)
                                        
                                        *   要替换每个客户端的静态文件
                                            
                                        *   只能客户端来做 (客户端是我们开发的)
                                            
                                        *   客户端去server下载最新的静态文件
                                            
                                        *   我们维护server的静态文件
                                            
                                        
                                        > 完整流程
                                        
                                        *   分版本，有版本号， 如201803211015
                                            
                                        *   将静态文件压缩成zip包，上传到服务端
                                            
                                        *   客户端每次启动，都去服务端检查版本号
                                            
                                        *   如果服务端版本号大于客户端版本号，就去下载最新的zip包
                                            
                                        *   下载完之后解压包，然后将现有文件覆盖
                                            
                                        
                                        > 问题解答
                                        
                                        *   掌握流程图
                                            
                                        *   要点1：服务端的版本和zip包维护
                                            
                                        *   要点2：更新zip包之前，先对比版本号
                                            
                                        *   要点3：zip下载解压和覆盖
                                            
                                        
                                        #### hybrid和h5的比较
                                        
                                        > 优点
                                        
                                        *   体验更好，跟NA体验基本一致
                                            
                                        *   可快速迭代，无需审核
                                            
                                        
                                        > 缺点
                                        
                                        *   开发成本高。联调、测试、查bug都比较麻烦
                                            
                                        *   运维成本高。参考此前讲过的更新上线的流程
                                            
                                        
                                        > 适用的场景
                                        
                                        *   hybrid: 产品的稳定功能，体验要求高，迭代频繁
                                            
                                        *   h5: 单次的运营活动(如 xx 红包) 或不常用功能
                                            
                                        
                                        > 问题解答
                                        
                                        *   优点：体验好，可快速迭代
                                            
                                        *   缺点：开发成本高，运维成本高
                                            
                                        *   适用的场景：hybrid适合产品型，h5适合运营型
                                            
                                        
                                        #### JS和客户端通讯
                                        
                                        *   回顾之前遗留的问题
                                            
                                        *   JS和客户端通讯的基本形式
                                            
                                        *   schema协议简介和使用
                                            
                                        *   schema使用的封装
                                            
                                        *   内置上线
                                            
                                        
                                        > 之前遗留的问题
                                        
                                        *   新闻详情页适用hybrid,前端如何获取新闻内容？
                                            
                                        *   不能用ajax获取。第一 跨域，第二 速度慢
                                            
                                        *   客户端获取新闻内容，然后JS通讯拿到内容，再渲染
                                            
                                        
                                        > JS和客户端通讯的基本形式
                                        
                                        *   JS访问客户端能力，传递参数和回调函数
                                            
                                        *   客户端通过回调函数返回内容
                                            
                                        
                                        #### schema 协议简介和使用
                                        
                                        *   之前介绍了http(s) 和 file协议
                                            
                                        *   schema协议 - 前端和客户端通讯的约定
                                            
                                        
                                            
                                            /* 网上搜的微信的部分 schema 协议 */
                                            
                                            weixin://dl/scan 扫一扫
                                            
                                            weixin://dl/feedback 反馈
                                            
                                            weixin://dl/moments 朋友圈
                                            
                                            weixin://dl/settings 设置
                                            
                                        
                                        > 内置上线
                                        
                                        *   将以上封装的代码打包，叫做invoke.js 内置到客户端
                                            
                                        *   客户端每次启动webview,都默认执行invoke.js
                                            
                                        *   本地加载，免去网络加载的时间，更快。
                                            
                                        *   本地加载，没有网络请求，黑客看不到schema协议，更安全
                                            
                                        
                                        > 问题解答
                                        
                                        *   通讯的基本形式：调用能力，传递参数，监听回调
                                            
                                        *   对schema协议的理解和使用
                                            
                                        *   调用schema代码的封装
                                            
                                        *   内置上线的好处：更快、更安全
                                            
                                        
                                        ### 如何热爱编程？
                                        
                                        *   热爱！
                                            
                                        *   怎么证明？
                                            
                                        
                                        #### 如何证明你热爱编程？
                                        
                                        *   看书
                                            
                                        *   写博客
                                            
                                        *   做开源
                                            
                                        
                                        > 看书 - 手下不离书
                                        
                                        *   构建知识体系的最好方式
                                            
                                        *   自己买书，不要借书
                                            
                                        *   看书有技巧
                                            
                                        
                                        > 博客 - 合格程序员的必备
                                        
                                        > 开源 - github 的 star 是硬通货

---

*Originally published on [MarkTang's Blog](https://paragraph.com/@marktang-s-blog/javascript)*
