记录一次蚂蚁金服前端电话面试

坐标杭州,18年毕业,算上实习一年半开发经验。是外派到蚂蚁的面试,后面两面都是阿里的面试官。
本来是给我发的在线测评,但是那边服务器出现问题,我一直打不开网页,最后只好以电话问答的形式。下面我写的大部分都是测评里的题目,部分是电话里新增的题目。。。

  1. 尽量使用尽可能多的方式实现子元素的垂直水平居中

    <div class="father">
        <div class="child">  
        </div>
    </div>
    
    <style>
        .father {
            width: 300px;
            height: 300px;
        }
        .child {
              
        }
    </style>
    

child分很多种情况,大致说一下

  • 行内元素:text-align + line-height
.father{
  text-align: center;
  line-height: 300px;
}
  • 定宽定高:absolute + margin
.father{
  position: relative;
}
.child{
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -150px 0 0 -150px;
}
/* 或者 */
.child{
  position: absolute;
  left: 0;
  top: 0; 
  right: 0; 
  bottom: 0;
  margin: auto;
}
  • 不定高:absolute + translate
.father{
  position: relative;
}
.child{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}
  • 不定高:flex
.father{
  display: flex; 
}
.child{
  margin:auto;
}
/* 或者 */
.child{
  justify-content: center;
  align-items: center;
}
  • table方式:
.father{
  display: table; 
}
.child{
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
  1. 尽可能多的方式实现如下三栏布局,要求 .main 在中间显示
<div class="container">
  <div class="main"></div>
  <div class="sub"></div>
  <div class="extra"></div>
</div>
  • 浮动
  • flex布局:利用order属性(排序,这个没答上来)
  • gird布局:grid-template-areas
  1. 执行下面的代码,输出结果是什么?
console.log(+false) // 0, 这里是一元运算符进行的弱类型转换,相对应的 +true 则返回 1
console.log('1' + 2 + '3' + 4) // '1234' 遇到字符串就会拼接
console.log(4 + 3 + 2 + '1')  // '91' 先加在一起再拼接
  1. 运行下面的代码,输出什么?
var x = 3;
var foo = {
  x: 2,
  baz: {
    x: 1,
    bar: function() {
      return this.x;
    }
  }
}
var go = foo.baz.bar;

console.log(go());  // 3
console.log(foo.baz.bar()); // 1

这题考的是this的指向:

this由调用者提供,由调用函数的方式来决定。如果是一个对象调用的函数,则this指向该对象,比如foo.baz.bar()。如果函数独立调用比如go(),那么该函数内部的this,则指向undefined。但是在非严格模式中,它会被自动指向全局对象window。

  1. 实现以下函数,使得输入的字符串逆序输出
function reverse(str) {
  let res = str.split('');
  return res.reverse().join('');
}

reverse('hello world!'); // output: '!dlrow olleh'

进阶问题

'hello world!'.reverse();  // output: '!dlrow olleh'
  • 这个问题需要给String的原型上添加方法,但是要考虑有一些改造:
String.prototype.reverse = function reverse() {
  let res = this.split('');
  return res.reverse().join('');
}
  1. 实现sleep 函数
    要求用法:
/**
- 使当前运行的异步操作(promise 或者 async)停止等待若干秒
- 
- @param ms */
(async () => {
  console.log('hello')
  await sleep(2000) // 等待两秒
  console.log('world')
})()
const sleep = (ms) => {
  new Promise(resolve, reject) {
    setTimeOut(() => {
      resolve(); // 大致这样?
    }, ms)
  }
}
  1. 实现throttle 节流函数

    用法:

    const throFun = () => console.log('hello');
    const thro = throttle(throFun, 300);
    document.body.onscroll = () => {
      thro();  // 调用至少间隔 300 毫秒才会触发一次
    }
    
    /**
    - 频率控制,返回函数连续调用时,action 执行频率限定为 1次 / delay
    - @param delay  {number}    延迟时间,单位毫秒
    - @param action {function}  请求关联函数,实际应用需要调用的函数
    - @return {function}    返回客户调用函数 */
    function throttle(action, delay) {
      var previous = 0;
      // 使用闭包返回一个函数并且用到闭包函数外面的变量previous
      return function() {
        var _this = this;
        var args = arguments;
        var now = new Date();
        if(now - previous > delay) {
            action.apply(_this, args);
            previous = now;
        }
      }
    }
    
  2. 实现debounce 防抖函数

    用法:

    const throFun = () => console.log('hello');
    const thro = debounce(throFun, 300);
    document.body.onscroll = () => {
      thro();  // 若一直调用则不会执行,空闲时间大于 300 毫秒才会执行
    }
    
    /**
    - 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 delay,action 才会执行
    - @param delay   {number}    空闲时间,单位毫秒
    - @param action {function}  请求关联函数,实际应用需要调用的函数
    - @return {function}    返回客户调用函数 */
    function debounce(action, delay) {
      var timer; // 维护一个 timer
      return function () {
          var _this = this; // 取debounce执行作用域的this
          var args = arguments;
          if (timer) {
              clearTimeout(timer);
          }
          timer = setTimeout(function () {
              action.apply(_this, args); // 用apply指向调用debounce的对象,相当于_this.action(args);
          }, delay);
      };
    }
    
  3. 数组去重有哪些方法?

const arr = [1,2,3,4,4,3,2,1];
// 方法一:new Set ES6
return [...new Set(arr)]; // 这里又问到我...的用法

// 方法二:双层for循环 (然后说这样性能不好,让我只用一层for循环的方法)
function unique(arr){
  var res=[];
  for (var i = 0; i < arr.length; i++) {
    for (var j = i+1; j < arr.length; j++) {
      if (arr[i] === arr[j]) {
        ++ i;
        j = i;
      }
    }
    res.push(arr[i]);
  }
  return res;
}

// 方法三:单层for循环 + indexOf
function unique(array){
    var res = [];
    for(var i = 0; i < array.length; i++) {
        //如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
        if (array.indexOf(array[i]) === i) {
            res.push(array[i])
        }
    }
    return res;
}
// 方法三点三:或者这样
function unique(array){
    let res = [];
    for(var i = 0; i < array.length; i++) {
        if (res.indexOf(array[i]) === -1) {
            res.push(array[i]);
        }
    }
    return res;
}

// 方法四:面试官说如果可以容忍改变原有数组的情况下,怎么改进性能更好
function unique(array){
    // 注意这里一定要倒叙for循环,否则会出现问题
    for(var i = array.length - 1; i > 0; i--) { 
        if (array.indexOf(array[i]) !== i) {
            array.splice(i, 1);
        }
    }
    // 因为少声明一个变量,节省了内存空间(虽然可以忽略不计,但是面试嘛~)
    return array;
}
  1. 场景题,考察事件代理,事件监听,DOM自定义属性等

题目描述:

  • 网页中有一个元素A,它有个data-href属性,里面存放一个链接地址🔗
  • 实现一个函数,当任意点击时,如果点击的元素就是A或其上层节点中找到A,则进行链接跳转

实现思路:

  • 首先给window添加点击事件的监听,然后先声明一个中间变量targetNode记录节点
  • 然后循环判断当前节点targetNode是否存在data-href属性
  • 如果存在则进行跳转,break。不存在则将该节点的父节点赋值给targetNode
  • 一直循环到判断targetNode是最外层节点为止

面试过后整理的代码:

window.addEventListener('click', (e) => {
    let targetNode = e.target
    while (targetNode !== document) { // 只要当前节点不是最外层document
        console.log(targetNode)
        if (targetNode.getAttribute('data-href')) { //  其实用hasAttribute更合适
            window.open(targetNode.dataset.href)
            break
        } else { // 没找到就继续往上找
            targetNode = targetNode.parentNode
        }
    }
})

总结:

  • 感觉这道题出的很好,回答过程中面试官也一直引导我的思路,比如最开始我想到判断节点是否为上下级关系的方法用DOM的contains()方法,然后面试官说可能有兼容性问题,最好用原生api。然后我就说用parentNode。后来我查了一下MDN,发现contains这个方法就是原生的api,还是IE率先引入的方法呢😂:
    contains兼容性

    但是这也不是重点,重点是用contains这个方法不能实现这个场景,因为你需要父节点(上层节点)是已知的。但这个场景是通过已知子节点(点击事件返回的target)来向上寻找节点。
  • 我说到用dataset获取自定义属性的时候,面试官说考虑到兼容性,有没有别的方法。我回答getAttribute()
  • 在说怎么一层一层的往上找节点的时候,最开始我想到了用递归调用函数,面试官当即打断我说没有必要,而且浪费性能。然后提示我说有什么循环的方法。最后想到了while
  1. 其他问题

  • ES6数组有哪些方法
  • React使用中用过哪些状态管理工具,紧接着问了redux和mobx的区别,面试遇到三四次了,故总结一下:

1.Redux 鼓励一个应用只用一个 Store,Mobx 鼓励使用多个 Store;
2.Redux 是函数式编程,而Mobx的模式是面向对象的;
3.Redux 使用“拉”的方式使用数据,这一点和 React是一致的,但 Mobx 使用“推”的方式使用数据;
4.Redux 鼓励数据范式化,减少冗余,Mobx 容许数据冗余,但同样能保持数据一致。
5.Redux更严格,必须调用reducer触发action来改变state, Mobx 最初的一个卖点就是直接修改数据,但是实践中大家还是发现这样无组织无纪律不好,所以后来 Mobx 还是提供了 action 的概念。和 Redux 的 action 有点不同,Mobx 中的 action 其实就是一个函数,不需要做 dispatch。如果想强制要求使用 action,禁止直接修改 observable 数据,使用 Mobx 的 configure,如下:

import {configure} from 'mobx';

configure({enforceActions: true});
  • 让讲了一下react的虚拟DOM,简单讲一下diff算法原理
  • React中key的作用
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容