JS面试题
- 事件代理
- “事件代理(事件委托)”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务,多用于子元素个数不确定或者量很大的情况。通过事件冒泡触发父元素绑定的事件,再根据
e.target.nodeName
或者e.target.matches
获取触发事件的具体子元素,对子元素进行进一步处理 - 代码简洁
- 减少浏览器内存占用
- 但是,不要滥用
- “事件代理(事件委托)”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务,多用于子元素个数不确定或者量很大的情况。通过事件冒泡触发父元素绑定的事件,再根据
<button id='btn'>添加按钮</button>
<ul id='uls'>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var lis = document.getElementsByTagName("li"),
btn = document.getElementById("btn"),
uls = document.getElementById("uls");
btn.onclick = function(){
var len = lis.length;
var li = document.createElement("li");
li.innerHTML = len;
uls.appendChild(li);
}
uls.onclick = function(e){
var e = window.event || e;
var tar = e.target || e.srcElement;
if(tar.nodeName=='LI'){
tar.style.background='red';
}
}
//本身是给li添加事件,现在委托在ul身上
</script>
</body>
</html>
ajax
题目:
-
手写一个简易的ajax
//XMLHttpRequest 对象用于在后台与服务器交换数据。 //get请求 const xhr = new XMLHttpRequest(); xhr.open('GET','./data/test.json',true);//true 异步请求 xhr.onreadystatechange = function () { if (xhr.readyState===4){ if(xhr.status === 200){ // console.log(JSON.parse(xhr.responseText)) alert(xhr.responseText) }else if(xhr.status === 404){ console.log('404 not found') } } } xhr.send(null) //post请求 const xhr = new XMLHttpRequest(); xhr.open('POST','./login',true); xhr.onreadystatechange = function () { if (xhr.readyState===4){ if(xhr.status === 200){ // console.log(JSON.parse(xhr.responseText)) alert(xhr.responseText) } } } const postData = { userName:'zhangsan', password:'xxx' } xhr.send(JSON.stringify(postData));//必须发送字符串类型
//promise形式ajax请求 function ajax(url) { const p = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { resolve( JSON.parse(xhr.responseText) ) } else if (xhr.status === 404 || xhr.status === 500) { reject(new Error('404 not found')) } } } xhr.send(null) }) return p } const url = './data/test.json' ajax(url) .then(res => console.log(res)) .catch(err => console.error(err))
-
跨域的常用实现方式
- JSONP
- CORS
知识点:
-
XMLHttpRequest
-
状态码
-
xhr.readyState
- 0 (未初始化)还没有调用send()方法
- 1(载入)已调用send()方法,正在发送请求
- 2(载入完成)send()方法执行完成,已经收到全部响应内容
- 3(交互)正在解析响应内容
- 4(完成)响应内容解析完成,可以在客户端调用(只需要这一种)
-
xhr.status(**)
- 2xx -表示成功处理请求,如200
- 3xx 需要走重定向,浏览器直接跳转,如301(永久重定向),302(临时重定向),304(资源为改变,使用缓存资源)
- 4xx 客户端请求错误,如404(找不到地址),403(客户端没有权限)
- 5xx 服务器端错误
-
-
跨域:同源策略,跨域解决方案
- 什么是跨域(同源策略)
- ajax请求时,浏览器要求当前网页和server必须同源(安全)
- 同源:协议(http,https),域名(xxx.com),端口(80port),三者必须一致
- 前端:
http://a.com:8080/;
服务端:https://b.com/api/xxx
(端口默认是80)不能跨域 - 所有跨域,都必须经过server端允许和配合
- 未经server端允许就实现跨域,说明浏览器有漏洞,危险信号
- JSONP
- CORS(服务端支持)
- 什么是跨域(同源策略)
-
加载图片css,js可无视同源策略(浏览器不限制)
<img src="跨域的图片地址"/>
<img/>
可以用于统计打点,可以使用第三方统计服务<link/><script>
可以使用CDN,CDN一般都是外域<script>
可以实现JSONP
<link href="跨域的css地址"/>
<script src="跨域的js地址"></script>
解答:
JSONP
-
访问http://imooc.com/,服务端一定返回一个html文件吗?
-
服务器可以任意动态拼接数据返回,只要符合html格式要求
-
同理于
<script src="https://imooc.com/getData.js">
-
<script>
可以绕过跨域限制 -
服务器可以任意动态拼接数据返回
-
所以,
<script>
就可以获得跨域的数据,只要服务端愿意返回
<body>
<p>一段文字 1</p>
<script>
window.abc = function (data) {
console.log(data)
}
</script>
<!--html端口和访问的jsonp.js端口不同,实现了跨域-->
<script src="http://localhost:8002/data/jsonp.js?username=xxx&callback=abc"></script>
<!--
<script src="http://localhost:8002/data/jsonp.js?username=xxx"></script>
服务器端可以动态拼接前端传过去的数据返回,例如username
<script src="http://localhost:8002/data/jsonp.js?username=xxx&callback=abc"></script>
可以修改全局函数名
-->
</body>
//jsonp文件
abc(
{ name: 'xxxgfhdfgh' }
)