前端面试要点week2
代码题
- 给定两个数组,写一个方法来计算它们的交集
//低级写法 :
function jiaoji(arr1 , arr2){
//获得数组长度较少的哪一个数组
if(arr1.length > arr2.length){
var temp = arr1;
arr1 = arr2;
arr2 = temp
}
//[2, 2] [1, 2, 2, 1] 此时数组长度较短的那个就是arr1了
//arr1用来比较在arr2中是否存在 ,
//将arr2去重
var newArr = Array.from(new Set(arr2))
//遍历数组arr1,查看是否存在
var array = [];
for(var i = 0 ; i < arr1.length ; i ++){
if(arr2.indexOf(arr1[i]) > -1) array.push(arr1[i])
}
return array
}
//高级写法 :
function union(arr1 , arr2) {
return arr1.filter( item => {
return arr2.indexOf(item) > -1;
})
}
2.带请求头的AJAX
var xhr = new XMLHttpRequest();
xhr.addEventListener("load" , loadHandler);
xhr.open( "POST" , "http://localhost:4001/a.php");
//设置请求头 , 必须在open后面,send前面
//如果ajax通信PHP时,使用post,必须设置这个属性
xhr.setRequestHeader( "content-type" , "application/x-www-form-urlencoded");
xhr.setRequestHeader( "name" , "pengyuyan");
xhr.send( "a=1&b=2");
- 写出使用jQuery遍历数组,对象的方法
//1.遍历数组
$.each(arr,function(index,item){
console.log(index,item);
})
//2.遍历对象
$.each(data,function(prop,value){
console.log(prop,value);
})
4.基于Promise封装Ajax
function ajax(url, method) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(url, method, true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.responseText)
} else if (xhr.status === 404) {
reject(new Error('404'))
}
} else {
reject('请求数据失败')
}
}
xhr.send(null)
})
}
- JS继承的封装
<script>
Function.prototype.extends = function( superClass ){
//o是要继承superClass的原型
var o = this.prototype;
function F(){};
//将superClass(想要继承的父级函数)的原型赋值给F
F.prototype = superClass.prototype;
this.prototype = new F();
//获得o里面的属性名
var names = Object.getOwnPropertyNames(o);
for(var i = 0 ; i < names.length ; i ++){
//获取o里面属性名的描述对象,并赋值给this.prototype
var desc = Object.getOwnPropertyDescriptor(o , names[i]);
Object.defineProperty(this.prototype , names[i] , desc)
}
//在this.prototype下面添加一个名为superClass的类 并赋值为参数superClass
this.prototype.superClass = superClass;
//如果constructor赋值时丢失,赋值回来
if(this.prototype.constructor !== this){
Object.defineProperty(this.prototype , "constructor" , {
value : this
})
}
if(superClass.prototype.constructor !== superClass){
Object.defineProperty(superClass.prototype , "constructor" , {
value : superClass
})
}
};
function CheckBox(){};
CheckBox.prototype = {
a : 1,
b : function(){}
}
function Radio(){
//改变this指向为Radio
this.superClass.apply(this , arguments);
}
Radio.prototype = {
c : 10,
d : function(){}
}
//使用时只要使用下面这句就可以了
Radio.extends(CheckBox);
var t = new Radio();
console.log(t)
</script>
- 函数的柯里化
function curry(fn){
var arr=[];
return function(){
if(arguments.length>0){
arr=arr.concat(Array.from(arguments));
return arguments.callee;
}else{
// fn.apply(null,arr);
return fn(arr);
}
}
}
var fn=curry(function(arr){
return arr.reduce((value,item)=>value+item);
});
知识点
-
网页的生命周期
- 页请求 : 页请求发生在页面声明周期开始之前,用户请求页面时,ASP.NET将确定是否需要分析和编译页面
- 开始 : 在开始阶段,将设置页面属性,如Request和Response。在此阶段,页面还将确定请求是回发请求还是新请求,并设置IsPostBack属性。
- 页面初始化 : 在页面初始化期间,可以使用页面中的插件,并设置每个控件的UniqueID属性。
- 加载 : 在加载期间,如果当前请求是回发请求,则将使用从视图状态和控件状态恢复的信息加载控件属性。
- 验证 : 在验证期间,将调用所有验证程序控件的Validate方法,此方法将设置各个验证程序控件和页面的IsValidate属性。
- 回发事件处理 : 如果请求是回发请求,则将调用所有的事件处理程序。
- 呈现 : 在呈现之前,会针对该页面和所有的控件保存视图状态。在呈现阶段中,页面会针对每个控件调用Render()方法,他会提供一个文本编辑器,用于间控件的输出写入页面的Response属性和OutputStream中。
- 卸载 : 完全呈现并将页面发送至客户端,准备丢弃该页面后,将调用卸载。此时,将卸载页面属性并执行清理。
-
什么是回流和重绘?如何优化?
- 回流 : 当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建。
- 重绘 : 当渲染树中的一些元素需要更新属性时,而这些属性只是影响元素的外观、风格,而不会影响页面的整体布局和元素尺寸。
- 回流一定会触发重绘,重绘不一定触发回流。
优化 :
- 不在布局信息改变时做DOM查询
- 使用CSSText或className一次性改变属性。
- 使用碎片容器fragment。
- 对于多次回流的元素,如动画,使用绝对定位脱离文档流,让他的改变不影响其他元素。
- 尽量不用table布局
-
懒加载的原理和应用?
- 概念 : 对于页面有很多的静态资源下(比如网上购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载。
- 原理 : 图片的加载是依赖于src路径,我们可以设置一个暂存器,把图片路径放到暂存器中,当我们需要这个图片加载显示时,再把路径赋值给src,这样就可以实现按需加载,也就是懒加载。我们通常使用html5中的data- 属性作为暂存器,例如src的值默认是正在加载中的GIF,而真正的图片路径是保存在data- 中。
-
link和@import的区别?
- link是html标签 , import是CSS提供的一种方式。
- 当一个页面被加载时,link引用的CSS被同时加载,import引用的CSS等到页面全部被加载完在加载。
- import只有IE5级以上的浏览器才能识别,link都可以。
- 用js控制dom改变样式只能使用link标签,因为import不是dom可以操控的。