Javascript高级面试

原型

异步

一、什么是单线程,和异步有什么关系

单线程:只有一个线程,同一时间只能做一件事

原因:避免DOM渲染的冲突
解决方案:异步

为什么js只有一个线程:避免DOM渲染冲突
  • 浏览器需要渲染DOM
  • JS可以修改DOM结构
  • JS执行的时候,浏览器DOM渲染会暂停
  • 两端JS也不能同时执行(都修改DOM就冲突了)
  • webworker支持多线程,但是不能访问DOM

 

解决方案存在的问题
  • 问题一:没按照书写方式执行,可读性差
  • 问题二:callback中不容易模块化

二、什么是event-loop

  • 事件轮询,JS实现异步的具体解决方案
  • 同步代码,直接执行
  • 异步函数先放在异步队列中
  • 待同步函数执行完毕,轮询执行异步队列的函数

setTimeout(function(){
    console.log(1);
},100);              //100ms之后才放入异步队列中,目前异步队列是空的
setTimeout(function(){
    console.log(2);  //直接放入异步队列
})
console.log(3)       //直接执行

//执行3之后,异步队列中只有2,把2拿到主线程执行,2执行完之后,异步队列中并没有任务,所以一直轮询异步队列,直到100ms之后1放入异步队列,将1拿到主线程中执行

$.ajax({
    url:'./data.json',
    success:function(){        //网络请求成功就把success放入异步队列
        console.log('a');
    }
})

setTimeout(function(){
    console.log('b')
},100)

setTimeout(function(){
    console.log('c');
})
console.log('d')

//打印结果:
//d    //d   
//c    //c  
//a    //b   
//b    //a   

//真实环境不会出现dacb

三、是否用过jQuery的Deferred

  • jQuery1.5的变化
  • 使用jQuery Deferred
  • 初步引入Promise概念

 

jQuery1.5之前

var ajax = $.ajax({
    url:'./data.json',
    success:function(){
        console.log('success1');
        console.log('success2');
        console.log('success3');
    },
    error:function(){
        console.log('error');
    }
})
console.log(ajax); //返回一个XHR对象

 

jQuery1.5之后

var ajax = $.ajax('./data.json');
ajax.done(function(){
    console.log('success1')
})
.fai(function(){
    console.log('fail')
})
.done(function(){
    console.log('success2');
})
console.log(ajax); //deferred对象

var ajax = $.ajax('./data.json');
ajax.then(function(){
    console.log('success1')
},function(){
    console.log('error1');
})
.then(function(){
    console.log('success2');
},function(){
    console.log('error');
})

//使用
var w = waithandle()
w.then(function(){
    console.log('ok1');
},function(){
    console.log('err2');
})
.then(function(){
    console.log('ok2');
},function(){
    console.log('err2');
})
//还有w.wait w.fail
  • 无法改变JS异步和单线程的本质
  • 只能从写法上杜绝callback这种形式
  • 它是一种语法糖,但是解耦了代码
  • 很好的提现:开放封闭原则(对扩展开放对修改封闭)
使用jQuery Deferred

//给出一段非常简单的代码,使用setTimeout函数
var wait = function(){
    var task = function(){
        console.log('执行完成');
    }
    setTimeout(task,2000)
}

wait();

//新增需求:要在执行完成之后进行某些特别复杂的操作,代码可能会很多,而且分好几个步骤

function waitHandle(){
    var dtd = $.Deferred();//创建一个deferred对象
    
    var wait = function(dtd){  // 要求传入一个deferred对象
        var task = function(){
            console.log("执行完成");
            dtd.resolve();  //表示异步任务已完成
            //dtd.reject() // 表示异步任务失败或者出错
        };
        setTimeout(task,2000);
        return dtd;
    }
    //注意,这里已经要有返回值
    return wait(dtd);
}
/*
*总结:dtd的API可分成两类,用意不同
*第一类:dtd.resolve  dtd.reject
*第二类:dtd.then  dtd.done  dtd.fail

*这两类应该分开,否则后果严重!
*可以在上面代码中最后执行dtd.reject()试一下后果
*/

