总纲:前端面试知识点大全
目录
4.document load 和 document DOMContentLoaded
7.请解释什么是单页应用 (single page app), 以及如何使其对搜索引擎友好 (SEO-friendly)
10.使用一种可以编译成 JavaScript 的语言来写JavaScript 代码有哪些优缺点?
1.变量声明提升
学习博客:https://blog.csdn.net/sinat_36521655/article/details/82469651
在js中,函数及变量的声明都将被提升到函数的最顶部。
理解var a=5; var a; a都会提升;但是function的提升不太一样,function a(){}这样a会提升,但是var a = function(){} 这种并不会提升。
2.冒泡机制
JS工作流的三个阶段:捕获阶段、处于目标阶段、冒泡阶段。在事件绑定的时候这个有用
IE只支持事件冒泡,不支持事件捕获,只能使用attachEvent();
别的浏览器是支持事件冒泡和事件捕获,使用addEventListener(event, func, usrCapture),第三个默认为false。
3.attribute 和 property
在JS高程设计中将attribute翻译为“特性”,property翻译为“属性”。attribute通常指DOM对象中的dom节点自带的属性,而property指对象的属性。从某种意义上说attribute属于property范畴。
4.document load 和 document DOMContentLoaded
DOM文档加载步骤:
(1)解析html结构
(2)加载外部脚本和样式表文件
(3)解析并执行脚本代码
(4)构造HTML DOM模型 //DOMContentLoaded
(5)加载图片等外部文件
(6)页面加载完毕 //load
页面完全加载成功才会触发load事件,而dom树构建成功时DOMContentLoaded事件就会被触发,所以DOMContentLoaded事件早于Load事件发生。
5.同源策略 (same-origin policy)
同源:指域名(主机名或者ip地址,两者不能混着)、端口、协议相同。不同的客户端JS脚本在没有明确授权的情况下,不允许读取对方的资源
同源策略:同域名(或者ip地址)、同端口、同协议视为一个域,一个域内的JS脚本仅仅具有本域内的权限,无法访问其他域的资源。有NetScape提出的安全策略,为了保护用户的信息安全
优点:他是浏览器最核心也是最基本的安全功能,可以在一定程度上放置XSS(跨站脚本攻击)、CSFR(跨站请求伪造)等攻击,提高web前端的安全性
缺点:在一定程度上限制了web拓展上的灵活性
由于浏览器实现的同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,所以AJAX是不允许跨域的。不过 像<script>,<link>,<img>,<iframe>这些标签是允许跨域的,但你并不能修改这些资源,比如iframe里的内容。
如果没有同源策略限制:
比如一个黑客,他利用iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名和密码登录时,如果没有同源限制,他的页面(外部页面)就可以通过 JavaScript读取到你的表单中输入的内容,这样用户名和密码就轻松到手了.又比如你登录了OSC,同时浏览了恶意网站,如果没有同源限制,该恶意 网站就可以构造AJAX请求频繁在OSC发广告帖.
6.strict模式
严格模式,对于一些方法和特性检查更严格,设置不能使用。比如严格模式下with语句就不能用。不使用var声明变量会报错。
优点:
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
缺点:
现在网站的 JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。所以推荐使用IIFE的方式,这样在函数内使用’use strict‘
7.请解释什么是单页应用 (single page app), 以及如何使其对搜索引擎友好 (SEO-friendly)
单页应用:就是只有一张Web页面的应用。浏览器一开始会加载必需的HTML、CSS和JavaScript,之后所有的操作都在这张页面完成,这一切都由JavaScript来控制。因此,单页Web应用会包含大量的JS代码,模块化开发和架构设计的重要性不言而喻。
首先前端要采用history模式(HTML5 History API,百度一下吧),一般用来写单页应用的框架都有这个模式。第二,要用后端做一套页面,内容和对应的前端页面一模一样,即所谓静态化,我用的sails框架即可实现这一点,主流的如Node.js的express框架也可以,php应该也行。第三,必须用nginx做代理跳转,将搜索引擎识别出后流量引到后端的端口上,看到预先渲染给搜索引擎看的页面,还有history模式自带的404问题也需要在nginx里将404转为index.html或者rewrite才可以。同时基本上使用外链的方式进行宣传,因为JS代码太多,爬虫识别不了,排名不会高。
8.Promise
推荐文章:xieranmaya/blog#3
promise出现是为了解决回调函数层次容易过深,不好维护。
var promise = new Promise(function(resolve, reject) {
//...some code
if (/* 异步操作成功 */) {
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。这两个参数本身也是函数,由JS引擎提供,不用自己部署。
resolve函数的作用:将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作的错误作为参数传递出去。
Promise的状态一旦改变,就无法修改。
Promise新建后会立即执行,then方法指定的回调函数将在当前脚本所有同步任务执行完成后才会执行。
PS:调用resolve或reject并不会终结Promise的参数函数的执行,要等到其完全执行完成才算终结。例如:
new Promise((resolve, reject) => {
resolve(1);//不会立马结束Promise
console.log(2);
}).then(r => {
console.log(r);
});//先输出2 在输出1.
一般而言,调用resolve和reject以后,Promise的使命就完成了,后续的任务应该放在then方法中。
8.1 then()方法
Promise实例生成后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。回调函数的参数来自于Promise中resolve和reject函数。
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数时Promise对象的状态变为Rejected时调用。其中,第二个函数时可选的。这两个函数都接受Promise对象传出的值作为参数。
then()方法放回的是一个新的Promise实例(PS:不是原来那个Promise实例,而是新建的),因此可以使用链式写法。若采用链式写法,前一个then方法中的回调函数完成后,会将返回结果作为参数传入下一个then方法中的回调函数。
链式then方法的作用:采用链式的then可以指定一组按照次序调用的回调函数,这时,前一个回调函数有可能返回的还是一个Promise对象(即有异步操作),而下一个回调函数就会等待该Promise对象的状态发生变化,再被调用。
8.2 catch()方法
相当于then(null, onRejected)。Promise内部的reject方法相当于抛出错误,而实例的catch方法用于捕获异常。它返回的也是一个Promise对象。
Promise对象的错误具有“冒泡”性质,会一直往后传递,直到被捕获为止。即错误总会被下一个catch方法捕获。
与传统的try/catch语句不同,如果没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应,代码依然正常运行而不会终止。
8.3 Promise.all()静态方法
该方法用于将多个Promise实例包装成一个新的Promise实例。
all方法可以接受任何具有Iterator接口的数据,其返回的每个成员都是Promise实例即可,通常使用数组且数组元素为Promise实例。如果成员不是Promise实例,就会先调用Promise.resolve方法将参数转为Promise实例,在进一步处理。
其状态由参数决定,例如const p= Promise.all([p1, p2, p3]);
1、只有p1,p2,p3的状态都变成resolved(fulfilled),p的状态才会变成resolved,此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数;
2、只要其中有一个被Reject的,p的状态就会变成Rejected,此时第一个被rejected的实例的返回值会被传递给p的回调函数。
PS:如果作为参数的Promise实例自身定义了catch方法,那么它被rejected时并不会触发Promise.all()的catch方法。
8.4 Promise.race()静态方法
和all方法类似,也是讲多个Promise实例包装成一个新的Promise实例,只不过Promise.race()的状态是根据率先改变状态的实例改变。那个率先改变的Promise实例的返回值就传递给Promise.race()的回调函数。
同样如果成员不是Promise实例,就会先调用Promise.resolve方法将参数转为Promise实例,在进一步处理。
8.5 Promise.resolve()静态方法
将现有对象转换为Promise对象。
例如:Promise.resolve('foo') 等价于new Promise(resolve => resolve('foo'));
该方法接受的参数有4种:
(1)一个Promise实例
如果参数是Promise实例,那么Promise.resolve将不做任何修改,原封不动的返回这个实例。
(2)一个thenable对象(具有then方法的对象)
thenable对象是指具有then方法的对象。Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。
(3)不具有then方法的对象或者基本类型
如果参数是一个基本类型,或者是一个不具有then方法的对象,那么Promise.resolve方法返回一个新的且状态为Resolved的Promise对象,并将resolve中的参数传给回调函数。
(4)不带任何参数
直接返回一个Resolved状态的Promise对象。但是值得注意的是,立即resolve的Promise对象也是microTask,在本轮任务队列的尾部,而不是下一个任务队列的首部。
8.6 穿透特性
promise还有一个值穿透的特性,即then、catch等方法如果未设置回调函数,则值会往下一个then、catch方法中传。其内部实现原理就是then和catch方法中判断传值情况,如果没有就直接将值往后传。例如
new Promise(resolve =>resolve(8)).then().catch().then(function(value){alert(value)});//会弹出8的弹窗。
//实际上相当于
new Promise(resolve=>resolve(8)).then(function(value){
return value;
}).catch(function(reason){
throw reason;
}).then(function(value) {
alert(value);
})
9.async
async函数完全可以看做由多个异步操作包装成的一个promise对象,而await命令就是内部then命令的语法糖。可以解决一堆then的问题。
10.使用一种可以编译成 JavaScript 的语言来写JavaScript 代码有哪些优缺点?
比如JSX、CoffeeScript、TypeScript
优点:可以拓展JavaScript语言和语法
缺点:需要预处理,增加工作量