腾讯前端面经一面

写在前面

  博主现在读大三,前端小白一只,上一个随笔发出了最近的美团一面的面试题与注意事项,这里博主整理了一下腾讯二月二十九日的第一次面试题与解题思路,注意事项,希望对大家的面试有所帮助。

面试题相关

垂直居中问题

题目
  屏幕正中间有一个元素A,随着屏幕宽度的增加,需要满足以下条件:

  • A元素垂直居中于屏幕中央;
  • A元素距离屏幕左右边距各10px;
  • A元素里面的文字”A”的font-size:20px;水平垂直居中;
  • A元素高度始终为A元素宽度的50%;(如果搞不定可以实现为A元素的高度固定为200px)
    请用htmlcss实现

图1


解题思路
  这个题目考察的是主要是垂直居中的措施,具体的方法大家可以自行查找,这里贴出我自己的代码。主要的地方是使用calc计算属性去设置左右边距,然后height也顺带实现A元素高度始终为A元素宽度的50%

    <!-- CSS -->

    * {
        margin: 0;
        padding: 0;
    }

    body {
        width: 100%;
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .fa-area {
        position: relative;
        width: calc(100% - 20px);
        height: calc(50% - 10px);
        margin-left: 10px;
        background-color: #376AF3;
    }

    .fa-area>div {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        color: #fff;
        font-size: 20px;
    }

    <!-- html -->

    <div class="fa-area">
        <div>A</div>
    </div>

arguments

题目
  函数中的arguments是数组吗?若不是,如何将它转化为真正的数组?


解题思路
  这个题目考察对arguments的认识,以及call的使用,并没有提及手写call函数。

不是
转化方案:
arguments = [].slice.call(arguments);

隐式类型转换

题目
  请说出以下代码打印的结果

if([] == false) {console.log(1);}
if({} == false) {console.log(2);}
if([]) {console.log(3);}
if([1] == [1]) {console.log(4);}

解题思路
  这个题目主要考察对JS隐式转换的知识。
  值得注意的是,当使用 == 的时候,JS会将两侧数据转换为number值,再进行==判断,再转换为bool值。所以第一行会打印,第二行不会打印(这里的原因是,对象转number的时候,会调用toString()方法,返回一个字符串直接量,js将这个字符串转换成数字类型,并返回这个数字。这一段在《JavaScript权威指南》可以查到)。
  而若直接空数组转bool的话,所有的对象object,用于判断条件时就会被转化为true,所以第三行会打印。
  第四行的话,对象是引用类型,看起来都是一样的两个空数组,但是其实是不同的两个对象,在内存中的地址是不同的,所以第四行不打印。
  这里当时不太明白,所以只根据自己的想象打出了答案,但是没有讲出1、2、3行的理由。

答:1 3

异步问题

题目
  请说出以下代码打印的结果


async function async1(){
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2(){
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
});
async1();
new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
console.log('script end');

解题思路
  这个题目主要考察对JS异步、JS执行机制的知识。
  这题其实我没有很大把握,所以面试官准许我放在node环境下打印后问我原因,然后根据async1、async2的样子写出对应的Promise语句。

new Promise((resolve) => {
    console.log('async1 start');
    new Promise((resolve1) => {
            console.log('async2');
        })
    }).then(() => {
        console.log('async1 end');
    })

JS是一个单线程语言,所以是按照语句的执行顺序执行的。一般任务分为两类

  • 同步任务:该任务在主线程上排队,一次执行
  • 异步任务:没有立马执行的任务,放在任务队列中执行

而除了这两种,任务还可以分为以下两种

  • 宏任务:整体代码script,setTimeout,setInterval等
  • 微任务:Promise,process.nextTick等

  在event loop中,宏任务执行完后,会判断内部有无可执行微任务,若有则执行可执行微任务,若无则执行接下来的宏任务。

  所以我们可以这么分析这类题目:先执行宏代码,遇到微任务就先加入队列等待执行,宏任务执行完后按入队列顺序执行,再执行setTimeout队列代码。

答:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout

this指向

题目
  以最小的改动解决以下代码的错误(可以使用ES6)


const obj = {
    name: 'jsCoder',
    skill: ['es6', 'react', 'angular'],
    say: function () {
        for (var i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(function() {
                console.log('N0.' + i + this.name);
                console.log(this.skill[i]);
                console.log('------------------');
            }, 0);
            console.log(i);
        }
    }
}
obj.say();

// 期望得到以下结果
1
2
3
N0.1 jsCoder
es6
------------------
N0.2 jsCoder
react
------------------
N0.3 jsCoder
angular
------------------

解题思路
  这个题目主要考察对this指向、闭包的知识。
  最初运行的时候是报错了,显示数组越界,所以for循环里的i改成了i + 1,然后var i = 0改成了let i = 0处理了这里的闭包问题(我并不希望setTimeout里面的i全是4),然后this的指向我是使用了匿名函数取代了setTimeout里面的函数,或者大家可以在外面使用var that = this;来绑定this
  以下是我的答案:

const obj = {
    name: 'jsCoder',
    skill: ['es6', 'react', 'angular'],
    say: function () {
        for (let i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(()=> {
                console.log('N0.' + (i + 1) + this.name);
                console.log(this.skill[i]);
                console.log('------------------');
            }, 0);
            console.log(i + 1);
        }
    }
}
obj.say();

手写bind

题目
  实现Function的bind方法


解题思路
  这个bind方法在各个博客中都有很详细的原理与解析,所以这里我只将我的答案贴上,希望轻喷。

Function.prototype.bind = function (context) {
    // 这里要存一下this而不能把返回里的函数对象转为匿名函数
    // 因为这本身就是为了因为bind()函数发布在ES5中,不能很好的兼容所有浏览器
    var self = this;
    return function () {
        return self.apply(context, arguments);
    }
}

手写节流函数

题目
  实现一个节流函数
  这里其实是用了一个很复杂的图来说节流的好处,然后让我写节流。
  当时我不会写节流函数,但是我会写防抖,所以我和面试官说我的项目上的防抖的原理,所以面试官让我先写了一个防抖函数,写完之后解释了节流函数,再让我写了一次。不得不夸一下,这个面试官非常的有耐心,节流和要点都有和我讲到,所以我才能安心写出这个我没接触过的函数。下面贴出此题一种解法。


解题思路

window.onload = () => {
    // 这两行代码大家可以不用管,是因为我想演示效果,所以大家随便用一个点击div的事件就可以
    let myInput = document.getElementById('myInput');
    let inputSet;
    // 节流函数
    myInput.addEventListener('click', () => {
        if (!inputSet) {
            // 第一次执行
            console.log(myInput.value);
            inputSet = setTimeout(() => {
                inputSet = undefined;
            }, 500);
        }
    })
}

算法题

题目
  手写排序算法
  这里面试官是问了你知道哪些常见的排序算法?然后我说冒泡排序、快速排序、归并排序、希尔排序(注意这个希尔我是不会的,所以千万放后面说,如果面试官对快速或归并感兴趣,会让你停下来的,别硬讲你不懂的技术,不然很拉低面试官的印象分),然后他让我写一个快速排序,这个我有写过,但是当时写的时候里面的逻辑没有理清,面试官一直陪着梳理思路,最后还是写完了这个算法。


解题思路

function sort(arr, flag) {
    function swap(arr, a, b) {
        let temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
    function partition(arr, left, right) {
        // 基准
        let pt = arr[right];
        // 指针
        let storeIndex = left;
        for (let i = left; i < right; i++) {
            if (arr[i] < pt) {
                swap(arr, i, storeIndex);
                storeIndex++;
            }
        }
        swap(arr, right, storeIndex);
        return storeIndex;
    }
    function quickSort(arr, left, right) {
        if (left > right) return;
        var storeIndex = partition(arr, left, right);
        quickSort(arr, left, storeIndex - 1);
        quickSort(arr, storeIndex + 1, right);
    }
    quickSort(arr, 0, arr.length - 1);
    return arr;
}
console.log(sort([1, 4, 2, 10, 5, 7, 2, 4, 6, 7]));

总结

  其实一面都是一些很基础的问题,但是它会将考察点掺杂在所有的问题中,一旦你触及了这个方面,他就会问你这个相关知识,所以你需要在问题中提炼出他想问的知识点,不要等他来问:”这个可以用call来做吗?”,而是你自己在回答的时候就觉察出来,并直接展示出来。
  但是对于你不熟悉的技术,千万别硬掺杂在一系列名词中吐露出来,面试官万一就觉得你可能不会,硬问这个,你就难顶了。
  希望大家都能收获自己期望的offer!

版权声明:本文为JobsOfferings原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/JobsOfferings/p/my_tencent_first.html