使用dtd.promise()

function waitHandle(){
    var dtd = $.Deferred();
    var wait = function(){
        var task = function(){
            console.log('执行完成');
            dtd.resolve();
        }
        setTimeout(task,2000)
        return dtd.promise();  //注意这里返回的是promise,而不是直接返回deferred对象
    }
    return wait(dtd)
}


var w = waitHandle();   //promise对象
$.when(w).then(function(){
    console.log('ok1');
},function(){
    console.log('err1');
})
/*
只能被动监听,不能干预promise的成功和失败
*/
  • 可以jQuery1.5对ajax的改变举例
  • 说明如何简单的封装、使用deferred
  • 说明promise和Defrred的区别

要想深入了解它,就需要知道它的前世今生

四、Promise的基本使用和原理

基本语法回顾
异常捕获

//规定:then只接受一个函数,最后统一用catch捕获异常

多个串联

var scr1 = 'https://www.imooc.com/static/img/index/logo_new.png';
var result1 = loadImg(src1);
var src2 = 'https://www.imooc.com/static/img/index/logo_new.png';
var result2 = loadImg(src2);

result1.then(function(img1) {
    console.log('第一个图片加载完成', img1.width);
    return result2;
}).then(function(img2) {
    console.log('第二个图片加载完成', img2.width);
}).catch(function(ex) {
    console.log(ex);
})
Promise.all和Promise.race

//Promise.all接收一个promise对象的数组
//待全部完成后,统一执行success
Promise.all([result1, result2]).then(datas => {
        //接收到的datas是一个数组,依次包含了多个promise返回的内容
        console.log(datas[0]);
        console.log(datas[1]);
})
   
//Promise.race接收一个包含多个promise对象的数组
//只要有一个完成,就执行success
Promise.race([result1, result2]).then(data => {
    //data即最先执行完成的promise的返回值
    console.log(data);
})
Promise标准
  • 三种状态:pending,fulfilled,rejected
  • 初始状态:pending
  • pending变为fulfilled,或者pending变为rejected
  • 状态变化不可逆

promise必须实现then这个方法
then()必须接收两个函数作为标准
then

五、介绍一下async/await(和Promise的区别、联系)

六、总结一下当前JS结局异步的方案

虚拟DOM

  • vdom 是 vue 和 React 的核心,先讲哪个都绕不开它
  • vdom 比较独立,使用也比较简单
  • 如果面试问到 vue 和 React 和实现,免不了问 vdom

问题

- vdom 是什么?为何会存在 vdom?
什么是vdom
  • virtual dom,虚拟DOM
  • 用JS模拟DOM结构
  • DOM变化的对比,放在JS层来做(图灵完备语言:能实现各种逻辑的语言)
  • 提高重绘性能
DOM

<ul id="list">
    <li class="item">Item 1</li>
    <li class="item">Item 2</li>
</ul>
虚拟DOM:

{
    tag: 'ul',
    attrs: {
        id: 'list'
    },
    children: [{
            tag: 'li',
            attrs: { className: 'item' },
            children: ['item1']
        },
        {
            tag: 'li',
            attrs: { className: 'item' },
            children: ['item2']
        }
    ]
}

//className代替class,因为class是js的保留字

浏览器最耗费性能就是DOM操作

现在浏览器执行JS性能非常低

设计一个需求场景

用jQery实现

遇到的问题

  • vdom 的如何应用,核心 API 是什么
  • 介绍一下 diff 算法
说一下使用 jquery 和使用框架的区别
jQuery 实现 todo-list

vue 实现 todo-list

jQuery 和框架的区别

  • 数据和视图的分离,解耦(开放封闭原则)
  • 以数据驱动视图,只关心数据变化,DOM 操作被封装
说一下对 MVVM 的理解
  • MVC
  • MVVM
  • 关于ViewModel

MVVM和vue

组件化和React

hybrid

未完待续,每日更新

来源:https://segmentfault.com/a/1190000017498782

posted @ 2018-12-25 11:38  大天狗子  阅读(540)  评论(0编辑  收藏  举报