【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23

北京京东科技 日常实习一面 21/12/22

体验极佳的一次面试!面试官大大贼温柔,循循善诱地帮助我把问题捋出来;

另外问题也都对我这个初学者很友好,超级简单哈哈哈

面试完半个小时二面电话就来了,约到了明天上午十一点

聊项目

  • 说下你在这个大型外包项目中负责的内容
  • 说下地图中的接口是如何用的

后来才知道,面的这个部门其中一个业务就是为政府做智慧城市相关的业务~真的巧!我最近在忙活的外包项目也是这个主题的说!

CSS

对CSS3动画有了解么

无。面试官大大表示这个是加分项 其实实际开发也用不太上

对盒子模型有了解嘛~

这里我还写过3篇文章嘞~(但是面试时候没想起来XD)

【青训营】做面试题般回顾前端基础知识CSS篇 - 2 CSS盒模型那些有趣的知识点 - 掘金 (juejin.cn)

【青训营】做面试题般回顾前端基础知识CSS篇 - 3 标准盒模型中块元素宽度&总宽度的问题 - 掘金 (juejin.cn)

由box-sizing属性引出的对盒模型的思考 - 掘金 (juejin.cn)

CSS3 中的盒模型有以下两种:标准盒子模型、IE 盒子模型
【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第1张图片
【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第2张图片

盒模型都是由四个部分组成的,分别是 margin、border、padding 和 content。

另外我提到了——

标准盒模型和 IE 盒模型的区别在于设置 width 和 height 时,所对应的范围不同:

  • 标准盒模型的 width 和 height 属性的范围只包含了 content,
  • IE 盒模型的 width 和 height 属性的范围包含了 border、padding 和 content。

可以通过修改元素的 box-sizing 属性来改变元素的盒模型:

  • box-sizeing: content-box表示标准盒模型(默认值)
  • box-sizeing: border-box表示 IE 盒模型(怪异盒模型)

移动端适配要咋做呢?

【1】使用特殊的布局单位(追问:rem em的区别?)

em 和 rem:它们相对于 px 更具灵活性,它们都是相对长度单位,它们之间的区别:em 相对于父元素,rem 相对于根元素。

二者的详细区别:

  • em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认 16px)。(相对父元素的字体大小倍数)。
  • rem: rem 是 CSS3 新增的一个相对单位,相对于根元素(html 元素)的 font-size 的倍数。作用:利用 rem 可以实现简单的响应式布局,可以利用 html 元素中字体的大小与屏幕间的比值来设置 font-size 的值,以此实现当屏幕分辨率变化时让元素也随之变化。

【经典】子盒子相对于父盒子做水平垂直居中?

抛出之前写得一篇文章 我觉得很好理解&很全面了~

【青训营】做面试题般回顾前端基础知识CSS篇 - 4 弹性布局与经典面试题CSS实现垂直居中 - 掘金 (juejin.cn)

刚才聊到了栅式布局 那么flex都有啥属性呢?

flex布局的概念:

flex 布局的基本概念 - CSS(层叠样式表) | MDN (mozilla.org)

总结几个常用方法:

更改flex方向 flex-direction

用flex-wrap实现多行Flex容器

以上两个属性的简写:简写属性 flex-flow

flex-grow - CSS(层叠样式表) | MDN (mozilla.org)

flex-shrink - CSS(层叠样式表) | MDN (mozilla.org)

flex-basis - CSS(层叠样式表) | MDN (mozilla.org)

当然!这些如果不常用 根!本!记!不!住!

所以就有了下面这个小练习

推荐一个5.2Kstars的仓库(截至21/10),在线尝试地址戳这里

然而!在我之前都做了一遍的前提下 在面试时候除了最基础的居中的属性,其他flex相关的属性都没答上来这里就很难受了 所以要时常用啊!

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第3张图片

刚才提到了高度塌陷的概念(在垂直居中时候提到的)可以说一下是什么情景 具体怎么解决么?

  • 子盒子设置浮动,父盒子可能会高度塌陷
  • 给父盒子设置一个overflow:hidden; 这样父盒子就是一个BFC了(挖坑。)高度塌陷消除~

刚才提到了BFC的概念(高度塌陷的时候)简单说一下BFC的作用

这个当时没太说清楚 只是举了个自适应双栏布局的例子(自己挖坑自己跳啊!),查阅下资料——

先来看两个相关的概念:

  • Box: Box 是 CSS 布局的对象和基本单位,⼀个⻚⾯是由很多个 Box 组成的,这个 Box 就是我们所说的盒模型。
  • Formatting context:块级上下⽂格式化,它是⻚⾯中的⼀块渲染区域,并且有⼀套渲染规则,它决定了其⼦元素将如何定位,以及和其他元素的关系和相互作⽤。

