前端面试问题01

  1. 多选题 (5分)以下哪些方法在JavaScript中可以获取数据类型?
  • A.TypeOf
  • B.InstanceOf
  • C.toString
  • D.Undefined

答:AB

正确答案:AB

Typeof 可以识别基本类型,返回的结果只能是numberstringbooleannullsymbolfunctionobject;无法区分array,regexp,{}对象

InstanceOf 运算符可以用来判断是否属于该数据类型,返回布尔值,可以支持所有的数据类型和自定义函数

  1. 多选题 (5分) 以下关于作用域的说法中正确的是?
  • A.Var 声明是全局作用域或函数作用域,而 Let 和 Const 是块作用域
  • B.Let 的声明会被提升到全局中
  • C.Var 的声明会被提升到全局中
  • D.Const 不可重复声明

答:ACD

正确答案:ACD

Var声明的范围是全局作用于或者本地函数作用域;
Var变量在函数内声明时是函数作用域;
Var变量可以重新声明和更新;
Var变量提升(Hoisting),它是一种JavaScript机制,它规定变量和函数声明在代码执行之前被移动到其作用域的顶部;

Let是块作用域,在带有Let的块中声明的变量仅可在该块中使用
Let可以更新但是不能重新声明
Let变量提升,与初始化为undefined的Var不同,Let关键字未初始化,Let不能提升到全局

Const声明是块作用域
Const声明只能在声明的块中访问
Const无法更新或重新声明
Const变量提升,与Let,一样不能提升到全局

总结:
1、var声明是全局作用域或函数作用域,而let和const是块作用域
2、var变量可以在其范围内更新和重新声明;let变量可以更新但不能重新声明; const变量既不能更新也不能重新声明
3、它们全部被提升到其范围的顶部,但是变量初始化为undefined时,let和const变量不会被初始化
4、虽然可以声明var和let而不进行初始化,但必须在声明期间初始化const

  1. 多选题 (5分) 以下关于普通函数和箭头函数的说法中正确的有哪些?
  • A.普通函数可以通过bind、call、apply改变this指向
  • B.普通函数可以使用new
  • C.箭头函数本身没有this指向
  • D.箭头函数可以通过bind、call、apply改变this指向

答:BCD

正确答案:ABC

箭头函数
又称匿名函数,不能作为构造函数,不能使用new
不绑定argumets,取而代之用rest参数解决
会捕获父类的上下文来作为自己的this值
没有原型
箭头函数的this永远指向调用者的父类的上下文,任何方法都改变不了指向,比如 call() , apply() , bind()

普通函数
通过call来转换Array原型中的push的指向,call() 方法 改变this的指向【call() , apply() , bind()
普通函数的this指向调用它的那个对象
普通函数的this指向调用它的那个对象
acll,apply,bind 它们在功能上没有区别的,都是改变this的指向*,它们的区别主要是用于方法是实行形式和参数传递上的不同。call和apply方法都是在调用之后立即执行的,而bind调用之后是返回原函数call() apply(),需要再调用一次才行bind(m)()*

  1. 多选题 (5分) 下列关于闭包的说法中正确的有哪些?
  • A.闭包使已经运行结束的函数上下文中的变量对象在内存中清除
  • B.创建闭包的最常见的方式就是在一个函数内创建另一个函数
  • C.闭包使我们在函数外部能够访问到函数内部的变量
  • D.闭包的本质就是作用域链的一个特殊的应用

答:AB

正确答案:BCD

闭包让你可以在一个内层函数中访问到其外层函数的作用域
闭包就是能够读取其他函数内部变量的函数
闭包的作用:

  1. 可以在函数外部访问到函数内部的局部变量: 函数执行, 形成私有的执行上下文, 使内部私有变量不受外界干扰,起到保护(避免命名冲突)和保存(解决循环绑定引发的索引问题)作用
  2. 让这些变量始终保存在内存中, 不会随着函数的结束而自动销毁: 是变量不会被垃圾回收机制回收
  1. 多选题 (5分) 以下哪些方法可以解决跨域问题?
  • A.通过Jsonp跨域
  • B.Document.domain + Iframe 跨域
  • C.Window.name + Iframe 跨域
  • D.PostMessage 跨域

