最近面试了 2 家公司( 5月29日 - 6月2日 ),整理一下面试时面试官提出的问题,以做记录~
1. 自我介绍 + 项目介绍
大概介绍了下毕业时间,实习经历,最近一份工作的工作内容。
项目相关
2. 说一下你第一个项目中( vsxxx )app 和 H5 是如何进行交互的,举个简单的例子
App 在打开 H5 页面时,通过向页面注册需要交互的方法,前端通过调用这个 app 提供的方法来向客户端获取数据或发送数据( window.WebViewJavascriptBridge )
首先,由于安卓和 ios 注入方法的不用,所以安卓在调用方法前,前端需要判断一下当前 window 下是否存在指定的方法。
// 检测安卓的方法是否存在
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge);
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function() {
callback(WebViewJavascriptBridge);
},
false
);
}
}
然后接下来是具体方法的调用,以 app 打开 H5,需要给 H5 发送当前登录 app 的用户的登录信息为例
// 调用获取客户端信息的方法
let userInfos = {};
let firstEnter = true;
getUserInfos(reqDate, (data) => {
userInfos = JSON.parse(data); // 这里获得app的用户的登录信息
});
function getUserInfos(reqDate, successCall) {
if (isIos) {
window['H5GetUserInfos'] = function(data) {
if (successCall) {
// 调用成功的回调函数,data为客户端返回给我们的数据
successCall(data);
}
};
// 将调用方法时请求的参数发送给客户端,若无填null
window.webkit.messageHandlers.H5GetUserInfos.postMessage(reqDate);
} else if (isAndroid) {
androidGetUserInfos(reqDate, successCall);
}
}
function androidGetUserInfos(reqDate, successCall) {
connectWebViewJavascriptBridge(function(bridge) {
if (firstEnter) {
// 安卓的方法在调用前需要初始化一次,所以用个索引值标识,初始化了就不用在调用了
firstEnter = false;
bridge.init(function(message, responseCallback) {
var data = {
'Javascript Responds': 'Wee!'
};
responseCallback(data);
});
}
bridge.callHandler('H5GetUserInfos', reqDate, function(
responseData
) {
successCall(responseData);
});
});
}
3. 页面如果一次要渲染成千上万个 dom,是否会造成卡顿,如何处理?
会造成卡顿,可以使用懒加载的方式,监听页面的滚动,靠近底部时加载剩余部分的 dom。
4. 做 H5 开发时,会碰到输入框聚焦后,被软键盘遮挡的情况,如何解决?
5. 绘制一个地图的边界,可以如何实现,数据应该是怎么的?
可以使用 canvas + svg 来绘制,数据使用 N 多个经纬度的坐标点连接起来,就可以绘制成一个地图的边界。
6. 一道 js 基础题,考察 null 和 undefined 的区别
let b,a = null;
console.log(a==b); // 输出true
console.log(a===b); // 输出false
因为 let b,a = null 这句代码的结果是 b: undefined, a: null 。
在比较相等性之前有个前提条件,不能将 null 和 undefined 他任何值,并且规定 null 和 undefined 是相等的。
全等于状态下,是 false,这个很好理解,它们不属于同一数据类型(如下图所示)。

7. 用 js 来去除数组中重复的值
思路一:使用 ES6 的 set
let arr = [1,1,5,3,2,5,0];
return Array.from(new Set(arr));
思路二:使用 Map - 用数组的值做 key,个数做 value,循环数组,如果遇到已有的 key 值就不做任何操作,如果遇到没有的就存下来做 key 。直到循环完,最后只取 map 的 key ,就可以得到去重后的数组。
实现如下:(利用Object的属性值唯一)
let arr = [1,1,5,3,2,5,0];
let result = []; // 去重数组
let obj = {}; // 去重对象
for(let i = 0; i < arr.length; i++) {
if(!obj[arr[i].item]) {
result.push(arr[i].item);
obj[arr[i].item] = i + 1;
}
}
8. 算法题 - 两数只和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 解法一: 时间复杂度:O(n) 的平方
let nums = [2, 7, 11, 15], target = 9
function twoSum(nums, target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
}
解法二: 时间复杂度:O(n)
const twoSum = (nums, target) => {
let map = new Map();
let res = [];
nums.forEach((e, i) => map.set(e, i));
for(let i=0;i<nums.length;i++) {
let j = map.get[targer - nums[i]];
if(j && j !== i) {
res = [i, j];
break;
}
}
return res;
};
解法三:双指针
const twoSum = (numbers, target) => {
var i = 0, j = numbers.length - 1;
while (i < j){
if(numbers[i] + numbers[j] == target) {
break; // 等于,则得到结果
}
else if(numbers[i] + numbers[j] < target) {
i++; // 小于则:指向低处的指针向高处移动,两数和增加
}
else {
j--; // 大于则:指向高处的指针向低处移动,两数和减小
}
}
return [i + 1, j + 1];
};
9. 使用 Eslint 来做了哪些代码审查?
10. 简述一下 Vue 双向绑定的原理
11. Vue 的生命周期
自己的:🔗
别人的:🔗
12. 开发 H5 使用的计量单位是?如何进行换算的?
使用的是 rem,以 375 为基准来计算,计算过程如下:
@fontSizeStandard: 37.5; // 设置字号基准值为37.5
使用具体dom的像素值 / @fontSizeStandard = rem的值。
.pxtorem(@property; @sizeValue) {
@remValue: (@sizeValue / @fontSizeStandard);
@{property}: ~'@{remValue}rem';
}
使用如下:
.pxtorem(font-size, 14);
13. Webpack 如何进行节流(性能优化)/ 浏览器防抖如何实现
- 资源与依赖包的控制
- 减少文件搜索范围(设置
resolve.alias字段 / 合理配置extensions扩展名) loader预处理文件增加include匹配特定条件happypack多线程执行babel-plugin-dynamic-import-node异步加载DllPlugin分包
防抖的实现:以表单提交为例,给提交按钮设置一个 disabled 属性,数据提交发起前将 disabled 设置为 true ,禁止用户点击,等到服务端返回了具体数据后再将 disabled 复原。
14. Get 和 Post 的区别
- get 产生一个 TCP 数据包;post 产生两个 TCP 数据包。
- 对于 get 请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200; 而对于 post ,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data ,服务器响应 200 ok。
- get 请求的参数是明文显示在 url 后的,并且有长度限制,而 post 没有
- get 请求参数会被完整保留在浏览器历史记录里,而 post 中的参数不会被保留。
15. 图片懒加载如何实现
首先一张图片就是一个 标签,浏览器是否发起请求图片是根据
的 src 属性。
所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给 的 src 赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给 src 赋值。
实现步骤:
- 加载 loading 图片 (首先给所有的 img 标签一个默认的 loading 图)
- 判断哪些图片要加载(图片距离顶部的距离大于可视区域和滚动区域之和时懒加载)
- 隐形加载图片后替换真图片
//创建一个临时图片,这个图片在内存中不会到页面上去。实现隐形加载 var temp = new Image(); temp.src = imgs[i].getAttribute('data-src'); // 只会请求一次 // onload 判断图片加载完毕,真是图片加载完毕,再赋值给 dom 节点 temp.onload = function(){ // 获取自定义属性 data-src ,用真图片替换假图片 imgs[i].src = imgs[i].getAttribute('data-src') }
面试题总结完毕~