记录一套新鲜的前端笔试题

2024-01-28 08:47:28 浏览数 (1)

前言

本套笔试题真实(2019.10.9),做题时间要求:四十分钟。

可供自测(初级前端),按需取用。

正文

第一题

CSS 有几种方法实现垂直水平居中?请写出来。

第二题

var a='a123',b='b234',请在不调用其他变量的情况下,互换 a,b 的值。

第三题

请写出匹配邮箱账号的正则表达式,邮箱可包含下划线“_”,但不能以下划线开头。

第四题

定义两个类A、B,其中A类有属性 type 值为'a',使用 ES5 规范实现 B 类继承 A 类。

第五题

有 3 个基于 Promise 的异步函数,A、B、C;写出按顺序 A-B-C 调用的代码(前一个函数完成后,才能执行后一个函数)。

第六题

有一个元素长度超过 10000 且类型都会 Number 的数组 args,如何求其最大值的方法。

第七题

说说你对 HTTP 协议的理解,HTTP协议的底层实现。

第八题

分别写出下面两段代码的输出结果

代码语言:javascript复制
for(var i=0;i<5;i  ){
    (function(){
        setTimeout(function(){
            console.log(i)
        },i*1000)
    })(i)
}
代码语言:javascript复制
for(var i=0;i<5;i  ){
    (function(i){
        setTimeout(function(){
            console.log(i)
        },i*1000)
    })(i)
}

第九题

根据下列代码,写出结果,并说明原因。

代码语言:javascript复制
setTimeout(()=>{
    console.log(1)
},0)
new Promise((resolve,reject)=>{
    console.log(2)
    setTimeout(()=>{
        console.log(3)
        resolve(4)
    },0)
}).then((val)=>{
    console.log(val)
})
setTimeout(()=>{
    console.log(5)
},0)
console.log(6)

第十题

除了压缩代码、合并文件外,列举出你所知道的优化网站首屏显示速度的方法?

第十一题

vue 数据双向绑定原理是什么,依赖收集是如何实现的?

第十二题

请用原生 js实现一个前端路由。

解答

仅供参考,期待交流

第一题解答

CSS 有几种方法实现垂直水平居中?请写出来。

答:

  1. 用inline-block和vertical-align来实现居中;( 参考- Centering in the Unknown)
  2. 用相对绝对定位和负边距实现上下左右居中;(常用)
  3. 用Flexbox来实现水平垂直居中,注意兼容;(常用)
  4. 利用绝对定位来实现居中;(参考)
  5. 使用css3中的transform;(参考)
  6. 使用table-cell,inline-block实现水平垂直居中;

小结:尽可能写全,关键是要分清在不同的场景用不同的方法!

第二题解答

var a='a123',b='b234',请在不调用其他变量的情况下,互换 a,b 的值。

答:

代码语言:javascript复制
var a='a123';
var b='b234';
a={a:b,b:a}
b=a.b
a=a.a
console.log(a)
console.log(b)

第三题解答

请写出匹配邮箱账号的正则表达式,邮箱可包含下划线“_”,但不能以下划线开头。

答:

代码语言:javascript复制
/^(?!_)[a-zA-Z0-9_-] @[a-zA-Z0-9_-] (.[a-zA-Z0-9_-] ) $/

第四题解答

定义两个类A、B,其中A类有属性 type 值为'a',使用 ES5 规范实现 B 类继承 A 类。

答:

  1. 原型链继承:即B.prototype-new A();
  2. 借用构造函数(call 或者 apply 的方式继承);
  3. 组合继承;

参考:六种常见继承模式

第五题解答

有 3 个基于 Promise 的异步函数,A、B、C;写出按顺序 A-B-C 调用的代码(前一个函数完成后,才能执行后一个函数)。

答:

代码语言:javascript复制
function A(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log("1");
            resolve();
        },3000);
    });
}
function B(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log("2");
            resolve();
        },1000);
    });
}
function C(){
    return  new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log("3");
        },1000);
    });
}

A().then(B).then(C)

或:

A().then(()=>{
    return B();
}).then(()=>{
    return C();
})

第六题解答

有一个元素长度超过 10000 且类型都是 Number 的数组 args,如何求其最大值的方法。

答:选择快速排序(是对冒泡排序的一种优化)

时间复杂度:O(nlogn)

