记头条的一次笔试

四月初收到了头条的笔试邀请,打开连接后发现跳到了牛客网。面试前心中非常忐忑,毕竟大厂,而本身面试经验又很少。javascript

最后作下来,发现本身确实还有不少不足,尤为是手撸代码这一块。有些 js 方法就是记不住,好比日期获取年,下意识写了 date.getYear(),实际上是不对的,应该是 date.getFullYear()css

话很少说,看题吧。指望能给予同在面试的你或他一点帮助!html

题一:正则考点

给出一个段文本,将文本内容输出为特定内容前端

文本java

aa "55" $c b
nn (8*) q 12
true sdc 12 2w2
复制代码

输出node

输出

这是笔试的第一题,看到题目后下意识想这个文本是怎么输入进去的?在浏览器端,js 不能读取文件吧。反正非常纠结。面试

大概过了 5 分钟,迟迟没法答题。最后干脆忽略文本文件读取,直接当有换行符的文本字符串处理。可是换行这一块在大脑中搜索不到任何信息,唉,最后答了一个使用 /\S/ 正则表达式处理,而后进入下一题。正则表达式


如下是笔试完后写的:编程

<input class="file" type="file">
<script> var file = document.querySelector('.file') file.addEventListener('change', function(e) { var fileRead = new FileReader() fileRead.readAsText(e.target.files[0]) fileRead.onload = function() { var text = fileRead.result text = text.match(/[\s\S]+/g)[0] var textArr = text.split(/[\r\n]+/) var arr = [] textArr.forEach(function(item) { arr.push(item.split(/\s+/)) }) console.log(arr) } }) </script>
复制代码

由于题目没有说清楚,因此假想它是须要读取一个文本文件里面的内容。固然,也能够直接使用正则匹配那部分代码。设计模式

题二:布局考点

CSS 内容,一个简单的 sticky footer 布局。大体内容就是当页面高度不够时,页脚固定在页面底部;当页面高度足够时,页脚被页面内容推送下去。

<header>
 <h1>Header</h1>
</header>
<main>
  <p>Bacon Ipsum dolor sit amet...</p>
</main>
<footer>
  <p>Footer</p> 
</footer>
复制代码
html {
  height: 100%;
}
body {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}
main {
  flex: 1;
}
复制代码

题三:Date 与编程能力考点

一个时间转换问题,输入一个时间戳或时间字符串,而后与当前时间对比。

若是1分钟之内,显示刚刚;若是小于2分钟,显示2分钟前;若是小于1小时,显示1小时前;若是小于1小天,显示1天前;若是大于2天,显示日期字符串,"2019-03-20"

function format(time) {
    time = new Date(time)
    var interval = new Date() - time
    if (interval < 60 * 1000) {
        return '刚刚'
    } else if (interval < 60 * 60 * 1000) {
        return Math.floor(interval / (60 * 1000)) + '分钟前'
    } else if (interval < 24 * 60 * 60 * 1000) {
        return Math.floor(interval / (60 * 60 * 1000)) + '小时前'
    } else if (interval < 2 * 24 * 60 * 60 * 1000) {
        return Math.floor(interval / (24 * 60 * 60 * 1000)) + '小时前'
    } else {
        return time.getFullYear() + '-' + (addZero(time.getMonth() + 1)) + '-' + addZero(time.getDay())
    }
}

function addZero(number) {
    return number < 10 ? ('0' + number) : number
}

console.log(format('2019-4-10 9:25:01'))
console.log(format(1555040105650))
复制代码

题四:计算机基础考点

正数和负数,其原码、反码、补码的关系。

这题很简单,不过忽然一会儿想不起来了。当时记混了,说正数的补码是反码加一。

  • 正数:原码、反码、补码都相同
  • 负数:反码等于原码取反,补码等于反码加一

题五:设计模式考点

实现一个事件类 Event,包括 on(),off(),once(),emit() 方法

