绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
【Step-By-Step】高频面试题深入解析 / 周刊05
2020-05-21 12:01:40

关于【Step-By-Step】

Step-By-Step (点击进入项目) 是我于 2019-05-20 开始的一个项目,每个工作日发布一道面试题。

每个周末我会仔细阅读大家的答案,整理一份较优答案出来,因本人水平有限,有误的地方,大家及时指正。

如果想 加群 学习,可以通过文末的公众号,添加我为好友。


本周面试题一览:

  • 实现 Promise.race 方法

  • JSONP 原理及简单实现

  • 实现一个数组去重的方法

  • 清除浮动的方法有哪些

  • 编写一个通用的柯里化函数currying

1. 实现 Promise.race 方法

在实现 Promise.race 方法之前,我们首先要知道 Promise.race 的功能和特点,因为在清楚了 Promise.race 功能和特点的情况下,我们才能进一步去写实现。

Promise.race 功能

Promise.race(iterable) 返回一个 promise,一旦 iterable 中的一个 promise 状态是 fulfilled / rejected ,那么 Promise.race 返回的 promise 状态是 fulfilled / rejected.

  1. let p = Promise.race([p1, p2, p3]);

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise实例的返回值,就传递给 p 的回调函数。

Promise.race 的特点

Promise.race 的返回值是一个 promise 实例

  • 如果传入的参数为空的可迭代对象,那么 Promise.race 返回的 promise 永远是 pending 态

  • 如果传入的参数中不包含任何 promise, Promise.race 会返回一个处理中(pending)的 promise

  • 如果 iterable 包含一个或多个非 promise 值或已经解决的promise,则 Promise.race 将解析为 iterable 中找到的个值。

Promise.race 的实现

  1. Promise.race = function (promises) {

  2. //promises传入的是可迭代对象(省略参数合法性判断)

  3. promises = Array.from(promises);//将可迭代对象转换为数组

  4. return new Promise((resolve, reject) => {

  5. if (promises.length === ) {

  6. //空的可迭代对象;

  7. //用于在pending态

  8. } else {

  9. for (let i = ; i < promises.length; i++) {

  10. Promise.resolve(promises[i]).then((data) => {

  11. resolve(data);

  12. }).catch((reason) => {

  13. reject(reason);

  14. })

  15. }

  16. }

  17. });

  18. }

2. JSONP原理及简单实现

尽管浏览器有同源策略,但是 <script> 标签的 src 属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。 jsonp 通过插入 script 标签的方式来实现跨域,参数只能通过 url 传入,仅能支持 get 请求。

实现原理:

  • Step1: 创建 callback 方法

  • Step2: 插入 script 标签

  • Step3: 后台接受到请求,解析前端传过去的 callback 方法,返回该方法的调用,并且数据作为参数传入该方法

  • Step4: 前端执行服务端返回的方法调用

jsonp源码实现

  1. function jsonp({url, params, callback}) {

  2. return new Promise((resolve, reject) => {

  3. //创建script标签

  4. let script = document.createElement('script');

  5. //将回调函数挂在 window 上

  6. window[callback] = function(data) {

  7. resolve(data);

  8. //代码执行后,删除插入的script标签

  9. document.body.removeChild(script);

  10. }

  11. //回调函数加在请求地址上

  12. params = {...params, callback} //wb=b&callback=show

  13. let arrs = [];

  14. for(let key in params) {

  15. arrs.push(`${key}=${params[key]}`);

  16. }

  17. script.src = `${url}?${arrs.join('&')}`;

  18. document.body.appendChild(script);

  19. });

  20. }

使用:

  1. function show(data) {

  2. console.log(data);

  3. }

  4. jsonp({

  5. url: 'http://localhost:3000/show',

  6. params: {

  7. //code

  8. },

  9. callback: 'show'

  10. }).then(data => {

  11. console.log(data);

  12. });

服务端代码(node):

  1. //express启动一个后台服务

  2. let express = require('express');

  3. let app = express();


  4. app.get('/show', (req, res) => {

  5. let {callback} = req.query; //获取传来的callback函数名,callback是key

  6. res.send(`${callback}('Hello!')`);

  7. });

  8. app.listen(3000);

3. 实现一个数组去重的方法

法1: 利用ES6新增数据类型 Set

Set类似于数组,但是成员的值都是的,没有重复的值。

  1. function uniq(arry) {

  2. return [...new Set(arry)];

  3. }

