我的前言
我的上一篇博客凉经记录了我的一面的几个问题,这几天我把二面的问题(顺序忘记了)也整理出来和大家分享分享,当然了,我只能分享我确定的问题,不会/不确定的问题希望大家在看到我的博客的时候给予解答。Thank you
1、手写ajax(原生js)
var xhr = new XMLHttpRequest();
xhr.open('GET','http://a.html?name=1&age=20');
//send方法,放在事件前后没有区别
xhr.send(); //post请求的时候,send中放参数,get请求一般放在url地址中
xhr.onreadystatechange(function(){
if(xhr.status == 200 && xhr.readyState == 4){ //请求后,判断状态是否成功
console.log(xhr.responseText);
}
})
如果大家面试中遇到类似的问题,千万不要使用其他库,我刚开始使用的库,然后问我原生js咋写,写着写着就忘记单词了?,在看的时候一定要动手写写,防止眼高手低。。。
在这里也顺便说一下里面的状态值:
status: 是服务器返回的状态码,200代表响应成功,大家也要记着一些常用的状态码:200、301、302、304、307、400、401、403、404、500等一些常见的。
readyState:
0:(未初始化)还没有调用send()
1:(载入)开始调用send(),发送内容
2:(载入完成)send()发送完毕,开始解析内容
3:(交互)正在解析内容
4:(成功)解析完成,可以调用数据
2、get、post区别
- 参数区别:get请求参数放在url或Cookie,post的参数放在body中
- 安全问题:get的参数放在地址栏中,可见相对post来说不太安全,post参数页面上不可见。
- 长度问题:get的参数一般浏览器都会有限制,不宜过长
- 作用:get无副作用,一般用于关键字查找、数据查询;post有副作用,比如添加数据,操作了数据库改变了信息。
3、深拷贝问题
这个问题我写过一篇博客,大家可以去看一下。我的那一篇博客写的拷贝都是js中的一些基本类型的数据,没有考虑到undefined、null等一些特殊的问题。如果要封装一个函数的话最好考虑一下,因为我写的时候面试官问这种情况怎样处理了。
function DeepCopy(obj){
//判断一下类型
if(!obj || typeof obj === 'undefined'){
throw Error("err");
}
var res;
if(Object.prototype.toString.call(obj)=='[object Array]'){ //判断传入参数是不是数组
res = []; //是数组的话定义为数组类型
for(var i = 0;i<obj.length;i++){
res[i] = DeepCopy(obj[i]); //对其子元素再进行递归遍历
}
}else if(Object.prototype.toString.call(obj) == '[object Object]'){ //判断传入参数是不是对象
res = {};
for(var key in obj){
res[key] = DeepCopy(obj[key]);
}
}else{
return obj;
}
return res;
}
原文:https://blog.youkuaiyun.com/tang422622/article/details/87869707
4、es6模块化和node(Common JS)中有什么区别
要知道两者之间的区别,必须先要了解es6中Module是什么,Common JS又是什么,这样才能做一番评价,两者的区别读者自行搜索(一定要看),我在这就不细说了。
区别:
- CommonJS 输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,ES6静态分析,动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变
- CommonJS 模块是运行时加载(只有运行到时才能得到这个对象),ES6 模块是编译时输出接口(只加载引入的方法)
- CommonJS 加载的是整个模块,即将所有的接口全部加载进来,ES6 可以单独加载其中的某个接口(方法)
- CommonJS this 指向当前模块,ES6 this 指向undefined(ES6模块采用严格模式,严格模式下this指向undefined)
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
5、浏览器事件循环机制(Event Loop)以及Promise()
给了我一段代码,让我分析输出结果,代码我忘了,就给大家贴上类似的一题吧。
async function async1() {
console.log("a");
//执行这一句后,await会让出当前线程,
//将后面的代码加到任务队列中,然后继续执行函数后面的同步代码
await async2();
console.log("b");
}
async function async2() {
console.log( 'c');
}
console.log("d");
setTimeout(function () {
console.log("e");
},0);
async1();
new Promise(function (resolve) {
console.log("f");
resolve();
}).then(function () {
console.log("g"); // then(console.log("g"))这种情况会立即执行,视为同步代码
});
console.log('h');
答案是什么呢,什么呢 ? 输出:d a c f h g b e
理解这题首先要知道浏览器的执行顺序是怎样的。一次弄懂Event Loop 分享这篇文章,写的很详细。浏览器将你的文件分为同步任务和异步任务,同步任务就按顺序直接执行,异步任务就会被放进任务队列中。
其中又分为宏任务和微任务,执行顺序是这样的:js代码为宏任务会首先执行,等执行栈为空后,就会去任务队列中把所有的微任务全部执行,等到执行队列为空时再次执行下一个宏任务,这样循环执行。
6、页面首次加载时执行了什么事件
这到题我没有答上来,只说了个load加载事件,然后就说不清啦,面试官一听不知道也没有继续往下问,也没有说说这题的思想(?),事后我查和搜索了各种资料,只找到了蛛丝马迹,如果有读者清楚,一定要告诉我哦 ?
- load是等页面中DOM元素、css、js、图片等加载完成之后才执行的事件
- DOMContentLoaded是DOM元素构建完成之后就执行的事件(jquery中封装)
7、居中方式、js数据类型(区别)
8、盒子模型、position的值以及区别
9、将类数组转为数组
- Array.from()
- Array.prototype.slice.call()
10、防抖和节流
这个题目面试官不是直接问我这两个是什么意思,我发现越是大神越从小问题问你,然后看你会不会运用到知识,巧了,我就是那个不会运用的?,推荐个大神的一篇博客 。
防抖: 有个特点是延时执行 就是带着前面的一起做,如果在我规定的时间内,又触发了新的,就从头开始计算时间,只关心用户的最后一次操作,比如搜索框输入时。
节流: 是在规定的时间内触发,如果时间未到就不触发事件
以上几个问题是我了解并整理的,还有几个问题我不是太了解的,我也贴出来让大家看看 希望会的童鞋一定一定要留言或者私信告诉我答案???
不清楚的问题(望解答)?
- ajax和服务器交互的过程
- 两中盒子模型怎样兼容??(我回答了个display:content-box,好像不对,是不是在文件开头声明 !DOCTYPE ?)
- absolut的父元素设置为static可以定位吗?为什么(肯定是不可以的,why??)更新:我理解的是:static是position的默认值,它会忽略top、bottom、left、right 这一些列的值,而定位就是根据这些值来计算位置的,所以子元素不能根据父元素设置了static的值进行定位。(个人理解,望解答?)
- 上一题中解决resizse频繁触发(应该用节流吧,resize()和scroll()差不多都应该使用节流吧)
基本上也就这些知识了,和大家分享一下,共同进步?
会的一定要帮我解答哦!!!
第四题:使用节流
对于窗口的滚动事件、onresize事件,可以使用节流,使用定时器让事件在规定的时间后触发这样不会频繁的触发时事件,影响页面的整体性能。
简单的代码:
var timer = null;
function throttle(){
clearTimeout(timer);
timer = setTimeout(function(){
console.log('1')
},500)
}
window.onresize = throttle;
加更加更
数组去重:(出现的频率超高)
我已经把数组去重和数据的深拷贝给弄混了,我也是醉了,所以我在这里好好总结总结:
1、利用ES6的 set
let arr = [1,2,5,3,2,1,4,2,5];
let set = new Set(arr);//去重
Array.from(set); //转为数组,也可以利用扩展运算符(...)
2、利用 indexOf
let arr = [1,2,2,3,1,5];
let newarr=[];
for(let i = 0;i<arr.length;i++){
if(newarr.indexOf(arr[i])==-1){
newarr.push(arr[i]);
}
}
console.log(newarr)
3、对象+数组
function unique(arr){
let res = [];
let obj = {};
for(var i = 0;i<arr.length;i++){
if(!obj[arr[i]]){
obj[arr[i]] = true; //随便赋值
res.push(arr[i]);
}
}
return res;
}
4、利用对象的key值不能重复(对象数组)
let arrs = [
{name:1,age:12},
{name:2,age:13},
{name:3,age:11},
{name:1,age:12},
]
function unique(arrs){
let obj = {};
let res = [];
for(let i = 0;i<arrs.length;i++){
obj[arrs[i].name] = arrs[i];
}
for(let key in obj){
res.push(obj[key]);
}
}
判断是不是空对象:
- JSON.stringify(obj) === “{}”
- Object.keys(obj) ===[]; //返回的是数组,判断是不是空数组
- Object.getOwnPropertyNames(obj) === []; //同上
从上一题引出的两题:
1、 Object.keys() 和 Object.getOwnPropertyNames() 的区别:
两个方法返回值都是数组,不包含Symbol属性
Object.keys() 是遍历对象自身所有 可枚举 的属性,可以遍历到原型上的值。
而Object.getOwnPropertyNames()是遍历对象 无论是否可枚举
2、JSON的语法:
let obj = {
a:123,
b:null,
c:undefined
}
JSON.parse(JSON.stringify(obj));// c不会输出
JSON的语法值,可以是true/false、number、string、null、对象、数组。除此之外不能是其他类型的值(undefined、NaN、函数…)