头条前端实习面试

一面二面紧挨着,视频面试只把记住的几个题记下来了
其余的都是我的 project 相关,没有列出来的必要

这是我放在印象笔记的,所以还有当时实现的代码
也不知道对不对,大家看的时候还能帮我找找错 嘿嘿 :)

js实现继承

这是我当时实现的

function Animal(){
    this.type = 'animal'
}

function dog(){
    Animal.call(this)
    dog.prototype = Animal.prototype
    dog.prototype.constructor = dog
}

不应该把Animal的原型给dog,这样对于dog原型链操作会影响到父类

正确的实现应该是

/**
 * js 继承实现
 */

const log = console.log

;
(function () {
    function Person() {
        this.name = "ownNamePerson"
    }
    Person.prototype.move = function move(params) {
        log('I am person, can move')
    }

    function Woman(n) {
        // 如果 父类不需要参数初始化
        Person.call(this)

        //如果父类需要参数初始化
        // super(arguments[2]) 翻译成
        //Person.call(this,arguments[2])

        this.name = "iamWoman"
        this.actualName = n
    }

    Woman.prototype = Object.create(Person.prototype)

    // 也可以这样写,不过多调用了一次Person的构造函数
    // Woman.prototype = new Person()

    Woman.prototype.inWomanPrototype = function inWomanPrototype(params) {

    }

    Woman.go = function go(params) {

    }

    Woman.prototype.constructor = Woman

    // 不能这么写,Woman 也需要有自己的原型链,这样Woman直接使用了Person的 prototype
    //当Woman.prototype.go = function name(params) {

    // }
    // 会影响Person的prototype
    // Woman.prototype = Person.prototype

    // ---------test-------------------------

    let woman = new Woman("iam woman name")

})();

实现bind

我当时的实现

Function.prototype.bind = function bind(fn) {
    let that = this
    let args = arguments
    return function () {
        fn.call(that, args)
    }
}

function test() {
    let that = this
}

let obj = {
    name: "wwc"
}

let newtest = test.bind(obj)
newtest()

正确的实现

let b = Function.prototype.bind
Function.prototype.bind = Function.prototype.bind || function bind(ctx) {
    let that = this
    let slice = Array.prototype.slice
    let bindArgs = slice.call(arguments,1)
    // bind可以传递参数,返回的被绑定的函数同样可以传参,所以这里先保存第一次bind的参数,忽略ctx,从 index 1 开始
    // 后面将调用时的参数传递进去,concat成一个array
    return function b(args) {
        // slice.call 将 arguments 转换为 Array
        that.apply(ctx,bindArgs.concat(slice.call(arguments)))
      // From https://stackoverflow.com/a/960870/7529562
      //NOTE: The slice function is intentionally generic; it does not require that its this value be an Array object. 
      //Therefore it can be transferred to other kinds of objects for use as a method.
      // Whether the slice function can be applied successfully to a host object is implementation-dependent.

      //Therefore, slice works on anything that has a length property, which arguments conveniently does.
    }
}

function test (a,b) {
    console.log(arguments)
}

let obj = {
    name: "wwc"
}

let newtest = test.bind(obj,'1','2')
newtest('3','4')

给一段代码判断执行顺序

// 判断下面输出顺序

console.log('begin');
setTimeout(() => {
    console.log('setTimeout 1');
    Promise.resolve()
        .then(() => {
            console.log('promise 1');
            setTimeout(() => {
                console.log('setTimeout2');
            });
        })
        .then(() => {
            console.log('promise 2');
        });
    new Promise(resolve => {
        console.log('a');
        resolve();
    }).then(() => {
        console.log('b');
    });
}, 0);
console.log('end');

给出代码判断this指向

let a = {b: function() { console.log(this) }, c: () => {console.log(this)}}

a.b()
a.c()

let d = a.b
d()

html文件解析过程,浏览器的重排,重绘

浏览器的渲染机制,为什么使用Virtual DOM,直接操作DOM的弊端是什么?

补全下面代码

function repeat(func, times, wait) {
    
}


// 输入
const repeatFunc = repeat(alert, 4, 3000);

// 输出
// 会alert4次 helloworld, 每次间隔3秒
repeatFunc('hellworld');
// 会alert4次 worldhellp, 每次间隔3秒
repeatFunc('worldhello')

