刷前端面经笔记(九)
1.JavaScript实现二分法查找?
二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。
查找过程可以分为以下步骤:
(1)首先,从有序数组的中间的元素开始搜索,
如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
(2)如果目标元素大于或者小于中间元素,
则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
(3)如果某一步数组为空,则表示找不到目标元素。
代码:
// 非递归算法
function binary_search(arr, key) {
var low = 0,
high = arr.length - 1;
while(low <= high){
var mid = parseInt((high + low) / 2);
if(key == arr[mid]){
return mid;
}else if(key > arr[mid]){
low = mid + 1;
}else if(key < arr[mid]){
high = mid -1;
}else{
return -1;
}
}
};
var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
var result = binary_search(arr,10);
alert(result); // 9 返回目标元素的索引值
// 递归算法
function binary_search(arr,low, high, key) {
if (low > high){
return -1;
}
var mid = parseInt((high + low) / 2);
if(arr[mid] == key){
return mid;
}else if (arr[mid] > key){
high = mid - 1;
return binary_search(arr, low, high, key);
}else if (arr[mid] < key){
low = mid + 1;
return binary_search(arr, low, high, key);
}
};
var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
var result = binary_search(arr, 0, 13, 10);
alert(result); // 9 返回目标元素的索引值
2.有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
这个问题要倒过来看,要到达n
级楼梯,只有两种方式,从(n-1)
级 或 (n-2)
级到达的。
所以可以用递推的思想去想这题,假设有一个数组s[n]
, 那么s[1] = 1
(由于一开始就在第一级,只有一种方法),s[2] = 1(
只能从s[1]
上去 没有其他方法)。
那么就可以推出s[3] ~ s[n]
了。
下面继续模拟一下,s[3] = s[1] + s[2]
,
因为只能从第一级跨两步, 或者第二级跨一步。
function cStairs(n) {
if(n === 1 || n === 2) {
return 1;
} else {
return cStairs(n-1) + cStairs(n-2)
}
}
3.递归设计。 实现一个函数,给该函数一个DOM节点,函数访问其所有子元素(所有子元素,不仅仅是直接子元素),每次访问子元素的时候,并为其传一个callback?
//访问一个DOM tree,是一个经典的深度优先搜索的算法
function Traverse(DOM,callback) {
callback(DOM);
var list = DOM.children;
Array.prototype.forEach.apply(list,(item)=>{
Traverse(item,callback); //递归
})
}
4.介绍一下对webpack的认识?
WebPack
是一个模块打包工具,可以使用WebPack
管理模块依赖,并编绎输出模块们所需的静态文件。
它能够很好地管理、打包Web
开发中所用到的HTML
、javaScript
、CSS
以及各种静态文件(图片、字体等),让开发过程更加高效。
对于不同类型的资源,webpack
有对应的模块加载器。webpack
模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。
webpack
的两大特色:
1)code splitting
(可以自动完成)
2)loader
可以处理各种类型的静态文件,并且支持串联操作
webpack
是以commonJS
的形式来书写脚本,但对 AMD/CMD
的支持也很全面,方便旧项目进行代码迁移。
webpack
具有requireJs
和browserify
的功能,但仍有很多自己的新特性:
1) 对CommonJS
、 AMD
、ES6
的语法做了兼容
2) 对js
、css
、图片等资源文件都支持打包
3) 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript
、ES6
的支持
4) 有独立的配置文件webpack.config.js
5) 可以将代码切割成不同的chunk
,实现按需加载,降低了初始化时间
6) 支持 SourceUrls
和 SourceMaps
,易于调试
7) 具有强大的Plugin
接口,大多是内部插件,使用起来比较灵活
8)webpack
使用异步 IO
并具有多级缓存。这使得 webpack
很快且在增量编译上更加快
5.关于HTTP2.0的认识
HTTP/2
引入了“服务端推(server push
)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能。
HTTP/2
提供更多的加密支持,HTTP/2
使用多路技术,允许多个消息在一个连接上同时交差。
它增加了头压缩(header compression
),因此即使非常小的请求,其请求和响应的header
都只会占用很小比例的带宽。
6.对AMD和Commonjs的理解?
CommonJS
是服务器端模块的规范,nodejs
采用了这个规范。
CommonJS
规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。
AMD
规范则是非同步加载模块,允许指定回调函数。
AMD
推荐的风格通过返回一个对象做为模块对象,CommonJS
的风格通过对module.exports
或exports
的
属性赋值来达到暴露模块对象的目的。
7.mongoDB和MySQL的区别?
MySQL
是传统的关系型数据库,MongoDB
则是非关系型数据库
mongodb
以JSON
结构(二进制)进行存储,对海量数据存储有着很明显的优势。
对比传统关系型数据库,NoSQL
有着非常显著的性能和扩展性优势,与关系型数据库相比,MongoDB
的优点有:
①弱一致性(最终一致),更能保证用户的访问速度:
②文档结构的存储方式,能够更便捷的获取数据。
8.讲讲304缓存的原理?
服务器首先产生ETag
,服务器可在稍后使用它来判断页面是否已经被修改。
本质上,客户端通过将该记号传回服务器,要求服务器验证其(客户端)缓存。
304
是HTTP
状态码,服务器用来标识这个文件没修改,不返回内容,浏览器在接收到个状态码后,会使用浏览器已缓存的文件。
客户端请求一个页面A
。
服务器返回页面A
,并在给A
加上一个ETag
。
客户端展现该页面,并将页面连同ETag
一起缓存。
客户再次请求页面A
,并将上次请求时服务器返回的ETag
一起传递给服务器。
服务器检查该ETag
,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304
(未修改——Not Modified
)和一个空的响应体。
9.用node模拟客户端发起请求?
var http = require("http");
var request = http.request({
host:"localhost",
port:"8080",
path:"/request",
method:"post"
},function(res){
res.on("data",function(chunk){
console.log(chunk.toString());
});
});
request.write("user=zhang&pass=111");
request.end("请求结束");//结束本次请求
10.CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?
CommonJS
模块的重要特性是加载时执行,即脚本代码在 require
的时候,就会全部执行。
一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。
ES6
模块是动态引用,如果使用 import
从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。
import/export
最终都是编译为require/exports
来执行的。
CommonJS
规范规定,每个模块内部,module
变量代表当前模块。
这个变量是一个对象,它的 exports
属性(即module.exports
)是对外的接口。
加载某个模块,其实是加载该模块的module.exports
属性。
export
命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。