块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

通俗来讲:BFC 是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发 BFC 的条件,则 BFC 中的元素布局不受外部影响。

追问:说几个创建BFC的条件

  • 根元素:body;
  • 元素设置浮动:float 除 none 以外的值;
  • 元素设置绝对定位:position (absolute、fixed);
  • display 值为:inline-block、table-cell、table-caption、flex 等;
  • overflow 值为:hidden、auto、scroll;

追问:BFC的作用

  • 解决 margin 的重叠问题:由于 BFC 是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个 BFC,就解决了 margin 重叠的问题。
  • 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为 0。解决这个问题,只需要把父元素变成一个 BFC。常用的办法是给父元素设置overflow:hidden。(这个就是上面提到的内容)
  • 创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。

JS

(2)表示迄今为止在日常实习中遇到了两次

(2)说下JS有哪些数据类型?

Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

很有趣的问题!聊聊数组都有哪些API 再拓展开来讲讲 用法

这个问题太有趣了!真的是要多(带着思考地)写(优雅的)代码,才能流利地回答啊!

面试官大大当时提醒了我 reduce concat sort这几个方法(居然没想起来!用的太少了啊还是),其他说得都还算全,这里我根据《JS数据结构与算法(第三版)》再捋一遍!

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第4张图片

  • 数组的遍历 map forEach(问了这两个的区别 答:一个返回改变后的数组 一个只是单纯遍历)
  • 数组的连接 concat
  • 数组的排序 sort 还提到了sort中函数的内容
  • 数组的归并操作 reduce 这个是面试官大大提醒的 讲了下用reduce算数组之和
  • 数组的查找 indexOf(某一个数) find(某一个条件) includes((是否有这个)数)

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第5张图片

  • 数组的删除splice与切片(节选一段)slice(这个当时居然忘记了!经常用的明明)
  • 数组转字符串 toString join('分隔符')
  • 数组的翻转 reverse
  • 数组的过滤 filter(输出的元素需要满足的条件)
  • 数组是否存在某个值some 是否全为某个值every 这个当时也忘了!
  • 填充数组 fill

如何进行Object的值遍历?

Object.values() - JavaScript | MDN (mozilla.org)

这个API很有趣!返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同

JS如何实现继承呢?

【1】通过原型链

通过原型链实现子类对父类的继承

Child.prototype = new Father();

别忘了修正Child类显示原型的constructor

Child.prototype.constructor = Child

这部分之前写过一篇小结,放到这里,能说出来肯定是加分的!

继承模式
  • 原型链继承 : 得到方法

    • 通过Child.prototype = new Parent()继承父函数 从而继承了属性与方法
    • 缺点:通过Child构造的对象 的原型对象 的 constructor 属性指向Parent!这不好!
      • 我们需要让子类型的原型的 constructor 指向子类型 才对!
      • 这个问题可以通过 Child.prototype.constructor = Child; 来修正constructor属性
    function Parent(){}
    Parent.prototype.test = function(){};
    function Child(){}
    Child.prototype = new Parent(); // 子类型的原型指向父类型实例
    Child.prototype.constructor = Child;// 修正constructor属性
    var child = new Child(); //有test()
    
  • 借用构造函数 : 得到属性

    • 通过 Parent.call(this,name,age) 继承(调用父类型构造函数)
    • 缺点:获得父类型的方法很麻烦!还得借助call方法一个个地弄 Parent.func.call(this,参数)
    function Parent(xxx){this.xxx = xxx}
    Parent.prototype.test = function(){};
    function Child(xxx,yyy){
        Parent.call(this, xxx);//借用构造函数   this.Parent(xxx)
        // 相当于 this.Parent(xxx)
    }
    var child = new Child('a', 'b');  //child.xxx为'a', 但child没有test()
    
  • 组合

    function Parent(xxx){this.xxx = xxx}
    Parent.prototype.test = function(){};
    function Child(xxx,yyy){
        Parent.call(this, xxx);//借用构造函数   this.Parent(xxx)
    }
    Child.prototype = new Parent(); //得到test()
    var child = new Child(); //child.xxx为'a', 也有test()
    
JS实现继承的最佳实践

使用 原型链结合构造函数

在父类型属性有很多条时 使用 Parent.call(this,父函数属性) 让子类型继承