答:ACD

正确答案:ABCD

跨域:指的是浏览器不能执行其他网站的脚本 它是由浏览器的同源策略造成的 是浏览器对javascript添加的安全限制 同源策略是一种约定 是浏览器核心的安全功能
同源策略会造成以下的影响:【url 的协议主机地址端口都相同】

  1. Cookie、LocalStorage 和 IndexDB 无法读取
  2. DOM 和 JS 对象无法获取
  3. Ajax请求发送不出去
参见的几种跨域方法:
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe跨域
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)–后端
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
JSONP

JSONP 方案和 Ajax 没有任何关系
JSONP 方案只支持 GET 请求 不支持post请求
JSONP 没有浏览器兼容问题,任何浏览器都支持。
核心思想:网页通过添加一个’< script >'元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
原理

  1. 客户端利用 script 标签的 src 属性,去请求一个接口,因为 src 属性不受跨域影响。
  2. 服务端响应一个字符串
  3. 客户端接收到字符串,然后把它当做 JS 代码运行。
document.domain + iframe

只适用于主域相同,子域不同的跨域通信
实现原理:两个页面通过 js 强制设置 document.domain 为基础主域,就实现了同域

  • 父窗口 http://www.domain.com/a.html
    <iframe id="iframe" src="http://child.domain.com/b.html"></iframe> <script> document.domain = 'domain.com'; var user = 'admin'; </script>
  • 子窗口 http://child.domain.com/b.html
    <script> document.domain = 'domain.com'; // 获取父窗口中变量 console.log('get js data from parent ---> ' + window.parent.user); </script>
location.hash + iframe

实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。

window.name + iframe

