文档章节

es6常用功能与异步详解(JS高级面试题)

o
 osc_gu9d45li
发布于 2019/04/06 17:05
字数 2028
阅读 19
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

callback hell方法的使用

可读性不友好

function loadImg(src,callback,fail){
    var img = document.createElement('img');
    img.onload = function(){
        callback(img);
    }
    img.onerror = function(){
        fail();
    }
    img.src = src;
}
var src = "https://www.baidu.com/img/baidu_jgylogo3.gif";

loadImg(src,function(img){
    console.log('img width',img.width)
},function(){
    console.log('faild')
})

用promise 去改造

用多个.then去分批处理

function loadImg(src){
    return new Promise(function(resolve,reject){
        var img = document.createElement('img');
        img.onload = function(){
            resolve(img);
        }
        img.onerror = function(){
            reject();
        }
        img.src = src;
    })
}
var src="https://www.baidu.com/img/baidu_jgylogo3.gif";
var result = loadImg(src);
result.then(function(img){
    console.log('img width',img.width)
},function(){
    console.log('faild')
})
result.then(function(img){
    console.log('img height',img.height)
})

问题解答:

  1. new promise实例,而且要传入return
  2. new promise时要传入函数,函数有resolve reject函数
  3. 成功时执行resolve()失败时执行reject()
  4. .then监听结果

ES6常用功能

  1. let 定义变量,可以重新赋值
  2. const 定义常量,不可以重新赋值
  3. 多行字符串/模板变量
  4. 解构赋值(详情见es6)
  5. 块级作用域(很大的改动)
  6. 函数默认参数
  7. 箭头函数

块级作用域

<!-- 在js里面 -->
var obj = {a:100,b:200}
for (var key in obj) {
    console.log(key,'for in')
}
console.log(key)  // 100,200

<!-- 在es6 -->
var obj = {a:100,b:200}
for (let key in obj) {
    console.log(key,'for in')
}
console.log(key); // undefine

箭头函数改变this指向的问题

<!-- 用箭头函数,指向本身函数对象 -->
function fn(){
    console.log('real',this); // {a:100}

    var arr = [1,2,3];
    arr.map(item=>{
        console.log(this); // {a:100}
    })
}
fn.call({a:100}); // call是强制让fn函数对象指向{a:100}

<!-- 不用箭头函数,this指向window -->
function fn(){
    console.log('real',this); // {a:100}

    var arr = [1,2,3];
    arr.map(function(item){
        console.log(this); // window;
    })
}
fn.call({a:100});

原型

描述一下zepto是如何使用原型 描述一下jquery如何使用原型 再结合自己的项目经验,说一个自己开发的列子

$p.css('color','red'); // css是原型方法
$p.html(); // html是原型方法

原型如何体现他的扩展性

异步

问题:

一. 什么是单线程,和异步有什么关系
  1. 单线程只有一个线程,同一时间只能做一件事情
var i,sum = 0;
for(i=0;i<100000;i++){
    sum+=i;
}
console.log(sum);

<!-- alert不处理,js执行和dom渲染暂时卡顿 -->
console.log(1);
alert('hello');
console.log(2);
  1. 用单线程的原因-避免DOM渲染的冲突 A. 浏览器需要渲染DOM

    B. js可以修改DOM结构

    C. JS执行的时候,浏览器DOM渲染会暂停

    D. 两段JS也不能同时执行(都修改DOM就冲突了)

    E. webworder支持多线程,但是不能访问DOM

  2. 单线程的解决单线程方案-异步

    console.log(100)
    setTimeout(function(){
        console.log(200);
    },1000)
    console.log(300);
    console.log(400);
    // 100
    // 300
    // 400
    // 200  一秒后执行
console.log(100)
$.ajax({
    url:'XXXX',
    success:function(res){
        console.log(res) // 最后执行
    }
});
console.log(300)
cobsole.log(400)

异步的问题:

问题一:没有按照书写的方式执行,可读性差

问题二:callback中不容易模块化(setTimeout和ajax里面的函数)

二. 什么是event-loop 异步的解决方案。
  1. 事件轮询,js实现异步的具体解决方案
  2. 同步代码,直接执行
  3. 异步函数先放在异步队列中;有setTimeout等待时间过后,才放入异步队列中。ajax执行完毕过后放入异步队列
  4. 待同步函数执行完毕,轮询执行异步队列的函数

回答点:

  1. 什么是异步队列,何时被放入异步队列
  2. 轮询的过程。
三. 是否用过jquery的deferred