function Parent(attribute,other){
    this.attribute = attribute;
    this.other = other;
}
Parent.prototype.output = function(){
    console.log("此方法位于Parent的显式原型中  Child构造函数继承了我 所以Child的实例对象可以顺着隐式原型连找到这个对象(在Object对象上)");
}
function Child(attribute, other){
    Parent.call(this,attribute,other);// 继承父类型的属性
}
Child.prototype = new Parent();// 原型链继承!让子类型的显式原型指向父类型的实例!
Child.prototype.constructor = Child;// 出于严谨 这里修正constructor属性 要不然Child的显式原型的constructor就是Parent了 这就很奇怪!
var child = new Child('a', 'b');// ['a', 'b']
child.output();

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第6张图片

上面的属性的输出有些问题

JS继承最佳实践完整版输出如下:

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第7张图片

好吧上面的还是不全 有点小问题——

Child.prototype.constructor = Child;// 出于严谨 这里修正constructor属性 要不然Child的显式原型的constructor就是Parent了 这就很奇怪!
// 修正完 constructor指向Child构造函数

【2】通过ES6中的Class类

这个没太说清楚~

月影大大的课程之前做得截图,很基础哈~

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第8张图片

【3】通过构造函数继承

这个其实才是面试官想考察的内容(顺带着引出了下一个问题的内容)

let son = new Father()

(2)说一下new一个构造函数过程中发生了什么

艾玛太经典了,我还写过一篇文章说这里哩(写得老清楚了,看就完事!)

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第9张图片

说了一下 在红宝书看到过bulabulabula

另外拓展了一下——判断构造函数的返回值类型,如果res为对象类型,new Person的最终结果为res 而非我们想要的那个实例对象!

追问-刚才说的第三步提到了this,那么new过以后,this指向哪里呢?

指向这个新创建的对象(红宝书提到了)

拓展:可以看看之前写的那篇文章中的例子 Fn即为构造函数 很明显它是指向这个新创建的Object空对象的

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第10张图片

了解Event Loop么?

我能说我上个月刚看完相关文章么emm 其实我也说了(老实话痨孩子)

前段时间总结的笔记——

JS引擎的执行机制——事件循环 Event Loop

看了下这篇文章 简单入门10分钟理解JS引擎的执行机制

注意本文中所有执行流程是基于浏览器环境,而不是node环境

node轮询有phase(阶段)的概念
浏览器和NodeJS中不同的Event Loop

事件循环的核心机制是:宏任务、微任务及其相关队列的执行流程图

单线程的JS通过事件循环 Event Loop 实现异步

JS的执行机制是

  • 首先判断JS是同步还是异步,同步就进入主线程,异步就进入event table
  • 异步任务在event table中注册函数,当满足触发条件后,被推入event queue
  • 同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程中

以上三步循环执行,这就是event loop

举个例子

console.log(1)

setTimeout(function(){
 console.log(2)
},0)

console.log(3)
1.console.log(1) 是同步任务,放入主线程里
2.setTimeout() 是异步任务,被放入event table, 0秒之后被推入event queue里
3.console.log(3) 是同步任务,放到主线程里

// 当 1、 3在控制条被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里的函数

但这还不够!

微任务、宏任务的概念

如果有多个任务在event queue里呆着呢?谁先?谁后?上新概念!

上道题

setTimeout(function(){
    console.log('定时器开始啦')
});

new Promise(function(resolve){
    console.log('马上执行for循环啦');
    for(var i = 0; i < 10000; i++){
        i == 99 && resolve();
    }
}).then(function(){
    console.log('执行then函数啦')
});

console.log('代码执行结束');

尝试按照,上文我们刚学到的JS执行机制去分析

1】setTimeout 是异步任务,被放到event table

【2new Promise 是同步任务,被放到主线程里,直接执行打印 console.log('马上执行for循环啦')3.then里的函数是 异步任务,被放到event table

【4】 console.log('代码执行结束')是同步代码,被放到主线程里,直接执行

所以,结果是 【马上执行for循环啦 — 代码执行结束 — 定时器开始啦 — 执行then函数啦】吗?

亲自执行后,结果居然不是这样,而是【马上执行for循环啦 — 代码执行结束 — 执行then函数啦 — 定时器开始啦

欸?不是setTimeout这个任务先进的event table麽?

并不是!上述根据异步同步一股脑划分的方法不对!

