1.自我介绍
2.什么时候开始接触前端?
3.如何学习一门新技术?
4.怎么学习前端?
5.选择前端的原因?
- 前端写出来之后直接就能看到,更有成就感。
- JavaScript的编程风格我很喜欢,尤其是对于异步编程更好理解
- node.js,微信小程序等框架,让前端经过一定的学习后也可以进行移动端开发。
- 大学接触的编程语言很多,个人接触下来觉得JS是自己比较感兴趣的。
6.你觉得前端人员应该掌握哪些知识?
- 前端基础:HTML,浏览器,CSS,JS
- 前端核心:ajax, 服务端语言
- 前端的流行框架和模块化开发
- 计算机基础:了解计算机网络,数据库等
7.你觉得前端人员应该具备哪些特点?
- 扎实的前端编程技术
- 具有合作精神,良好的交流沟通能力
- 理解系统整体的编程,与后端的交互等
8.你了解我们公司吗?
9.有了解react吗?他们的一个区别?
- React:依赖组件 单向数据绑定 模板.jsx
- Vue:依赖组件 属于MVVM模式,双向数据绑定 模板.vue
10.让你实现一个框架如何实现?
11.前端与后端的区别?
- 前端:客户端开发,在应用程序和网站屏幕上看到的所有内容都属于前端
- 后端:服务端开发,在后端服务器和浏览器或应用程序之间存储网站、应用数据和中间媒介的服务器都属于后端。
- 区别
前端 | 后端 |
---|---|
前端 Web 开发人员需要精通 HTML,CSS 和 JavaScript。 | 后端开发人员应该拥有数据库,服务器,API 等技能 |
前端开发人员团队设计网站的外观,并通过测试不断修改 | 后端开发人员团队开发软件,并构建支持前端的数据库架构 |
除非网站是一个简单工作的静态网站,否则不能单独提供前端服务 | 后端服务可以作为 BaaS(后端即服务)独立提供 |
前端开发人员的目标是确保所有用户都可以访问该网站或应用,并在所有视图中做出响应 —— 移动和桌面 | 后端开发人员的目标是围绕前端构建程序,并提供所需的所有支持,并确保站点或应用始终正常运行 |
12.如何实现promise
我们根据 Promise 的执行顺序,手动实现一个 Promise 。
- 顺序
- 先执行 MyPromise 构造函数;
- 注册 then 函数;
- 此时的 promise 挂起, UI 非堵塞,执行其他的同步代码;
- 执行回调函数。
- 代码
- 首先,我们知道promise有三种状态,pending、resolve、reject定义三个变量,
- 然后,定义myPromise函数,内部有两个函数reject和resolve,状态都是从pending转变
- 其次,注册.then函数,判断两个参数是否为函数类型(如果不是函数,就创建一个函数赋值给对应的参数)
- 最后,执行回调函数
// 三种状态
const PENDING = "pending";
const RESOLVE = "resolve";
const REJECT = "reject";
// promise 函数
function MyPromise(fn){
const that = this; // 回调时用于保存正确的 this 对象
that.state = PENDING; // 初始化状态
that.value = null; // value 用于保存回调函数(resolve/reject 传递的参数
值)
that.resolvedCallbacks = []; // 用于保存 then 中的回调
that.rejectedCallbacks = []; // 用于保存 catch中的回调
// resolve 和 reject 函数
function resolve(value) {
if(that.state === PENDING){
that.state = RESOLVE;
that.value = value;
that.resolvedCallbacks.map(cb => cb(that.value));
}
}
function reject(value) {
if (that.state === PENDING) {
that.state = REJECT
that.value = value
that.rejectedCallbacks.map(cb => cb(that.value))
}
}
// 实现如何执行 Promise 中传入的函数
try {
fn(resolve, reject)
} catch (e) {
reject(e)
}
}
// 实现 then 函数
MyPromise.prototype.then = function(onResolved, onRejected) {
const that = this;
// 判断两个参数是否为函数类型(如果不是函数,就创建一个函数赋值给对应的参数)
onResolved = typeof onResolved === 'function' ? onResolved : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r}
// 判断当前的状态
if (that.state === 'pending') {
that.resolvedCallbacks.push(onResolved)
that.rejectedCallbacks.push(onRejected)
}
if (that.state === 'resolve') {
onResolved(that.value)
}
}
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
}).then(value => {
console.log(value)
})
13.数组的排序实现
- sort()
14.讲一下MVVM模式
- MVVM分为Model、View、ViewModel三者。
- Model:代表数据模型,数据和业务逻辑都在Model层中定义;
- View:代表UI视图,负责数据的展示;
- ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
- Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。
15.发布+订阅模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<input type="button" id="pub1" value="第一报社"><input type="text" id="txt1" value=''> <br>
<input type="button" id="pub2" value="第二报社"><input type="text" id="txt2" value=''> <br>
<input type="button" id="pub3" value="第三报社"><input type="text" id="txt3" value=''> <br>
<textarea name="" id="sub1" cols="30" rows="10"></textarea>
<textarea name="" id="sub2" cols="30" rows="10"></textarea>
</body>
<script>
// 发布者
var Publish = function(name) {
this.name = name;
this.subscribers = []; //接受所有的订阅者(每一个元素是函数类型fn的数组)
}
// Publish类的实例对象发布消息的方法
Publish.prototype.deliver = function(news) {
var publish = this;
this.subscribers.forEach(function(fn) {
// 把新消息发给一个订阅者
fn(news, publish);
});
// 链式编程
return this;
}
// 具体的一个订阅者去订阅报纸的方法
Function.prototype.subscribe = function(publish) {
var suber = this; //当前订阅者
// 数组的some : 遍历数组中的元素,执行一个函数,有一个返回true、,整体返回true
// 检查当前这个人是不是已经订阅过了
var isExists = publish.subscribers.some(function(item) {
return item === suber;
});
if (!isExists) {
publish.subscribers.push(suber);
}
// 链式编程
return this;
}
// 取消订阅的方法
Function.prototype.unsubscribe = function(publish) {
var suber = this;
// filter 返回一个新数组,
// 去掉suber
publish.subscribers = publish.subscribers.filter(function(item) {
return item !== suber;
});
return this;
}
var pub1 = new Publish('第一报社');
var pub2 = new Publish('第二报社');
var pub3 = new Publish('第三报社');
// 定义 2个订阅者
var sub1 = function(news) {
document.getElementById('sub1').innerHTML += arguments[1].name + '~~~' + news + '\n';
}
var sub2 = function(news) {
document.getElementById('sub2').innerHTML += arguments[1].name + '~~~' + news + '\n';
}
// 执行订阅方法
sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3);
sub2.subscribe(pub1).subscribe(pub2);
// 事件绑定
document.getElementById('pub1').onclick = function() {
pub1.deliver(document.getElementById('txt1').value)
}
document.getElementById('pub2').onclick = function() {
pub2.deliver(document.getElementById('txt2').value)
}
document.getElementById('pub3').onclick = function() {
pub3.deliver(document.getElementById('txt3').value)
}
sub1.unsubscribe('pub1');
</script>
</html>
16.节流和防抖
- 节流:一定的间隔时间内只执行一次,如果这个单位时间内触发多次函数,只有一次生效。 滚动事件,鼠标点击事件
- 防抖:事件被触发n秒后再执行回调,n秒内又被触发则重新计时
17.接触移动端吗?
18.em rem区别
- em:当使用em单位时,像素值将是em值乘以使用em单位的元素的字体大小。em 单位转为像素值,取决于他们使用的字体大小。 此字体大小受从父元素继承过来的字体大小,除非显式重写与一个具体单位。 一般用于按钮、菜单、标题等有自己字体大小
- rem:当使用rem单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的字体大小。 根元素字体大小乘以你 rem 值。rem 单位翻译为像素值是由 html 元素的字体大小决定的。 此字体大小会被浏览器中字体大小的设置影响,除非显式重写一个具体单位。 一般用于媒体查询
19.判断一个字符串是否是回文
- str.split(‘’).reverse().join(‘’);
- 二分法:left right left < mid &&right >mid
20.$nextTick
- JS的运行机制:JS执行是单线程,它基于事件循环,主要过程如下:
- 所有的同步任务都在主线程上执行,形成一个执行栈
- 主线程之外,还存在一个“任务队列”,只要异步任务有运行结果,在“任务队列中防止一个事件”
- 一旦“执行栈”中的所有同步代码执行完毕,系统就会读取“任务队列”,异步任务结束等待状态,进入执行栈,开始执行在这个过程中,主线程的执行过程就是一个tick,所有的异步结果都通过“任务队列”调度。分为微任务和宏任务,每一个宏任务之后,都要清空所有的微任务。
- 任务分类
- 宏任务macro task 有 setTimeout、MessageChannel、postMessage、
setImmediate - 微任务micro task 有 MutationObsever 和 Promise.then
- 宏任务macro task 有 setTimeout、MessageChannel、postMessage、
- 异步更新队列:
- 可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
- 如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
- 然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
- Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
- vue 的 nextTick 方法的实现原理:
- vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
- microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
- 考虑兼容问题,vue 做了 microtask 向 macrotask 的降级方案
21.如何将.vue文件变成.html文件渲染
- .vue—编译之后变为渲染函数—渲染虚拟DOM树(跟踪依赖关系)—渲染真实DOM
22.你遇到的最大挑战?完成之后你的成就感?
- 在学习前端的过程中,遇到比较大的挑战是学习JS时,之前学习就像Java就是面向对象编程,但是JS是基于面向对象,有对象这个概念,又不完全是面向对象编程,没有class这个概念,关于继承与原型链一开始很难理解,最后通过查资料,看视频和前端人员博客等,搞清楚整个的一个发展规范,最后深入理解JS的这种编程思想。
23.你有什么想问我的?
- 定期会有技术分享交流会吗?
- 如果我有幸入职,对于我这个岗位,您对我3-5年的职业规划的建议是什么?
- 请问贵公司对于员工有什么职业发展方面的培训吗?
- 感谢您这次对我的面试,请问我的经历和能力,有哪些是不符合公司预期的吗?或者您觉得我有哪些方面需要加强呢?
- 团队成员有多少人呢,前端人员大概有多少?