1.同源策略
同源策略可防止 JavaScript 发起跨域请求。源被定义为 URI、主机名和端口号的组合。此策略可防止页面上的恶意脚本通过该页面的文档对象模型,访问另一个网页上的敏感数据。
同源策略: 协议、主机、端口必须完全一致
2.跨域
跨域问题产生的原因 :浏览器的同源策略导致了跨域。当我们在前端开发中使用ajax/fetch这些技术发送网络请求的时候,当协议、主机、端口有任何一个不一致的时候,则构成跨域。
跨域的作用 :用于隔离潜在恶意文件的重要安全机制
跨域问题的解决:
- jsonp ,允许 script 加载第三方资源
- 在服务器使用cors实现跨域资源共享
res.writeHead(200, {
“Content-Type”: “text/html; charset=UTF-8”,
“Access-Control-Allow-Origin”:‘http://localhost’,
‘Access-Control-Allow-Methods’: ‘GET, POST, OPTIONS’,
‘Access-Control-Allow-Headers’: ‘X-Requested-With, Content-Type’
}); - 在前端的工程化项目(webpack)中,我们可以通过配置devserver的proxy来解决跨域访问的问题。他的原理是在本地开启一个服务器向数据服务器发送请求,因为服务器和服务器之间是没有跨域
- 但是因为webpack的devserver只在开发环境下有效,当项目发布上线之后仍然会有跨域问题,为了解决项目上线的跨域问题,我们配置服务器的反向代理(Apache/ngix)来实现跨域请求
- 除此之外,我还知道当项目打包成apk之后就不存在跨域问题了,所以如果项目要打包成apk,我们需要在项目中的所有请求中写全路径(此时我们可以配置axios.default.baseURL来解决)
- iframe 嵌套通讯,postmessage
3.JSONP
Jsonp 并不是一种数据格式,jsonp 是用来解决跨域获取数据的一种解决方案。
具体是通过动态创建 script 标签向服务器发送请求,然后服务器返回一段JS脚本给客户端,然后客户端收到JS脚本立马执行对应的代码。为此,服务器应该设置响应头为 application/javascript
4.事件绑定的方式
- 嵌入dom
<button onclick="func()">按钮</button>
- 直接绑定
btn.onclick = function(){}
- 事件监听
btn.addEventListener('click',function(){})
5.事件委托
事件委托利用了事件冒泡,将子元素自己的事件交给父亲来处理。(子元素自己不绑定事件也不处理事件,委托给父元素来处理)
<ul>
<li>苹果</li>
<li>香蕉</li>
<li>凤梨</li>
</ul>
// good 事件委托
document.querySelector('ul').onclick = (event) => {
var ev = event || window.event;
var target = ev.target || ev.srcElement;//IE浏览器
if (target.nodeName === 'LI') {
console.log(target.innerHTML)
}
}
// bad 给每一个li绑定事件
document.querySelectorAll('li').forEach((e) => {
e.onclick = function() {
console.log(this.innerHTML)
}
})
6.事件循环
事件循环是一个单线程循环,用于将任务队列中的回调函数(任务)调度入栈。如果调用栈中的任务执行完毕并且任务队列中有对应的回调函数(任务),则将回调函数出队并推送到调用栈中执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s4L6rDR1-1583931573914)(assets/1576485332149.png)]
宏任务:script setTimeout setInterval setImmediate, I/O, UI rendering。
微任务:process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
事件循环的任务队列有宏任务队列和微任务队列,每次一个宏任务执行完毕的时候,都会把微任务队列中的微任务执行完毕之后才会再次执行下一个宏任务。
7.事件模型
- DOM0
直接绑定
<input onclick="sayHi()"/>
btn.onclick = function() {}
btn.onclick = null
- DOM2
DOM2级事件可以冒泡和捕获
通过addEventListener绑定
通过removeEventListener解绑
// 绑定
btn.addEventListener('click', sayHi)
// 解绑
btn.removeEventListener('click', sayHi)
- DOM3
DOM3具有更多事件类型
DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,全部类型如下:
UI事件,当用户与页面上的元素交互时触发,如:load、scroll
焦点事件,当元素获得或失去焦点时触发,如:blur、focus
鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup
滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
文本事件,当在文档中输入文本时触发,如:textInput
键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified
8.target和currentTarget区别
event.target:返回触发事件的元素
event.currentTarget:返回绑定事件的元素
9.prototype和__proto__
的关系是什么
1.函数有一个prototype属性,这个属性表示函数的原型
这个属性中有三部分信息:构造函数 所有实例公共的属性和方法 __proto__
2.对象有一个__proto__属性,他指向函数的原型
function Person(name,age){
this.name = name;
this.age = age;
}
var p = new Person("zhangsan",18);
p.__proto__ == Person.prototype;
3.函数原型中的信息
Person.prototype.constructor == Person;
Person.prototype.__proto__ == Object.prototype;
Object.prototype.__proto__ == null
//区别
//a._proto_是隐式原型,prototype是显示原型
//b.prototype:每一个函数创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象
//c._proto_ :javascript中任意的对象都有一个内置属性,在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过_proto_来访问。
10.什么是Ajax,ajax常用属性和方法
Ajax(asynchronous JavaScript and XML) 是使用js向服务器发送请求的一种异步通信的机制。
Ajax的好处:
1.异步请求,可以不断向服务器发送请求
2.允许我们局部刷新页面
let xmlhttp
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlhttp = new XMLHttpRequest()
} else {
// IE6, IE5 浏览器执行代码
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
}
xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById("myDiv").innerHTML = xmlhttp.responseText
}
}
xmlhttp.open("GET", "/ajax/test.txt", true)
xmlhttp.send()
Ajax的常用方法:
1.open方法:与服务器建立连接
2.send方法:向服务器发送数据
3.onreadystatechange:监听服务器响应的回调
4.responseText/responseXML:获取服务器响应的数据
5.readyState:ajax的状态码,4表示ajax响应已经完成
11.Ajax和Fetch区别
- ajax是使用XMLHttpRequest对象发起的,但是用起来很麻烦,所以ES6新规范就有了fetch,fetch发一个请求不用像ajax那样写一大堆代码。
- 使用fetch无法取消一个请求,这是因为fetch基于Promise,而Promise无法做到这一点。
- 在默认情况下,fetch不会接受或者发送cookies
- fetch没有办法原生监测请求的进度,而XMLHttpRequest可以
- fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
- fetch不是在ajax上的封装,是ES6规范下的一种网络请求技术,兼容性上比不上XMLHttpRequest
12.ajax 的缺点
1、ajax 不支持浏览器 back 按钮。
2、安全问题 AJAX 暴露了与服务器交互的细节。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
5、ajax跨域访问的问题
13.变量提升
用var声明的变化会被自动提升。let和const不会使变量提升。
用var声明的变量会被提升到当前作用域的最前面,只会提升变量的声明,不会提升变量的复制。
如果有函数的声明和变量的声明同名,则函数的提升会在变量的提升之前。
14.cookie、localStorage、sessionStorage区别
特性 | cookie | localStorage | sessionStorage |
---|---|---|---|
数据的生命周期 | 一般由服务器生成,可以setMaxAge来设置cookie的有效时间,如果在浏览器生成,默认是关闭浏览器之后失效 | 永久保存,可清除 | 仅在当前会话有效,关闭页面后清除 |
存放数据大小 | 4KB | 5MB | 5MB |
与服务器通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端保存 | 仅在客户端保存 |
用途 | 一般由服务器生成,用于标识用户身份 | 用于浏览器缓存数据 | 用于浏览器缓存数据 |
15.自调用函数?用于什么场景?好处?
自调用函数:1、声明一个匿名函数2、马上调用这个匿名函数。
自调用函数的作用:创建一个独立的作用域。
自调用函数好处:防止变量的命名污染问题(同名的变量在多个地方声明多次)
场景:一般用于框架、插件等场景