window.name 属性的独特之处在于,name 值在不同页面(甚至不同域名)加载后仍然存在,并且可以支持非常长的 name 值(2M)

  • a.html(http://www.domain1.com/a.html)
    var proxy = function(url, callback){ var state = 0; var iframe = document.createElement('iframe'); iframe.src = url; iframe.onload = function(){ if(state === 1){ callback(iframe.contentWindow.name); destoryIframe(); } else { iframe.src = 'http://www.domain1.com/proxy.html'; state = 1; } } document.body.appendChild(iframe); // 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问) function destoryIframe(){ iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); } } // 请求跨域b页面数据 proxy('http://www.domain2.com/b.html', function(data){ alert(data); });
  • proxy.html (http://www.domain1.com/proxy.html)
    中间代理页,与a.html同域,内容为空即可。
  • b.html (http://www.domain2.com/b.html)
    window.name = "name=admin&password=dfad1212";

总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

postMessage

是为数不多可以跨域操作的 window 属性之一
可以解决以下场景的问题:

  1. 页面和其打开的新窗口之间的数据传递
  2. 多窗口之间的数据传递
  3. 页面和其嵌套的 iframe 之间的数据传递
  4. 以上各场景之间的数据传递

用法: postMessag(data, origin) 方法接受两个参数

  • data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用**JSON.stringify()**序列化。
  • origin: 协议+主机+端口号,也可以设置为"*“,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/"。

示例

  • a.html (http://www.domain1.com/a.html)
    <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe> <script type="text/javascript"> var iframe = document.getElementById('iframe'); iframe.onload = function(){ var data = {name:'122'}; iframe.contentWindow.postMessage(JSON.Stringify(data), 'www.domain2.com'); } window.addEventListener('message', function(e){ console.log(JSON.parse(e.data)); },false) </script>
  • b.html (http://www.domain2.com/b.html)
    // 接收domain1的数据 window.addEventListener('message', function(e){ console.log(JSON.parse(e.data)); var data = JSON.parse(e.data); if(data){ data.age = 12; // 处理后再发回domain1 window.parent.postMessage(JSON.Stringify(data), 'www.domain1.com') } },false)
CORS

后端需要开启cors
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。

实际上就是在响应头添加允许跨域的源
Access-Control-Allow-Origin: 字段和值(意思就是允许去哪些源地址去请求这个服务器)

nginx代理【这个没看懂】

nginx反向代理接口跨域
跨域原理同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
#proxy服务器 server { listen 81; server_name www.domain1.com; location / { proxy_pass http://www.domain2.com:8080; #反向代理 proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 index index.html index.htm; # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用 add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为* add_header Access-Control-Allow-Credentials true; } }

nodejs中间件代理【这个没看懂】

node中间件实现跨域代理,原理大致与nginx相同
使用node + express + http-proxy-middleware搭建一个proxy服务器

WebSocket协议

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

  1. 多选题 (5分) 以下哪些方法可以解决浏览器缓存问题?
  • A.在 Ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,”0″)
  • B.在 Ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,”no-cache”)
  • C.在 URL 后面加上一个随机数:”fresh=” + Math.random();
  • D.在 URL 后面加上时间戳:”nowtime=” + new Date().getTime();

答:AB

正确答案:ABCD

1、在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,“0”)。
2、在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,“no-cache”)。
3、在URL后面加上一个随机数: “fresh=” + Math.random();。
4、在URL后面加上时间戳:“nowtime=” + new Date().getTime();。
5、如果是使用jQuery,直接这样就可以了$.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录。

  1. 多选题 (5分) 以下关于微任务和宏任务说法正确的有哪些?
  • A.JavaScript是单线程的,不分同步异步
  • B.微任务和宏任务皆为异步任务,它们都属于一个队列
  • C.宏任务一般是:script,setTimeout,setInterval、setImmediate
  • D.遇到宏任务,先执行宏任务,执行完后如果没有宏任务,就执行下一个微任务,如果有宏任务,就按顺序一个一个执行宏任务

答:CD

正确答案:BC

JavaScript是一门单线程语言,即一次只能完成一个任务,若有多个任务要执行,则必须排队按照队列来执行(前一个任务完成,再执行下一个任务)。
JavaScript语言将任务执行模式分成同步异步
宏任务:< script>整体代码,setTimeout,setInterval,setImmediate,requestAnimationFrame,Ajax,DOM事件
微任务:process.nextTick,MutationObserver,Promise.then catch finally
微任务比宏任务的执行时间要早
微任务和宏任务皆为异步任务

  1. 多选题 (5分) 解决JavaScript的加载、解析和执行会阻塞页面渲染过程问题的方法有哪些?
  • A.我们一般采用的是将 JavaScript 脚本放在文档的底部,来使 JavaScript 脚本尽可能的在最后来加载执行
  • B.给 JavaScript 脚本添加 defer 属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件
  • C.给 JavaScript 脚本添加 Async 属性,这个属性会使脚本异步加载,不会阻塞页面的解析过程
  • D.动态创建 DOM 标签的方式,对文档的加载事件进行监听,当文档加载完成后再动态的创建 script 标签来引入 JavaScript 脚本

答:ACD

正确答案:ABCD

浏览器渲染机制:解析DOM生成DOM Tree,解析CSS生成CSSOM Tree,两者结合生成render tree渲染树,最后浏览器根据渲染树渲染至页面
defer属性,浏览器会立即下载相应的脚本,在下载的过程中页面的处理不会停止,等到文档解析完成后脚本才会执行
async属性,浏览器会立即下载相应的脚本,在下载的过程中页面的处理不会停止,下载完成后立即执行,执行过程中页面处理会停止。
动态创建DOM方式:动态创建DOM标签的方式,可以对文档的加载事件进行监听,当文档加载完成之后再动态创建script标签来引入js脚本。
使用setTimeout延迟方法:设置一个定时器来延迟加载js脚本文件
让js最后加载:将js脚本放在文档的最底部,来使js脚本尽可能的在最后来加载执行。

  1. 多选题 (5分) 以下关于Cookie的说法中正确的有哪些?
  • A.Cookie 是服务器提供的一种用于维护会话状态信息的数据
  • B.在发生 XHR 的跨域请求的时候,同源下的 Cookie,会被自动添加到请求头部
  • C.Cookie 一般可以存储 16k 大小的数据,并且不能被同源的网页所共享访问
  • D.服务器端可以使用 Set-Cookie 的响应头部来配置 Cookie 信息

答:AD

正确答案:AD

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息
Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期安全性使用范围的可选属性组成

  1. 多选题 (5分) 以下哪些方法可以判断一个对象属于某个类并且说法正确?
  • A.使用 InstanceOf 运算符来判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置
  • B.通过对象的 Constructor 属性来判断,这种方式很安全,因为 Constructor 属性不会被改写
  • C.通过对象的 Constructor 属性来判断,对象的 Constructor 属性指向该对象的构造函数
  • D.使用 Object.prototype.toString() 方法来打印对象的[[Class]] 属性来进行判断

答:CD

正确答案:ACD

instanceof:可以用来判断某一个对象的类型,左边是一个对象,需要时该对象所
属的类的构造函数,或者是继承的父类的构造函数。
constructor:对于无法使用typeof来判断类型的对象来说,可以使用constructor来进行判断
Object.prototype.toString:可以使用Object.prototype.toString.call()来进行判断类型

  1. 多选题 (5分) 下列对于Undefined与Undeclared的说法中正确的有哪些?
  • A.Undefined是还没有在作用域中声明过的变量
  • B.Undeclared是还没有在作用域中声明过的变量
  • C.对于 Undeclared 变量的引用,浏览器会报引用错误
  • D.可以使用 TypeOf 的安全防范机制来避免报错

答:BC

正确答案:BCD

undefined是Javascript中的语言类型之一,而undeclared是Javascript中的一种语法错误
undefined: 已申明,未赋值
undeclared: 未声明,未赋值。
undeclared undefined 类型的变量在 typeof 输出都是undefined

  1. 多选题 (5分) 以下关于ES6 模块与 CommonJavaScript 模块、AMD、CMD 的差异说法正确的有哪些?
  • A.CommonJavaScript 模块输出的是一个值的拷贝
  • B.CommonJavaScript 模块是运行时加载
  • C.ES6 模块输出的是值的引用
  • D.ES6 模块是编译时输出接口

答:BD

正确答案:ABCD

CommonJS:NodeJS是CommonJS规范服务器端的实现,webpack也是CommonJS的形式书写。同步加载,服务器端从磁盘中读取速度快,运行在服务器端没有问题。浏览器不能兼容CommonJS
AMD:基于CommonJS规范的node.JS是服务端模块化的实现,实现浏览器端的模块化就是AMD
CMD:AMD推崇依赖前置,CMD推崇依赖就近,延迟加载
ES6 :ES6模块化采用静态编译,在编译的时候就能确定依赖关系,以及输入和输出的变量。
AMD规范与CMD规范的区别

  1. CMD推崇依赖就近,AMD推崇依赖前置
  2. CMD延迟执行,AMD是提前执行
    3.CMD性能好,按需加载,当用户有需要在执行。AMD用户体验好,不延迟执行,依赖模块提前加载完毕

ES6模块和CommonJS规范区别

  1. CommonJS支持动态导入,ES6不支持,是静态编译
  2. CommonJS同步加载,用于服务端,文件放在本地磁盘,读取速度快。同步导入卡住主线程也并无影响。ES6异步加载,用于浏览器端,不能同步加载,会导致页面渲染,用户体验差。
  3. CommonJS模块输出的是值拷贝,内部的变化影响不到值的变化。ES6模块输出的是值引用,原始值变化,加载的值也会跟着变化,ES6模块是动态引用,并且不会缓存值
  4. CommonJS模块是运行时加载,ES6模块是编译时输出接口。CommonJS模块就是对象,输入时先加载整个模块,生成一个对象,然后从对象读取方法。ES6模块不是对象,export输出指定代码,import导入加载某个值,而不是整个模块
  5. 关于模块顶层的this指向问题,在CommonJS顶层,this指向当前模块;而在ES6模块中,this指向undefined。
  6. ES6模块当中,是支持加载CommonJS模块的。但是反过来,CommonJS并不能requireES6模块,在NodeJS中,两种模块方案是分开处理的。

加载模式的总结

  1. CommonJS加载模式—同步/运行时加载
  2. AMD加载模式—异步加载、依赖前置
  3. CMD加载模式—异步加载、依赖就近
  4. ES6加载模式—静态编译
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值