我当时的实现

function repeat(func, times, wait) {
    let timer
    let count = 1

    function set(f) {
        timer = setTimeout(() => {
            func(f)
            if (count >= times) {
                clearTimeout(timer)
                return
            }
            set(f)
            count++

        }, wait)
    }

    return set
}


// 输入
const repeatFunc = repeat(alert, 4, 3000);

// 输出
// 会alert4次 helloworld, 每次间隔3秒
repeatFunc('hellworld');

这种实现如果调用两次 repeatFunc
一共会输出4次,因为 count 被公用了

而且只能接受一个参数

当时更好的写法没有想出来
面试官到最后给了一个写法,但是有错误,

改完之后:

async function wait(seconds) {
    return new Promise((res) => {
        setTimeout(res, seconds);
    });
}

function repeat(func, times, s) {
    return async function (...args) {
        for (let i = 0; i < times; i++) {
            func.apply(null, args);
            await wait(s);
        }
    };
}

let log = console.log
let repeatFunc = repeat(log,4,3000)
repeatFunc('HelloWorld')
repeatFunc('WorldHello')

输出

HelloWorld
WorldHello
HelloWorld
WorldHello
HelloWorld
WorldHello
HelloWorld
WorldHello

最初给的是

async function wait(seconds) {
    return new Promise((res) => {
        setTimeout(res, seconds);
    });
}

async function repeat(func, times, s) {
    return function (...args) {
        for (let i = 0; i < times; i++) {
            func.apply(null, args);
            await wait(s);
        }
    };
}

首先, 必须在 async 中使用 await
所以

return async function (...args) {
    
}

再者, async 函数返回值会被 Promise 包装
所以 async function repeat(){} 返回 Promise,并不是我们想要的 async function
所以这里去掉 async

#实习##前端工程师##面经##字节跳动#
全部评论
begin, end, setTimeout1, resolve(), a, resolve(), promise1, b promise2, setTimeout2
点赞 回复 分享
发布于 2019-02-25 16:58
大佬过了嘛
点赞 回复 分享
发布于 2019-02-25 16:34
你第一种写法,让count变量放到返回函数里,别放闭包不就不公用了么?
点赞 回复 分享
发布于 2019-02-25 22:33
楼主大几?
点赞 回复 分享
发布于 2019-02-25 22:38
有算法吗
点赞 回复 分享
发布于 2019-02-25 23:04
我给出最后一题我的正确实现 function repeat(func, times, wait) { function set(f) { let timer let count = 1 let print = () => { timer = setTimeout(() => { func(f) if (count >= times) { clearTimeout(timer) return } print(f) count++ }, wait) } print() } return set } // 输入 let log = console.log const repeatFunc = repeat(log, 4, 3000); // 输出 // 会alert4次 helloworld, 每次间隔3秒 repeatFunc('hellworld'); repeatFunc('1111')
点赞 回复 分享
发布于 2019-02-26 08:31
统一回复,我收到了头条的offer,但无奈的是入职的前一天被学校拦下来了,不让大三实习, 最后没办法,不能入职了,只能到暑假重新面试,真是尴尬
点赞 回复 分享
发布于 2019-03-08 08:34
在加上一题,第三面的,用css实现立方体,注意,是立方体。
点赞 回复 分享
发布于 2019-03-08 08:36
最后一个js题直接用闭包就好了 function repeat(func, times, wait) { var run = function() { let currentTime = 0 let content = arguments[0] return (function next() { setTimeout(() => { func(content) currentTime++ if (currentTime < times) { next() } }, wait) })() } return run }
点赞 回复 分享
发布于 2019-03-22 10:35
function repeat(func, times, wait) { var run = function() { let currentTime = 0 let content = arguments[0] return (function next() { setTimeout(() => { func(content) currentTime++ if (currentTime < times) { next() } }, wait) })() } return run }
点赞 回复 分享
发布于 2019-03-22 10:36
function wait(seconds) {   return new Promise(resolve => {     setTimeout(resolve, seconds);   }); } function repeat(func, times, s) {   return async function (...args) {     for (let i = 0; i < times; i++) {       func.apply(null, args);       await wait(s);     }   }; } const repeatFunc = repeat(alert, 4, 2000); repeatFunc("hellworld");//会alert4次 helloworld,每次间隔3秒
点赞 回复 分享
发布于 2019-09-07 17:14
编程题很多吗?基础问的多吗?
点赞 回复 分享
发布于 2019-12-13 00:53
repeat那道题,我也给一个思路,大家可以参考 function* inner(func, text, times) {     for (let i = 0; i < times; i ++) {         yield func(text)     } } function repeat2(func, times, interval) {     return function (text){         let innerFunc = inner(func, text, times)         let inter = setInterval(() => {             let res = innerFunc.next()             if (res.done) {                 clearInterval(inter)             }         }, interval)     } }
点赞 回复 分享
发布于 2021-01-03 19:40
6***委托:currentTarget与target有什么区别与联系?
点赞 回复 分享
发布于 2021-02-22 16:29