法2: 利用 indexOf

  1. function uniq(arry) {

  2. var result = [];

  3. for (var i = ; i < arry.length; i++) {

  4. if (result.indexOf(arry[i]) === -1) {

  5. //如 result 中没有 arry[i],则添加到数组中

  6. result.push(arry[i])

  7. }

  8. }

  9. return result;

  10. }

法3: 利用 includes

  1. function uniq(arry) {

  2. var result = [];

  3. for (var i = ; i < arry.length; i++) {

  4. if (!result.includes(arry[i])) {

  5. //如 result 中没有 arry[i],则添加到数组中

  6. result.push(arry[i])

  7. }

  8. }

  9. return result;

  10. }

法4:利用 reduce

  1. function uniq(arry) {

  2. return arry.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);

  3. }

法5:利用 Map

  1. function uniq(arry) {

  2. let map = new Map();

  3. let result = new Array();

  4. for (let i = ; i < arry.length; i++) {

  5. if (map.has(arry[i])) {

  6. map.set(arry[i], true);

  7. } else {

  8. map.set(arry[i], false);

  9. result.push(arry[i]);

  10. }

  11. }

  12. return result;

  13. }

4. 清除浮动的方法有哪些?

当容器的高度为auto,且容器的内容中有浮动(float为left或right)的元素,在这种情况下,容器的高度不能自动伸长以适应内容的高度,使得内容溢出到容器外面而影响(甚至破坏)布局的现象。这个现象叫浮动溢出,为了防止这个现象的出现而进行的CSS处理,就叫CSS清除浮动。

  1. <style>

  2. .inner {

  3. width: 100px;

  4. height: 100px;

  5. float: left;

  6. }

  7. </style>

  8. <div class='outer'>

  9. <div class='inner'></div>

  10. <div class='inner'></div>

  11. <div class='inner'></div>

  12. </div>

1. 利用 clear 属性

在 <divclass='outer'> 内创建一个空元素,对其设置 clear:both; 的样式。

  • 优点:简单,代码少,浏览器兼容性好。

  • 缺点:需要添加大量无语义的html元素,代码不够优雅,后期不容易维护。

2. 利用 clear 属性 + 伪元素

  1. .outer:after{

  2. content: '';

  3. display: block;

  4. clear: both;

  5. visibility: hidden;

  6. height: ;

  7. }

IE8以上和非IE浏览器才支持:after,如果想要支持IE6、7,需要给 outer 元素,设置样式 zoom:1;

3. 利用 BFC 布局规则

根据 BFC 的规则,计算 BFC 的高度时,浮动元素也参与计算。因此清除浮动,只需要触发一个BFC即可。

可以使用以下方法来触发BFC

  • position 为 absolute 或 fixed

  • overflow 不为 visible 的块元素

  • display 为 inline-block, table-cell, table-caption

如:

  1. .outer {

  2. overflow: hidden;

  3. }

注意使用 display:inline-block 会产生间隙。

5. 编写一个通用的柯里化函数 currying

在开始之前,我们首先需要搞清楚函数柯里化的概念。

函数柯里化是把接受多个参数的函数变换成接受一个单一参数(初函数的个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

  1. const currying = (fn, ...args) =>

  2. args.length < fn.length

  3. //参数长度不足时,重新柯里化该函数,等待接受新参数

  4. ? (...arguments) => currying(fn, ...args, ...arguments)

  5. //参数长度满足时,执行函数

  6. : fn(...args);

  1. function sumFn(a, b, c) {

  2. return a + b + c;

  3. }

  4. var sum = currying(sumFn);

  5. console.log(sum(2)(3)(5));//10

  6. console.log(sum(2, 3, 5));//10

  7. console.log(sum(2)(3, 5));//10

  8. console.log(sum(2, 3)(5));//10

函数柯里化的主要作用:

  • 参数复用

  • 提前返回 – 返回接受余下的参数且返回结果的新函数

  • 延迟执行 – 返回新函数,等待执行

参考文章:

[1] CSS-清除浮动

[2] 详解JS函数柯里化

[3] JavaScript数组去重 

谢谢各位小伙伴愿意花费宝贵的时间阅读本文,如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和Star,您的肯定是我前进的大动力。 https://github.com/YvetteLau/Blog

关注公众号,加入技术交流群。

分享好友

分享这个小栈给你的朋友们,一起进步吧。

前端进阶之路
创建时间:2020-05-21 10:18:21
一位会拍照的程序媛来分享前端进阶之路
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 刘小夕
    栈主

小栈成员

查看更多
  • 小雨滴
  • ?
  • 栈栈
  • 叶子,你好
戳我,来吐槽~