问题解答:

1. 可以拿jquery1.5 对ajax的改变举例

2. 说明如何简单的封装、使用deferred,说出它的好处

3. 说明promise和deferred的区别

jQuery1.5的变化——1.5之前

var ajax = $.ajax({
    url:'./data.json',
    success:function(){
        console.log('success 1');
        console.log('success 2');
        console.log('success 3');
    },
    error:function(){
        console.log('error');
    }
})

jQuery1.5的变化——1.5之后 这样写的好处:

  1. 这样对修改封闭,对扩展开放,
  2. 增加一个函数,不用再修改原来的函数
  3. 多人开发,一人维护一个函数。
  4. 测试也只测试新的函数。
  5. 对代码管理和维护有好处的
// 每一个方法都会执行
var ajax = $.ajax('data.json');
ajax.done(function(){
    console.log('success 1');  
}).fail(function(){
  console.log('fail 1');  
}).done(function(){
    console.log('success 2');  
}).fail(function(){
  console.log('fail 2');  
}).done(function(){
    console.log('success 3');  
}).fail(function(){
  console.log('fail 3');  
})

<!-- 与promise很相近了 -->
var ajax = $.ajax('data.json')
ajax.then(function(){
   console.log('success 1'); 
},function(){
    console.log('error 1');
}).then(function(){
   console.log('success 2'); 
},function(){
    console.log('error 2');
})
  1. 无法改变js异步和单线程的本质
  2. 只能从写法上杜绝callback这种形式
  3. 它是一种语法糖形式,但是解耦了代码
  4. 很好的体现:开放封闭原则
  5. 减少了回归测试的成本。多人开发方便。

使用jquery deferred举例:

var wait = function(){
    var task = function(){
        console.log('执行完成');
    }
    setTimeout(task,20000)
}
wait();
function waitHandle(){
    // 定义 
    var dtd = $.Deferred();
    
    var wait = function(dtd){
    
        var task = function(){
            console.log('执行完毕');
            // 成功
            dtd.resolve()
            // 失败
            // dtd.reject()
        }
        setTimeout(task,2000);
        
        // wait返回
        return dtd;
    }
    
    // 最终返回
    return wait(dtd);
}

var w = waitHandle();
w.then(function(){
    console.log('ok 1');
},function(){
    console.log('err 1');
})
w.then(function(){
    console.log('ok 2');
},function(){
    console.log('err 2');
})
w.then(function(){
    console.log('ok 3');
},function(){
    console.log('err 3');
})

w.reject();  //  不会报错


// 开放封闭原则!!!

总结: dtd的API可分成两类,用意不同

第一类:dtd.reolve  dtd.reject  主动触发

第二类:dtd.then  dtd.done  dtd.fail  被动监听

初步引入promise概念,是 jquery deferred 引入过来的

promise和jquery deferred的区别:

promise对象只能被动监听,不能主动修改,所以在w.reject()会报错。

function waitHandle(){
    // 定义 
    var dtd = $.Deferred();
    
    var wait = function(dtd){
    
        var task = function(){
            console.log('执行完毕');
            // 成功
            dtd.resolve()
            // 失败
            // dtd.reject()
        }
        setTimeout(task,2000);
        
        // wait返回
        return dtd.promise(); // 这里返回的是promise对象
    }
    
    // 最终返回
    return wait(dtd);
}
var w = waitHandle();
$.when(w).then(function(){
    console.log('ok 1');
},function(){
    console.log('err 1');
}).then(function(){
    console.log('ok 2');
},function(){
    console.log('err 2');
})

w.reject();  // 这里就会直接报错。

四. promise的基本使用和原理

基本语法回顾

1. 异常捕获

function loadImg(src){
    return new Promise(resolve,reject){
        var img = document.createElement('img');
        img.onload = function(){
            resolve(img);
        }
        img.onerror = function(){
            reject('图片加载失败');
        }
        img.src=  src;
    }
}

var src="https://wwww.img.address";
var result = loadimg(src);
// 规定:then只接受一个成功的参数,最后统一用catch来捕获错误
result.then(function(img){
    console.log(1,img.width);
    return img;
}).then(function(img){
    console.log(2,img.width);
}).catch(function(ex){
    // 统一捕获异常,也会捕获到reject方法
    console.log(ex);
})

2. 多个串联

// 场景:希望加载完第一个,再加载第二个
var src1 = 'img.address';
var result1 = loadImg(src1);
var src2 = 'img.address';
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);
})

3. 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(datas);
})

4. promise标准

