字节跳动暑期实习生一面面经 大三

身份:双非本科大三,大二从小程序开始学起前端,之后自学前端。

自我介绍

了解box-sizing吗?

这里脑子没转,说了不太了解。。面试官特别好,是会引导着你去回答问题的。

了解盒模型吗?

了解的,盒模型分为标准盒模型和IE盒模型。标准盒模型是包括margin,padding,border,content。标准盒模型的width只包括content。而IE盒模型width包括了border和padding。这也更符合我们平时对于一个盒子的认知。

面试官:所以这个box-sizing设置为content-box时就是标准盒模型,border-box就是IE盒模型。

js中数据类型有哪些?

基本数据类型boolean,number,string,null,undefined。

还有引用数据类型,object

基本数据类型存在栈中,引用值的栈中存的是堆中对象的地址。具体戳->JavaScript中基本数据类型和引用数据类型的区别

怎么加事件监听?(手写)

var a = document.getElementById("a");
a.onclick(function(){
    alert(a.tagName)
})

还有没有其他方式呢?

 addEvenListener,有三个参数,第一个是添加事件名,第二个是给事件添加的函数,第三个是个布尔值,表示是否在冒泡阶段获取监听,true是冒泡阶段,false是捕获阶段。

var a = document.getElementById("a");
a.addEventListener('click',function(){
        alert(a.tagName)
    }, true)

了解事件传播机制吗?

事件传播机制分为三大部分:捕获,目标,冒泡。捕获是时间对象从window派发到目标对象父级的过程,目标是事件对象到目标元素的阶段,冒泡是从目标对象父级到window的过程。

了解this吗?

this永远指向的是最后调用它的对象。然后说的有点错误,面试官又纠正了一下。

你刚刚提到了修改this的三个方法,可以讲一下吗?

分为call,apply,bind。call和apply都是立即执行的,他俩主要的区别在于传参的时候,第一个参数都是this要指向的对象,而call第二个参数可以到第n个,用逗号隔开,是传入的参数列表。apply只有第二个参数,是参数的数组。bind返回的是一个函数,需要调用才可以改变。

ok,可以手写一个bind吗?

Function.prototype.bind2 = function(target) {
    var target = target || window;
    return function() {
        return apply(target)
    }
}

这里写的有点问题,所以面试官给我写了个代码,让我看看代码最后输出什么,然后来解决这个问题。面试官真的太温柔了!!!

正确的在这里:来自:总结了17年初到18年初百场前端面试的面试经验(含答案)

(1)初始版本

Function.prototype.bind=function(obj,arg){
  var arg=Array.prototype.slice.call(arguments,1);
  var context=this;
  return function(newArg){
    arg=arg.concat(Array.prototype.slice.call(newArg));
    return context.apply(obj,arg);
  }
}
复制代码

(2) 考虑到原型链

为什么要考虑?因为在new 一个bind过生成的新函数的时候,必须的条件是要继承原函数的原型

Function.prototype.bind=function(obj,arg){
  var arg=Array.prototype.slice.call(arguments,1);
  var context=this;
  var bound=function(newArg){
    arg=arg.concat(Array.prototype.slice.call(newArg));
    return context.apply(obj,arg);
  }
  var F=function(){}
  //这里需要一个寄生组合继承
  F.prototype=context.prototype;
  bound.prototype=new F();
  return bound;
}

下面是面试官考的运算结果题:

Function.prototype.bind2 = function(target) {
    var target = target || window;
    var that = this;
    return function() {
        return that.apply(target)
    }
}

var name = 123;
var foo = { name: 789 }; 
var obj = {
    name: 345,
    sayName: function() {
         console.log(this.name);
    }
}

var sayName = obj.sayName.bind2(foo);
sayName();

经过我百般脑残后,终于是说出了这个sayName应该输出的是什么,是789。但是面试官说我写的bind输出的是123,让我看看为什么。 然后我加了个that,好像不是很对,他说我没有考虑bind后面传参的问题,还有原型链的继承问题。

说一下原型链和原型链的继承吧

原型链就是用来实现继承父对象的属性和方法的。当在子对象找不到对应的属性和方法的时候,就会通过原型链向上查找,直到找到或者到object原型。原型链的继承我看到一个最优化的继承,叫做圣杯模式。他是通过增加一个中间对象来实现的原型链的继承。这样当子对象修改他原型的方法的时候就不会同时修改父对象的方法了。

说一下cookie,sessionStorage,localStorage的区别?

cookie 是网站为了标识用户信息而存储在本地(client side)上的数据,一般会加密

cookie数据始终在同源请求中传递,即在浏览器和服务器之间来回传递

seesionstorage 和 localstorage 不会把数据发到服务器,仅在本地保存

存储大小,cookie的大小不能超过4k
sessionstorage 和 localstorage 的大小一般在5M以上,比cookie大的多

有效时间不同

localstorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据

sessionstorage 数据在当前浏览器窗口关闭后自动删除

cookie  设置的cookie过期之前一直有效,即使窗口或者浏览器关闭

ok,给你出道题,这是一个嵌套数组,把它拆成平铺的数组。

var arr = [1, [2, [3]], [[[4, 5], 6], 7], 8]

 第一个使用的是es6中的flat方法,面试官说,不可以用这个哦

那换一种,将数组转化成了字符串,然后通过逗号分隔,用Number方法提取数字

面试官:那我要是数组里还有字母呢~

好吧。。那用递归调用,我定义了一个全局空数组result,然后递归判断给定的数组的元素是不是还是数组,是就继续调用,不是就push进result中。

面试官:能不能不用全局变量呢~

好吧。。那就传值进去,最后返回。。。返回这卡了半天,也不知道想啥呢,还是面试官小哥哥提示我的。。

function x(arr) {
    var arr1 = (arr + '').split(',')
    var arr2 = arr1.map(function(i) {
        return Number(i)
    })
    return arr2
}


function fun (arr,rusult) {
    for (var i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) fun(arr[i],result)
        else result.push(arr[i])
    }
    return result
}
fun(arr, [])

 你有什么问题想问我吗?

我因为是从微信小程序开始学起前端的,自我感觉基础还不是很好,想请你对我的面试做个点评吧!

恩正像你说的,基础这方面还是要再继续学习。不过后面给你做的题,经过提示也做出来啦,总体还是可以的。剩下说啥忘了。。

我在投简历的时候看到咱们是有微信小程序的方向吗?

恩我们是有小程序,不过是自研的,和微信小程序还不太一样。

 

非常宝贵的一次经历!很喜欢这位面试官,这次面试让我对自己有了一些信心,希望以后能越面越顺利!也希望能有字节跳动的二面!

你可能感兴趣的:(面试)