相关推荐

10.31一面45min 11.4二面hr面速通最搞笑的一集。因为我简历上放了博客和项目地址。所以开局直接说爬了一下我的博客看了我的项目网站挺不错的hhh。最难蚌的是我博客上放了一个前端面经。面试官突然灵机一动唉&nbsp;那我就你的面经问你问题吧!(我:这不成了免费题库了???)虽然是我总结的,但是其实有一些细节忘了。(三道输出题第一次全答错了还好第二次基本答对了。)下面就是正文烤面筋:1.flex&nbsp;1和flex&nbsp;auto区别(举例,一个父容器设置display:&nbsp;flex;&nbsp;width:1000px;左边一个子元素width:&nbsp;100px;右边的这样设置flex:1;&nbsp;width:200px;&nbsp;flex-basis:300px;)问:右边的有多宽?懵了,说应该200px,不知道对不对。gpt给的是900px。2.子选择器结合相邻兄弟选择器,设置了一个color:&nbsp;red;&nbsp;问哪一个div是红色。还有结合伪类和属性选择器的问题。(答对了但没完全说清楚。)3.本来说看看HTML部分因为没有就没问4.sort会改变原数组吗,有没有不改变原数组的排序方法(冒泡,选择,插入?面试官:没那么复杂)5.看到我总结的深浅拷贝,讲讲JSON实现的深拷贝有什么缺点。(有丢失函数日期undefined等问题,无法解决循环引用,原型链丢失。)怎么解决循环引用?(手动实现,用weakmap)6.因为我总结了事件循环原型链那些,出了三道输出题目见结尾。7.讲讲promise,还有all,allSettled,race,any的各自作用。8.问了vue3的ref还有reactive的区别(对数组进行包装该用哪个?又答错了,不过给我很详细的说了一下为什么用ref,其实ref底层也是reactive)9.vuex和pinia实现持久化需要插件,为什么不能自定义一个全局变量代替呢?(因为方便管理?又是一个不知道的问题)10.反问问了下对我技术提升的建议,探探口风。本来以为寄了,听起来还行,可能给他逗笑了两次,因为我博客的面经有些是空着的,我直接说空着的还没总结就是不会问了下技术栈,详细的跟我讲了一下,还有告诉我有三面就总结到这里吧,不管过不过还是挺开心的。难得遇到边聊天边问的面试了,虽然我做了一个网易云音乐的项目,当时快手面试官直接黑着脸说烂大街了。但是这个面试官笑着说他刚毕业的时候也是做的这个,还问我是不是B站学的还是自己做的hhh。(当然是独立知识产权啦!)11.4二面七分钟速通产品经理面的&nbsp;开局就说不用说技术细节随便聊了聊天11.4当天约了hr面11.7oc
我已成为0offer的糕手:你这面试官水平不行,自己背的八股就是错的,ref底层和reactive没关系,数组的响应式两个也都可以做。这两个最大区别在于.value是属性,所以你重新赋值一个对象是可以的,因为proxy拦截会把它变成响应式。但是reactive不行,因为他本身就返回一个proxy拦截的对象,因为要实现响应式,然后你又重新赋值一个对象类型的话,相当于把proxy给破坏了,就不是响应式了,而ref你修改的只是对象里面value的值,对象本身没有被破坏,相当于对象里面嵌套对象。和数组本身没关系,是要不要重新赋值的问题,只是修改内部的话这两个都可以做响应式
查看9道真题和解析
点赞 评论 收藏
分享
评论
7
119
分享
牛客网
牛客企业服务