JS面试题汇总(四)

1.typeof 于 instanceof 区别

  • typeof 对于基本类型,除了 null 都可以显示正确的类型
  • typeof 对于对象,除了函数都会显示 object
  • 对于 null 来说,虽然它是基本类型,但是会显示 object ,这是⼀个存在 很久了的 Bug
  • instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的 原型链中是不是能找到类型的 prototype
// 我们也可以试着实现⼀下 instanceof
function instanceof(left, right) {
    
    
 	// 获得类型的原型
 	let prototype = right.prototype
 	// 获得对象的原型
 	left = left.__proto__
 // 判断对象的类型是否等于类型的原型
 	while (true) {
    
    
 		if (left === null)
 			return false
 		if (prototype === left)
 			return true
 	left = left.__proto__
 	}
 }

2.判断⻚⾯是否加载完成

  • Load 事件触发代表⻚⾯中的 DOMCSSJS ,图⽚已经全部加载完毕。
  • DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待
    CSSJS ,图⽚加载

3.如何解决跨域

因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端⼝ 有⼀个不同就是跨域, Ajax 请求会失败。

我们可以通过以下⼏种常⽤⽅法解决跨域的问题:

JSONP

JSONP 的原理很简单,就是利⽤ <script> 标签没有跨域限制的漏洞。通过<script> 标签指向⼀个需要访问的地址并提供⼀个回调函数来接收数据当需 要通讯时

<script src="http://domain/api?param1=a&param2=b&callback=jsonp"></script> <script>
 function jsonp(data) {
    
    
 console.log(data) }
</script>

JSONP 使⽤简单且兼容性不错,但是只限于 get 请求

  • 在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要⾃⼰封装⼀ 个 JSONP,以下是简单实现
function jsonp(url, jsonpCallback, success) {
    
    
 	let script = document.createElement("script");
 	script.src = url;
 	script.async = true;
 	script.type = "text/javascript";
 	window[jsonpCallback] = function(data) {
    
    
 		success && success(data);
 	};
 	document.body.appendChild(script); 
 }
jsonp(
 	"http://xxx",
 	"callback",
 	function(value) {
    
    
 	console.log(value);
 	} 
 );

CORS:

  • ORS 需要浏览器和后端同时⽀持。 IE 8 和 9 需要通过 XDomainRequest 来实现。
  • 浏览器会⾃动进⾏ CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了
    CORS ,就实现了跨域。
  • 服务端设置 Access-Control-Allow-Origin 就可以开启 CORS 。 该属性表示哪些域名 可以访问资源,如果设置通配符则表示所有⽹站都可以访问资源。

4.事件代理

如果⼀个节点中的⼦节点是动态⽣成的,那么⼦节点需要注册事件的话应该注 册在⽗节点上

<ul id="ul"> 
 <li>1</li>
 <li>2</li> 
 <li>3</li> 
 <li>4</li> 
 <li>5</li>
</ul> 
<script>
	let ul = document.querySelector('#ul')
	ul.addEventListener('click', (event) => {
    
    
	console.log(event.target); 
	})
</script>
  • 事件代理的⽅式相对于直接给⽬标注册事件来说,有以下优点
    1. 节省内存
    2. 不需要给⼦节点注销事件

5.优化webpack打包速度

  • 减少⽂件搜索范围
    1. ⽐如通过别名
    2. loadertestinclude & exclude
  • Webpack4 默认压缩并⾏
  • Happypack 并发调⽤
  • babel 也可以缓存编译

6.Babel 原理

  • 本质就是编译器,当代码转为字符串⽣成 AST ,对 AST 进⾏转变最后再⽣成新的代码
  • 分为三步:词法分析⽣成 Token ,语法分析⽣成 AST ,遍历 AST ,根据插件变换相应 的节点,最后把 AST 转换为代码

7.如何实现⼀个插件

  • 调⽤插件 apply 函数传⼊ compiler 对象
  • 通过 compiler 对象监听事件

⽐如你想实现⼀个编译结束退出命令的插件

apply (compiler) {
    
    
 	const afterEmit = (compilation, cb) => {
    
    
 		cb()
 		setTimeout(function () {
    
    
 			process.exit(0)
 		}, 1000)
 }
 compiler.plugin('after-emit', afterEmit) 
 }
 }
module.exports = BuildEndPlugin

猜你喜欢

转载自blog.csdn.net/qq_44880095/article/details/113496806