而准确的划分方式是:

  • macro-task(宏任务):包括整体代码scriptsetTimeoutsetInterval
  • micro-task(微任务)Promiseprocess.nextTick(Node独有)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5oeipqxB-1640179150890)(https://segmentfault.com/img/bV1TKz?w=879&h=723)]

按照这种分类方式:JS的执行机制是

  • 【1】执行一个宏任务(JS脚本中的内容都是宏任务~),过程中如果【2】遇到微任务,就将其【3】放到微任务的【事件队列】里
  • 当前【4】宏任务执行完成后,会查看微任务的【事件队列】,并【5】将里面全部的微任务依次执行完

重复以上2步骤,结合event loop(1) event loop(2) ,就是更为准确的JS执行机制了。

尝试按照刚学的执行机制,去分析例2:

1.首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里

2.遇到 new Promise直接执行,打印"马上执行for循环啦"

3.遇到then方法,是微任务,将其放到微任务的【队列里】

4.打印 "代码执行结束"

5.本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"执行then函数啦"

6.到此,本轮的event loop 全部完成。


7.下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"定时器开始啦"

所以最后的执行顺序是【马上执行for循环啦 — 代码执行结束 — 执行then函数啦 — 定时器开始啦】

谈谈setTimeout

这段setTimeout代码什么意思? 我们一般说: 3秒后,会执行setTimeout里的那个函数

 setTimeout(function(){
    console.log('执行了')
 },3000)    

但是这种说并不严谨,准确的解释是: 3秒后,setTimeout里的函数会被推入event queue,而event queue(事件队列)里的任务,只有在主线程空闲时才会执行

所以只有满足 (1)3秒后 (2)主线程空闲,同时满足时,才会3秒后执行该函数

如果主线程执行内容很多,执行时间超过3秒,比如执行了10秒,那么这个函数只能10秒后执行了

图解Event Loop

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第11张图片

  • 同步任务直接进入主执行栈(call stack)中执行
  • 等待主执行栈中任务执行完毕,由EL将异步任务推入主执行栈中执行

说完概念 简单说了下例子,面试官大大下狠手了——

追问 了解async await么

答:简单了解 刚准备描述一个输出题的例子…

补一下async await的概念

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第12张图片

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第13张图片

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第14张图片

面试官大大说你别费劲了 我给你来一道 说输出吧

async function async1(){
    console.log("async1 start");
    await async2();
	console.log("async1 end");
    return 'async return';
}
async function async2(){
    console.log("async2");
}

console.log("script start");

setTimeout(function() {
    console.log("setTimeout");
}, 0);

async1().then(function (message) { console.log(message)});

new Promise(function(resolve){
	console.log("promise1");
	resolve();
}).then(function() {
	console.log("promise2");
});

console.log("script end");

我自己的理解如下:

第二版理解:(但还是不透彻!回头需要看下红宝书&一些文章继续学习)

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第15张图片

另外面试官大大建议我在babel中转换下ES6的async await代码(额我试了一下 不太会啊 这不是一样的么orz

【人生第一份offer~】北京京东科技 日常实习一面二面(已OC) 21/12/22&23_第16张图片

) 自行理解下~

手写题

斐波那契数列

这道算法题太友善了趴 感谢一面大大!

经典递归问题,输入n 输出斐波那契数

  • 斐波那契数定义:第n个数返回第n-1个数和第n-2个数的和
function fb(n) {
    if(n === 1 || n === 2) {
        return 1
    }
    return fb(n - 2) + fb(n - 1)
}

北京京东科技 日常实习二面 21/12/23

激动的心 颤抖的手 终于拿到offer了!

感谢和善的面试官大大!一定努力学习回报大大的信任!

总而言之这次面试还是更注重“我在学校做了什么”

大学生活闲聊

这部分面试官大大问了我几个有趣的问题——

  • 大学这三年多的学习历程?

    • 大一:数理基础 大二:计算机基础课人工智能 大三才开始正式系统地学习前端开发
  • 为什么放弃人工智能科研,选择前端开发?

  • 大学期间上过感触最深的课程是哪个?

    • 数据结构?那么让你写一本书/告诉学弟学妹如何学习数据结构与算法,那么你会怎么写呢?
  • 大学期间做过(计算机相关)最有成就感的一件事是什么?

    • 答的大二下的软基课设,基本上是自己一人独自完成了一个物流管理小项目

一道简单的手写题

‘a.b.c’ -> {a: {b: {c: null }}}

用了个笨办法 面试官也没让优化 直接就到反问环节了

function main(str) {
    let obj = {}
    let data = str.split(".").reverse()
    temp = JSON.parse(JSON.stringify(`{ ${data[0]} : null }`))
    for(let i = 1; i < data.length; i++) {
        obj = JSON.parse(JSON.stringify(`{ ${data[i]} : ${temp} }`))
    }
    return obj
}
console.log(main('a.b.c.d'));

你可能感兴趣的:(面试,前端开发之路,css,前端,面试,javascript)