前端面试题(JS 事件 Ajax跨域)

101 阅读3分钟

事件

知识点

1.通用事件绑定

    // 第一种
    var btn = document.getElementById('btn1')
    btn.addEventListener('click',function(event) {
    	console.log('clicked')
    })
    // 第二种
    function bindEvent(elem,type, fn) {
    	elem,addEventListener(type,fn)
    }
    var a = document.getElementById('link1')
    bindEvent(a,'click', function(e) {
    	e.preventDefault() //阻止默认行为
        alert('clicked')
    })

2.事件冒泡

    <body>
    	<div id="div1">
        	<p id='p1'>激活</p>
            <p id='p1'>取消</p>
            <p id='p1'>取消</p>
            <p id='p1'>取消</p>
        </div>
        <div id='div2'>
        	<p id='p5'>取消</p>
            <p id='p6'>取消</p>
        </div>
    </body>
    var p1 = document.getElementById('p1')
    var body = document.body
    bindEvent(p1, 'click',function (e) {
    	e.stopPropagation()
        alert('激活')
    })
    bindEvent(body,'click',function (e) {
    	alert('取消')
    })

3、代理

<div id='div1'>
	<a href='#'>a1</a>
    <a href='#'>a2</a>
    <a href='#'>a3</a>
    <a href='#'>a4</a>
    <!-- 会随时新增更多 a 标签 -->
</div>
    var div1 = document.getElementById('div1')
    div.addEventListener('click',function (e) {
    	var target = e.target //获取冒泡的最初触发的标签
        if (target.nodeName === 'A') {
        	alert(target.innerHTML)
        }
    })

题目

1.编写一个通用的事件监听函数

	function bindEvent(elem,type, selector, fn) {
    	if(fn == null) {
        	fn = selector
            selector = null
        }
        elem.addEventListener(type,function (e) {
        	var target
            if (selector) {
            	target = e.target
                if (target.matches(selector)) {
                	fn.call(target,e)
                }
            } else {
            	fn(e)
            }
        })
    }
    // 使用代理
    var div1 = document.getElementById('div1')
    bindEvent(div1,'click','a',function (e) {
    	console.log(this.innerHTML)
    })
    
    // 不适用代理
    var a = document.getElementById('a1')
    bindEvent(a,'click',function (e) {
    	console.log(a.innerHTML)
    }

描述事件冒泡流程

  • DOM树形结构
  • 事件冒泡
  • 阻止冒泡(stopPropagation)
  • 冒泡的应用

对于一个无限下拉加载图片的页面,如何给每个图片绑定事件

  • 使用代理
  • 知道代理的优点

1.代码简洁
2.浏览器效率高

Ajax

知识点

XMLHttpRequest

    var xhr = new XMLHttpRequest()
    //true 是异步,false是同步, api是请求URL,GET是请求方式
    xhr.open('GET','/api',true)
    xhr.onreadystatechange = function () {
    	// 这里的函数异步执行,可参考之前 JS 中的异步
        if(xhr.readyState == 4) { // 4 完成
        	if( xhr.status ==200) { // 状态码 200 成功
            	alert(xhr.responseText)
            }
        }
    }
    xhr.send(null) //send 发送

readyState

  • 0 -(未初始化) 还没有调用send()方法
  • 1 -(载入) 已调用send() 方法,正在发送请求
  • 2 -(载入完成) send()方法执行完成,已经接收到全部相应内容
  • 3 -(交互) 正在解析响应内容
  • 4 -(完成) 响应内容解析完成,可以在客户端调用了

状态码说明

  • 2xx - 表示成功除理请求 如200
  • 3xx - 需要充定向,浏览器直接跳转
  • 4xx - 客户端请求错误, 如404
  • 5xx - 服务器端错误

跨域

  • 什么是跨域
  • 浏览器有同源策略,不允许ajax 访问其他域接口
  • 跨域条件:协议、域名、端口、有一个不同就算跨域
  • 可以跨域的三个标签
  • <img src=xxx>
  • <link href=xxxx>
  • <script src=xxxx>
  • 三个表情的使用场景
  • <img> 用于打点统计,统计网站可能是其他域,如百度站长
  • <link><script>可以使用CDN,CDN的也是其他域
  • <script>可以用于JSONP
  • 跨域注意事项
  • 所有跨域请求都必需经过信息提供方允许
  • 如果未经允许即可获取,那是浏览器同源策略出现漏洞
  • JSONP
  • 加载URL请求时
  • 不一定服务器真正有一个相应的文件
  • 服务器可以根据请求,动态生成一个文件,返回
    <script>
    window.callback = function (data) {
    // 这是我们跨域得到的信息
    console.log(data)
    }
    </script>
    <script src="https://xxx.com/api.js">
    <!--以上将返回 callback({x:100,y:200})-->
  • 服务器端设置 http header
  • 另外一个解决跨域的简洁方法,需要服务器端来做
  • 但是作为交互方,前端必须知道这个方法
  • 是讲来解决跨域问题的一个趋势
// 注意不同后端语言写法不一样
// 第二个参数填写允许跨域的域名称,不建议直接写 '*'
	response.setHeader("Access-Control-Allow-Orgin", "http://a.com,http://b.com")
    response.setHeader("Access-Control-Allow-Header", "X-Requested-With");
    response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
// 接收跨域的cookie
response.setHeader('Access-Control-Allow-Credentials','true');

题目

  1. 手动编写一个 ajax, 不依赖第三方库
   var xhr = new XMLHttpRequest()
   //true 是异步,false是同步, api是请求URL,GET是请求方式
   xhr.open('GET','/api',true)
   xhr.onreadystatechange = function () {
   	// 这里的函数异步执行,可参考之前 JS 中的异步
       if(xhr.readyState == 4) { // 状态码 4 完成
       	if( xhr.status ==200) { // 状态码 200 成功
           	alert(xhr.responseText)
           }
       }
   }
   xhr.send(null) //send 发送
  1. 跨域的几种实现方式
  • JSONP
  • 服务器端设置 http header