关于“标准”的闲谈,标准很重要

    任何技术推广使用都需要一套标准来支撑
    如 html js css http等,无规则不成方圆
    任何不符合标准的东西,终将会被用户抛弃

状态变化

    三种状态:pending fulfilled rejected
    初始状态pending
    pending 变成fulfilled,或者pending变为rejected
    状态不可逆

then

promise 实例必须实现then这个方法
then()必须可以接收两个函数作参数
then()返回的必须是一个promise实例

问题解答总结:

1. 基本语法复习
2. 如何异常捕获(error和reject都要考虑)
3. 多个串联-链式执行的好处
4. promise.all和promise.race
5. promise标准-状态变化,then函数
五. 介绍一下 async/await

是es7体验中的。

then只是将callback拆分了

async/await是最直接的同步写法

const load = async function(){
    const result1 = await loadImg(src1);
    console.log(result1);
    const result2 = await loadImg(src1);
    console.log(result2);
}
load()

语法(和promise的区别和联系)

1. 使用await,函数必须用async标识
2. await 后面跟的是一个promise实例
    使用了promise,并没有和promise冲突
    完全是同步的写法,再也没有回调函数
    但是:改变不了JS单线程、异步的本质
3. 需要安装babel-polyfill并,引入
六. 总结当前js异步解决方案
1. jQuery Deferred
2. Promise
3. async/await
4. generator(并不是解决异步的,原理比较复杂,忽略)
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
我的架构演化笔记 功能1: 基本的用户注册

“咚咚”,一阵急促的敲门声, 我从睡梦中惊醒,我靠,这才几点,谁这么早, 开门一看,原来我的小表弟放暑假了,来南京玩,顺便说跟我后面学习一个网站是怎么做出来的。 于是有了下面的一段...

强子哥哥
2014/05/31
976
3
CSS Browser Selector

CSS Browser Selector 是一个小的 JS 库,可增强 CSS 的选择器功能,支持根据不同的操作系统和浏览器来编写指定的 CSS 代码,可检测浏览器、浏览器版本、平台、平台版本、设备、设备版本、m...

匿名
2013/01/17
2.8K
1
首列固定的列表

实现特殊的表格(UITableView)效果:即表格中的首列固定不动,而每一行除了首列均可左右拖动,以展现每一行更多内容。 作者谭林江(@无法越狱的痛)说:去益盟面试回来,感觉聊得有点郁闷,...

匿名
2013/01/24
1.3K
0
Web开发组件管理器--Bower

Bower 是一个针对Web开发的包管理器。该工具主要用来帮助用户轻松安装CSS、JavaScript、图像等相关包,并管理这些包之间的依赖。 功能有些类似于Component。不同之处是,Component是围绕Git...

匿名
2013/02/01
1.2W
2

没有更多内容

加载失败,请刷新页面

加载更多

SQL 语句大全

点击上方“掌上编程”,选择“置顶或者星标” 优质文章第一时间送达! 一、基础 「1、说明:创建数据库」 CREATE DATABASE database-name    「2、说明:删除数据库」 drop database ...

GeneralMa
昨天
0
0
山东创睦网络科技有限公司:使用Python爬取全球新冠肺炎疫情数据

使用Python爬取全球新冠肺炎疫情数据 导入所需库包 获取实时数据的url 正式编写程序 查看输出结果 导入所需库包 在获取数据之前,我们需要先安装好所需的包requests和pandas: 1.如果是使用p...

osc_qv1fwke0
39分钟前
14
0
如何1年获得别人3年的工作经验(深度好文)

最近有同学问我,为什么你的工作年限不长,技术却这么厉害,我笑了笑,啥也没说。 我不是不想回答,是不知道怎么回答。在他们的定位可能就是,每方面都懂一点,遇到问题能够快速解决,就是比...

zhang_rick
今天
1
0
新基建带动行业

什么是“新基建”? 什么是“新基建”? 根据央视发布的信息来看,其涵盖了5G基站建设、新能源汽车充电桩、大数据中心、人工智能、工业互联网,特高压,城际以及城轨交通,涉及了七大领域和相...

osc_anefoz50
40分钟前
16
0
怕入错行?这群技术人写了本“择业指南”

计算机专业好找工作吗?哪些方向是当前的主流和热门方向呢? 计算机专业的你是不是还在为职业发展纠结犹豫呢? 刚经历完高考选专业的你是不是还在迷茫徘徊呢? 那么福利来啦! 《软件技术职业...

阿里云云栖号
40分钟前
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部