记一次面试
Posted hejing-work
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次面试相关的知识,希望对你有一定的参考价值。
一、一面(笔试)
- jsonp跨域简述原理
jsonp实现跨域的原理是跨域的服务端把客户端所需要的数据放进客户端本地的一个js方法里,进行调用,客户端在本地的js对返回的数据进行处理。这样就实现了不同域名下的两个站点间的交流。由于<script>标签的src可以跨域,利用这一点,就有了jsonp这种非正式传输协议。因为有可能是多个不同站点都要访问这个服务端,那么各个站点要调用的方法可能是各不相同的,如果把方法名写死的话,就会很不和谐。所以解决的办法是各个站点来访问服务端时,在url中带一个参数(callback)过来,服务端获取到这个参数,就会在生成js代码时,以这个callback参数作为方法名,再把数据放到这个方法里。这样各个站点就可以调用各自的方法了。
写一个模拟jsonp原理的一个简单的例子。参考链接:https://www.cnblogs.com/liyuspace/p/9258349.html
本地客户端:
1 <script type="text/javascript"src="http://example.com/Index.aspxcallback=Hello"></script>
本地回调函数:
1 function Hello(data){ 2 alert(data.result); 3 }
跨域服务端:
{ string callback=Request.QueryString["callback"];//获取客户端回调函数名,值为"Hello" Response.Write(callback+"({result:1})"); //调用客户端指定函数,并把数据传进去 }
- 正则表达式判断邮箱地址
参考链接:https://www.cnblogs.com/lst619247/p/9289719.html
举例:zhangsan-001@gmail.com
分析邮件名称部分:- 26个大小写英文字母表示为
a-zA-Z
- 数字表示为
0-9
- 下划线表示为
_
- 中划线表示为
-
- 由于名称是由若干个字母、数字、下划线和中划线组成,所以需要用到
+
表示多次出现
根据以上条件得出邮件名称表达式:
[a-zA-Z0-9_-]+
分析域名部分:一般域名的规律为“[N级域名][三级域名.]二级域名.顶级域名”,比如“qq.com”、“www.qq.com”、“mp.weixin.qq.com”、“12-34.com.cn”,分析可得域名类似“
**
.**
.**
.**
”组成。- “**”部分可以表示为
[a-zA-Z0-9_-]+
- “.**”部分可以表示为
.[a-zA-Z0-9_-]+
- 多个“.**”可以表示为
(.[a-zA-Z0-9_-]+)+
综上所述,域名部分可以表示为
[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+
最终表达式:
由于邮箱的基本格式为“名称@域名”,需要使用“^”匹配邮箱的开始部分,用“$”匹配邮箱结束部分以保证邮箱前后不能有其他字符,所以最终邮箱的正则表达式为:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$
- 26个大小写英文字母表示为
- 以下输出结果是什么?
- console.log(1+‘1‘+‘2‘) 输出112 //字符串和其他的数据使用+号运算,会连接成一个新的字符串
- console.log(1+‘1‘+2) 输出112
- console.log(1-‘1‘+‘2‘) 输出02 //减号只能作为数值运算,没有二义性(这点和加号不同),所以解释器就将1-‘1‘自动转成number进行运算。
- console.log(1-‘1‘+2) 输出2
- condole.log(‘A‘-‘B‘) 输出NAN //not a number,非数值
- 从输入url到得到html的过程参考链接:https://blog.csdn.net/sinat_41747081/article/details/87629707
1. 域名解析
浏览器会把输入的域名解析成对应的ip,解析分为几部分进行。
- 查看浏览器内部缓存,如果查到域名对应的ip,就发送和接受参数和数据
- 查看本机的host文件,浏览器会在本机的hosts文件查看是否有对应的ip服务器地址。
- 查看本地路由器的DNS缓存,找到对应的ip
- 查看网络服务商中DNS服务器
- 查询根域名下是否存在。
上述5步找到对应的ip地址后 - 询到目标IP地址后,则开始建立 TCP 三次握手 ,与目标服务器建立连接。
- 通过规定的协议(http)向目标主机发送请求
2. 服务器接收到请求和返回数据
服务器:安装了系统和web-server的主机,可以理解为一台电脑,安装了系统和软件来处理数据(硬件)
-
服务器接收到了浏览器发送的请求后,根据某个协议,通过web-server把浏览器发送的数据进行打包(包含请求头,ip地址,请求路径和查询参数等)
-
web-server把数据打包后,发送给网站代码(比如django、flask、node.js等后端服务)
- 后端服务软件会根据路径和查询参数进行相应处理,返回给浏览器对应的数据包(包括http协议组成的代码。里面包含页面的布局、文字。数据也可能是图片、脚本程序,反应头,反应数据,请求头等)
3. 浏览器的接受数据和页面渲染
- 将html解析成DOM树的结构
- 将css解析出结构化的css,也就是cssom
- 将DOM树和cssom合并在一起形成render tree,即渲染树
- 根据render tree进行渲染
- 闭包的优点和缺点?
参考链接:https://www.cnblogs.com/fengrenfan/p/10486844.html
闭包定义:当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的变量,且返回的这个函数在外部被执行,就产生了闭包。闭包是一个环境,具体指的就是外部函数--高阶函数。
说白了就是一个环境,能够读取其他函数内部的变量。本质上,闭包是将函数内部和函数外部连接起来的桥梁。
用处:1.读取函数内部的变量;
2.这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除。
优点:1:变量长期驻扎在内存中;
2:避免全局变量的污染;
3:私有成员的存在 ;
特性:1:函数套函数;
2:内部函数可以直接使用外部函数的局部变量或参数;
3:变量或参数不会被垃圾回收机制回收 GC;
缺点:
常驻内存 会增大内存的使用量 使用不当会造成内存泄露,详解:
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
- 创建一个对象的过程
①为对象分配内存空间,将对象的实例变量初始化为其变量类型的默认值
②如果实例变量在声明时被显式的初始化则将初始化值赋给实例变量
③调用构造方法
④返回对象的引用
- 下面代码输出什么?
function fun(n){ return n==1?1:n*fun(n-1); //函数返回n的阶乘,即n*(n-1)*(n-2)...2*1 }; console.log(fun(4)); //输出24
- 怎么判断类型为对象?
- typeof
1 console.log(typeof null); 2 console.log(typeof {}); 3 console.log(typeof []);
- instanceof
1 var a={}; 2 console.log(a instanceof Object) //true 3 console.log(a instanceof Array) //false 4 var b=[]; 5 console.log(b instanceof Array) //true 6 console.log(b instanceof Object) //true,数组属于object中的一种
instanceof需要判断两次才能区分对象和数组
- constructor
1 var a={}; 2 console.log(a.constructor==Object) //true 3 var b=[]; 4 console.log(b.constructor==Array) //true 5 console.log(b.constructor==Object) //false
constructor可以区分对象和数组,注意constructor属性是可以被修改的,会导致检测出的结果不正确。
- Object.prototype.toString.call()
1 Object.prototype.toString.call({}) //"[object Object]" 2 Object.prototype.toString.call([]) //"[object Array]"
推荐此方法
- jQuery中的$.type接口
1 $.type([]) //array 2 $.isArray([]); //true 3 $.isPlainObject({}); //true
-
怎么判断空对象?
参考链接:https://www.cnblogs.com/jpfss/p/9105119.html
- 将json对象转化为json字符串,再判断该字符串是否为"{}"
var data = {}; var b = (JSON.stringify(data) == "{}"); alert(b);//true
- for in 循环判断
1 var obj = {}; 2 var b = function() { 3 for(var key in obj) { 4 return false; 5 } 6 return true; 7 } 8 alert(b());//true
- jquery的isEmptyObject方法。此方法是jquery将2方法(for in)进行封装,使用时需要依赖jquery
1 var data = {}; 2 var b = $.isEmptyObject(data); 3 alert(b);//true
- Object.getOwnPropertyNames()方法。此方法是使用Object对象的getOwnPropertyNames方法,获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的length来判断此对象是否为空
1 var data = {}; 2 var arr = Object.getOwnPropertyNames(data); 3 alert(arr.length == 0);//true
- 使用ES6的Object.keys()方法。与上一种方法类似,是ES6的新方法, 返回值也是对象中属性名组成的数组
1 var data = {}; 2 var arr = Object.keys(data); 3 alert(arr.length == 0);//true
- 将json对象转化为json字符串,再判断该字符串是否为"{}"
10.v-if和v-show的相同点和不同点
相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:v-if显示隐藏是将dom元素整个添加或删除,而v-show隐藏则是为该元素添加css--display:none,dom元素还在。
11.介绍DOM树
常见的DOM节点:元素节点、文本节点、属性节点。
常见的DOM操作:获取、创建、添加、删除、设置属性。
12.判断一个字符串中出现最多次数的字符
1 function fun(str){
2 var obj={};
3 var max=0;
4 var key=‘‘;
5 for(var i=0;i<str.length;i++){
6 if(!obj[str.charAt(i)]){
7 obj[str.charAt(i)]=1;
8 }else{
9 obj[str.charAt(i)]++;
10 }
11 }
12 for(var i in obj){
13 if(max<obj[i]){
14 max=obj[i];
15 key=i;
16 }
17 }
18 return ‘str中最多的字符是‘+key+‘,出现了‘+max+‘次‘;
19 }
20 console.log(fun(‘dhdf793dcdjsd8‘));//str中最多的字符是d,出现了5次
stringObject.charAt(index):charAt() 方法可返回指定位置的字符,index表示字符串中某个位置的数字,即字符在字符串中的下标。
13.输出斐波那契数列
1 var arr=[]; 2 function fun(n){ 3 if(n<3){ 4 arr[0]=1; 5 if(n==2){ 6 arr[1]=1; 7 } 8 }else{ 9 arr[0]=arr[1]=1; 10 for(var i=2;i<n;i++){ 11 arr[i]=arr[i-1]+arr[i-2]; 12 } 13 } 14 console.log(arr); 15 } 16 fun(7);//[1,1,2,3,5,8,13]
二、二面(面谈)
- 列举常见的HTTP状态码:
(略)参考链接:https://baike.baidu.com/item/HTTP状态码/5053660?fr=aladdin - 网页优化加载
1. 优化图像2. 去掉不必要的插件3. 减少DNS查询(DNS lookups)4. 最小化重定向5. 使用内容分发网络(Content Delivery Network CDN)6. 把CSS文件放在页面顶部,而JS文件放在底部7. 利用浏览器缓存8. 使用 CSS Sprites 整合图像9. 压缩CSS和JavaScript10. 启用GZIP压缩11.前端实现懒加载(lazyload)
- Ajax是什么?如何创建一个Ajax
ajax全称是asynchronous javasript and xml,主要用来实现客户端服务器的异步通信效果,实现页面的局部刷新,使用ajax原生方式发送请求主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果。
1 <script type="text/javascript"> 2 window.onload = function(){ 3 //第一步:创建xhr对象 4 //xhr是一个对象;里面可以放很多东西,数据; 5 var xhr = null; 6 if(window.XMLHttpRequest){//标准浏览器 7 xhr = new XMLHttpRequest();//创建一个对象 8 }else{//早期的IE浏览器 9 xhr = new ActiveXObject(‘Microsoft.XMLHTTP‘);//参数是规定的; 10 } 11 console.log("状态q"+xhr.readyState);//0 12 //第二步:准备发送请求-配置发送请求的一些行为 13 //open即打开链接,第一个参数是以什么方式;第二个是往哪儿发送请求,第三个可以不写,默认true,表示异步,false表示同步;; 14 xhr.open(‘get‘,‘03form.php‘,true); 15 console.log("状态w"+xhr.readyState);//1 16 17 //第三步:执行发送的动作 18 //send也可以写在前面,推荐写在后面;写null是兼容问题; 19 xhr.send(null); 20 console.log("状态e"+xhr.readyState);//1 21 22 //第四步:指定一些回调函数,也属于事件函数;不触发不执行,触发条件是xhr.readyState;z这个值有0-4,共5个状态,是由浏览器控制的; 23 xhr.onreadystatechange = function(){ 24 if(xhr.readyState == 4){//4指服务器返回的数据可以使用; 25 if(xhr.status == 200){ //判断已经成功的获取了数据;200表示hTTP请求成功;404表示找不到页面;503表示服务器端有语法错误; 26 var data = xhr.responseText;//json,文本,主角; 27 // var data1 = xhr.responseXML; 28 } 29 } 30 // console.log("状态t"+xhr.readyState);//2表示已经发送完成; 31 32 // console.log(1234); 33 } 34 35 // console.log(456); 36 console.log("状态r"+xhr.readyState);//1 37 38 39 } 40 </script>
- 谈谈你对webpack的了解
参考链接:https://blog.csdn.net/NingZheYuan/article/details/80729174
(1)概念
- webpack是一个现代javascript应用程序的静态模块打包器,
- webpack处理应用程序时他会递归的构建一个依赖关系图,其中包含应用程序的每个模块,然后将这些模块打包成一个或者多个build文件
(2)入口enter
告诉webpack 使用那个模块 来作为构建内部依赖图的开始。进图入口文件后,webpack会找到那些模块和库是入口起点(直接或者间接)的依赖。举例:
1 module.exports = { 2 entry: ‘./path/to/my/entry/file.js‘ // 我们的入口文件 3 };
(2)出口output
告诉webpack从哪里产出builds以及如何命名这些文件 默认值是
./dist
。这样整个应用程序结构都会编译到你指定的文件夹中。举例:1 const path = require(‘path‘); 2 3 module.exports = { 4 entry: ‘./path/to/my/entry/file.js‘, // 入口文件 5 output: { 6 path: path.resolve(__dirname, ‘dist‘), // 打包后的文件夹的名字及路径 7 filename: ‘my-first-webpack.bundle.js‘ // 打包后的js名称 8 } 9 };
(3)loader
loder 让webpack能够处理那些 非javascript 的文件(webpack自身只理解javascript)。loader可以将所有类型文件转换为 webpack 能够处理的有效模块,然后就可以利用 webpack打包模块 来对他们进行处理。本质上 webpack loader 是将 所有类型的文件 转化为 应用程序依赖图(最终的bundle) 可以直接进行引用。webpack loader 两个参数:
1. test 用于标识出应该被对应的 loader 进行转换的 某个 或者某个文件
2. use 标识转换时应该使用那个loader1 const path = require(‘path‘); 2 3 module.exports = { 4 entry: ‘./path/to/my/entry/file.js‘, // 入口文件 5 output: { 6 path: path.resolve(__dirname, ‘dist‘), // 打包后的文件夹的名字及路径 7 filename: ‘my-first-webpack.bundle.js‘ // 打包后的js名称 8 }, 9 module: { 10 rules: [ 11 { test: /.txt$/, use: ‘raw-loader‘ } 12 ] 13 } 14 };
raw-loader
webpack 的原始模将文件加载为字符串
- 列举常见的HTTP状态码:
(4)插件pligins
插件的范围包括:
1. 打包优化
2. 压缩
3. 重新定义环境中的变量
注意:如果你在一个配置文件中多次的使用同一个插件时,这时候需要通过new 操作符来重建一个新的实例。
1 const webpack = require(‘webpack‘); 2 const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); // html 需要npm 安装一下 3 const config = { 4 module: { 5 rules: [ 6 { test: /.txt$/, use: ‘raw-loader‘ } 7 ] 8 }, 9 plugins: [ 10 new webpack.optimize.UglifyJsPlugin(), // 压缩js 11 new HtmlWebpackPlugin({template: ‘./src/index.html‘}) // 指定模板 12 ] 13 };
(5)模式
通过 development
或 production
之中的一个 来设置 mode
参数, 来启动 webpack
内置的优化
1 module.exports = { 2 mode: ‘production‘ 3 };
5.原型模式创建对象过程
参考链接:https://blog.csdn.net/u010176097/article/details/80484890
(1)JS中prototype,__proto__,constructor的关系
1 function Person(){ 2 Person.prototype.name=‘hj‘; 3 Person.prototype.age=22; 4 Person.prototype.say=function(){ 5 console.log(‘姓名:‘+this.name+‘,年龄:‘+this.age) 6 } 7 } 8 var person1=new Person(); 9 var person2=new Person(); 10 console.log(person1.__proto__==Person.prototype);//true 11 console.log(Person.prototype.constructor==Person);//true
JS中,当我们创建一个函数的时候,就根据一组特定的规则给这个函数创建一个prototype属性,这个属性指向这个函数的原型对象。在默认情况下,每个原型对象都会自动获得一个constructor 属性,这个属性指向这个函数。 上面的代码中,新建了一个Person对象,然后在Person的原型对象上(Person.prototype)添加了属性和方法,Person的原型对象有个constructor属性,指向Person。通过new Person()创建了两个实例对象person1和person2,person1的__proto__指向的就是Person的原型对象。下图表明了上述关系。
(2)在原型对象中查找值
1 function Person(){ 2 Person.prototype.name=‘hj‘; 3 Person.prototype.age=22; 4 Person.prototype.say=function(){ 5 console.log(‘姓名:‘+this.name+‘,年龄:‘+this.age) 6 } 7 } 8 var person1=new Person(); 9 var person2=new Person(); 10 person1.say();//姓名:hj,年龄:22 11 person1.name="aaa"; 12 person1.say();//姓名:aaa,年龄:22
在上面的代码中,person1中也有个name属性,在调用say方法时,会先在实例对象中查找name,如果有,返回name,如果没有,则继续在原型对象中查找,依次向上,直到找到或者没找到返回null。虽然可以通过对象实例 访问原型对象中的值,但是却不能通过实例对象重写原型中的值。如果在实例对象中已经找到了name属性,则自动屏蔽掉原型对象中的值。不过,通过delete操作符可以删除实例属性属性。 (3) 检测属性是在实例中还是原型对象中
使用hasOwnProperty()可以检测出实例对象是否具有某个属性,如果是原型属性统一返回false.
1 function Person(){
2 Person.prototype.name=‘hj‘;
3 Person.prototype.age=22;
4 Person.prototype.say=function(){
5 console.log(‘姓名:‘+this.name+‘,年龄:‘+this.age)
6 }
7 }
8 var person1=new Person();
9 var person2=new Person();
10 console.log(person1.hasOwnProperty("name"));//true
11 delete person1.name;//delete删除person1的name属性
12 console.log(person1.hasOwnProperty("name"));//false
6.display:none和visiblity:hidden的区别
相同:两者都能隐藏元素。
不同:
(1)display:none 不占页面空间,visiblity:hidden 占据原先页面空间。这里必须说明的是,元素不占页面空间后,取该元素或其内部元素的宽高值永远是0。如果想隐藏又想取到宽高值,那就得用visiblity:hidden。
(2)display:none 的子元素也一定无法显示,visiblity:hidden 的子元素可以设置显示。display:none元素及其子元素都将隐藏,而visiblity:hidden元素的子元素却可以设置visibility: visible 显示出来。在这一点上,如果页面是比较 复杂或者是不受控制的,就要慎重使用visiblity:hidden,因为保不齐哪个元素被设置成可见,影响显示效果。
(3)display:none 引起页面重绘和回流, visiblity:hidden 只引起页面重绘。
visiblity:hidden 看起来性能比display:none好些,在两者都能使用情况下,可先考虑visiblity:hidden。
三、三面(HR电话)
不知道有没有三面,正在等通知。。。
以上是关于记一次面试的主要内容,如果未能解决你的问题,请参考以下文章