代码语言:javascript复制
function quickSort(arr){
    if(arr.length<=1){return arr;}    //如果数组<=1,则直接返回
    let pivotIndex = Math.floor(arr.length/2);   
    let pivot = arr.splice(pivotIndex,1)[0]; //找基准,并把基准从原数组删除
    let left=[], right=[];    //定义左右数组
    for(let i=0; i<arr.length; i  ){//比基准小的放在left,比基准大的放在right
        if(arr[i] <= pivot){
            left.push(arr[i]);   
        } else { 
        right.push(arr[i]);
        }
    }
    return quickSort(left).concat([pivot],quickSort(right));    //递归
}

第七题解答

说说你对 HTTP 协议的理解,HTTP协议的底层实现。

答:HTTP是超文本传输协议,是一种可靠的应用层数据传输协议,传输前需要进行三次握手进行客户端和服务端的验证。

常用的方法是:GET、POST、PUT、DELETE;

常见的返回码有:200、302、403、404、500、503

底层实现: http协议的底层是在应用层里,是一个特殊处理的socket,建立在TCP/IP协议之上的一种广泛应用:服务器先初始化一个socket,与端口绑定,对端口进行监听,调用阻塞,等待客户端的连接。然后,初始化客户端的socket,与服务器的socket连接,需要经过三次握手。

第八题解答

分别写出下面两段代码的输出结果:

代码语言:javascript复制
for(var i=0;i<5;i  ){
    (function(){
        setTimeout(function(){
            console.log(i)
        },i*1000)
    })(i)
}
代码语言:javascript复制
for(var i=0;i<5;i  ){
    (function(i){
        setTimeout(function(){
            console.log(i)
        },i*1000)
    })(i)
}

答:分别是:

//5,5,5,5,5

//0,1,2,3,4

考察点:闭包:第一段代码没有传递 i 值,第二段代码有传递 i 值。

第九题解答

根据下列代码,写出结果,并说明原因。

代码语言:javascript复制
setTimeout(()=>{
    console.log(1)
},0)
new Promise((resolve,reject)=>{
    console.log(2)
    setTimeout(()=>{
        console.log(3)
        resolve(4)
    },0)
}).then((val)=>{
    console.log(val)
})
setTimeout(()=>{
    console.log(5)
},0)
console.log(6)

答:2,6,1,3,4,5

原因:

  1. 首先遇到setTimeout放到宏任务队列,
  2. 然后Promise的executor是一个同步函数,执行console.log(2)
  3. 然后又是一个setTimeout,再被推入到宏任务队列,
  4. 然后又遇到一个setTimeout,也被推到宏任务队列中
  5. 然后看到主线程的同步任务console.log(6),随即打印;

// 这个时候控制台打印了2,6;(可以在控制台中看到已返回“undefined”)

  1. 然后执行宏任务,console.log(1)
  2. 继续执行宏任务队列中的,console.log(3);此时,遇到resolve,promise.then是一个微任务,则推到主线程执行,console.log(4)
  3. 再执行宏任务队列的任务,console.log(5)
  4. 全都执行完啦!

力荐:

一次弄懂Event Loop

Eventloop不可怕,可怕的是遇上Promise

第十题解答

除了压缩代码、合并文件外,列举出你所知道的优化网站首屏显示速度的方法?

答:

  1. 使用 CDN 加速静态资源;
  2. webapck打包,减少资源载入,按需加载;
  3. 避免 JS 执行阻塞渲染;
  4. 图片使用懒加载,视频或音频禁止自动播放,用图标代替图片;
  5. 充分利用本地缓存;

第十一题解答

vue 数据双向绑定原理是什么,依赖收集是如何实现的?

答:Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更新。

实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发生变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者Watcher是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理。

回答来源

第十二题解答

请用原生 js实现一个前端路由。

答:

原理:以 hash 形式(也可以使用 History API 来处理)为例,当 url 的 hash 发生变化时,触发 hashchange注册的回调,回调中去进行不同的操作,进行不同的内容的展示。

代码语言:javascript复制
function Router() {
    this.routes = {};
    this.currentUrl = '';
}
Router.prototype.route = function(path, callback) {
    this.routes[path] = callback || function(){};
};
Router.prototype.refresh = function() {
    this.currentUrl = location.hash.slice(1) || '/';
    this.routes[this.currentUrl]();
};
Router.prototype.init = function() {
    window.addEventListener('load', this.refresh.bind(this), false);
    window.addEventListener('hashchange', this.refresh.bind(this), false);
}
window.Router = new Router();
window.Router.init();

上面路由系统 Router 对象实现,主要提供三个方法:

  1. init 监听浏览器 url hash 更新事件;
  2. route 存储路由更新时的回调到回调数组routes中,回调函数将负责对页面的更新;
  3. refresh 执行当前url对应的回调函数,更新页面;

参考链接

结语

实打实写一哈更重要!祝需要笔试的盆友们顺利!

0 人点赞