class Event {
    constructor() {
        this.events = {}
    }
    on(event, callback) {
        if (!this.events[event]) {
            this.events[event] = []
        }
        this.events[event].push(callback)
    }
    off(event, callback) {
        if (this.events[event]) {
            this.events[event] = this.events[event].filter(fn => callback !== fn)
        }
    }
    once(event, callback) {
        let _this = this
        if (!_this.events[event]) {
            _this.events[event] = []
        }
        const fn = function() {
            callback.apply(_this, arguments)
            _this.off(event, fn)
        }
        _this.events[event].push(fn)
    }
    emit(event, data) {
        if (this.events[event]) {
            this.events[event].forEach(function(callback) {
                callback(data)
            })
        }
    }
}

let event1 = new Event()
event1.once('abc', function(data) {
    console.log('1', data)
})
event1.on('abc', function(data) {
    console.log('2', data)
})
event1.emit('abc', 521)
event1.emit('abc', 520)
复制代码

题六:性能优化与事件委托考点

有一个表格 table,点击其中 td 元素,能够弹出元素里的文本内容。

<table class="table" border="1">
    <tr>
        <td>Hi</td>
        <td>Ha</td>
        <td>Ho</td>
    </tr>
</table>
<script> var table = document.querySelector('table') table.addEventListener('click', function(event) { if (event.target.nodeName.toLowerCase() === 'td') { alert(event.target.innerHTML) } }) </script>
复制代码

题七:正则与编程能力考点

数字金额千分位转换,如 14290023.2314,290,023.23,使用正则和非正则两种方式

老实说前些天我还特地看了千分位转换的,可是当时看别人的正则实现很头疼,因此只是过了下。笔试时,正则这一块没答出来。而后写了一个非正则的。

function formatRegExp1(number) {
    var pattern = /(?=(\B\d{3})+\.)/g
    return number.toFixed(2).toString().replace(pattern, ',')
}

function formatRegExp2(number) {
    var pattern = /(\d)(?=(?:\d{3})+\.)/g
    return number.toFixed(2).toString().replace(pattern, '$1,')
}

function format(number) {
    number = number.toFixed(2).toString()
    var dotIndex = number.indexOf('.')
    var part = number.substring(0, dotIndex)
    var flag = 0
    var result = ''
    for (var i = part.length - 1; i >= 0; i--) {
        result = part[i] + result
        if (i !== 0 && ++flag === 3) {
            result = ',' + result
            flag = 0
        }
    }
    return result + number.substring(dotIndex)
}

console.log(format(114290023))
console.log(format(2114290023))
复制代码

题八:this 指向考点

这道题在最开始写本文时漏掉了,想了想仍是补上,万一有人忽略了这个知识点呢(实际上是我本身不会这个知识点啦 -_-)

var obj1 = {
    name: 'obj1'
}
var obj2 = {
    name: 'obj2'
}
var obj3 = {
    name: 'obj3'
}
function say() {
    console.log(this.name)
}
var fn = say.bind(obj1).bind(obj2).bind(obj3)
fn()
复制代码

结果是 obj1,表面缘由是 bind() 只对第一次有效。可是这是为何呢?追本溯源,咱们来看看本质是啥。

bind() 的实现:

Function.prototype.bind = function(context) {
    const self = this
    const args = [...arguments].slice(1)
    return function F() {
        if (self instanceof F) {
            return new self(...args, ...arguments)
        }
        return self.apply(context, args.concat(...arguments))
    }
}
复制代码

题目代码:

var s1 = say.bind(obj1)
s1 = function() {
    return say.apply(obj1)
}

var s2 = s1.bind(obj2)
s2 = function() {
    return (function() {
        return say.apply(obj1)
    }).apply(obj2)
}

var s3 = s1.bind(obj3)
s3 = function() {
    return (function() {
        return (function() {
            return say.apply(obj1)
        }).apply(obj2)
    }).apply(obj3)
}

s3()
复制代码

由此能够看到 say() 方法的 this 指向就是 obj1

小结

整体来讲,题目是不难的,可是很考验候选人的综合能力。若是你也面试前端,而且未来也刚好遇到了套试题,不要高兴的太早。虽然他能帮助你经过笔试,可是后面的面试更难。

相关文章
相关标签/搜索