曾经面试踩过的坑,都在这里了~ Javascript

2018-11-04 15:27:58 +08:00
 southSu

接上一篇的 曾经面试踩过的坑,都在这里了~ HTML/CSS

Javascript

1、请将下列 b 函数进行修改,保证每次调用 a 都能+1 (考闭包):
//本文由 IT@IT·平头哥联盟-首席填坑官∙苏南分享,如有错误,欢迎留言
function b(){
	var a=1;
};

function b(){
	var a=1;
	return ()=>{
		a++;
		return a;
	}
};
let c = b();
c(); //2
c(); //3
c(); //4

####### 2、js 有哪些基本数据类型:    ECMAScript 标准定义有 7 种数据类型:

3、用 js 将 386485473.88 转换为 386,485,473.88 (千位分割符):
//方法 1:
var separator=(num)=>{
	if(!num){
		return '0.00';
	};
	let str = parseFloat(num).toFixed(2);
	return str && str
		.toString()
		.replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
			return $1 + ",";
		});
}

separator(386485473.88) //"386,485,473.88"

//方法 2:
(386485473.88).toLocaleString('en-US')  // "386,485,473.88" 由 (sRect)补充

4、js 的 for 跟 for in 循环它们之间的区别?
var southSu = ['苏南','深圳','18','男'];
for(var i=0;i<southSu.length;i++){
	console.log(typeof i); //number
	console.log(southSu[i]);// 苏南 , 深圳 , 18 , 男
}
var arr = ['苏南','深圳','18','男','帅气',"@IT·平头哥联盟-首席填坑官"];
for(var k in arr){
	console.log(typeof k);//string
	console.log(arr[k]);// 苏南 , 深圳 , 18 , 男 , 帅气,@IT·平头哥联盟-首席填坑官
}

Object.prototype.test = '原型链上的属性,本文由 @IT·平头哥联盟-首席填坑官∙苏南分享';
var southSu = {name:'苏南',address:'深圳',age:18,sex:'男',height:176};
for(var i=0;i<southSu.length;i++){
	console.log(typeof i); //空
	console.log(southSu[i]);//空
}


for(var k in southSu){
	console.log(typeof k);//string
	console.log(southSu[k]);// 苏南 , 深圳 , 18 , 男 , 176 ,本文由 @IT·平头哥联盟-首席填坑官∙苏南分享
}

5、给 table 表格中的每个 td 绑定事件,td 数量为 1000+,写一下你的思路(事件委托题):
<body class="container">
	<table id="table">
		<tr><td>我们是 @IT·平头哥联盟</td><td>,我是首席填坑官</td><td>苏南</td><td>前端开发</td><td>优秀</td></tr>
		<tr><td>我们是 @IT·平头哥联盟</td><td>,我是首席填坑官</td><td>苏南</td><td>前端开发</td><td>优秀</td></tr>
		<tr><td>我们是 @IT·平头哥联盟</td><td>,我是首席填坑官</td><td>苏南</td><td>前端开发</td><td>优秀</td></tr>
		…………
	</table>
<script>
	let table =document.querySelector("#table");
	table.addEventListener("click",(e)=>{
		let {nodeName} = e.target;
		if(nodeName.toUpperCase() === "TD"){
			console.log(e.target);//<td>N</td>
		}
	},false);

</script>
</body>

6、js 把一串字符串去重(能统计出字符重复次数更佳),列出你的思路(两种以上):
<script>
	let str = "12qwe345671dsfa233dsf9876ds243dsaljhkjfzxcxzvdsf 本文由 @IT·平头哥联盟-首席填坑官∙苏南分享";
	let array = str.split("");

	//方案一:
	array = [...new Set(array)].join("");
	array = ((a)=>[...new Set(a)])(array).join("");
	console.log(array);//12qwe34567dsfa98ljhkzxcv 本文由 @IT·平头哥联盟-首席填坑官∙苏南分享  只能过滤,不会统计

	//方案二:
	function unique (arr) {
		const seen = new Map()
		return (arr.filter((a) => !seen.has(a) && seen.set(a, 1))).join("");
	}
	console.log(unique(array)) // 12qwe34567dsfa98ljhkzxcv 本文由 @IT·平头哥联盟-首席填坑官∙苏南分享

	//方案三:
	function unique (arr) {
		let arrs=[];
		var news_arr = arr.sort();//排序能减少一次循环
		for(var i=0;i<news_arr.length;i++){
				if(news_arr[i] == news_arr[i+1] && news_arr[i]!= news_arr[i-1] ){
						arrs.push(arr[i]);
				};
 
		};
		return arrs.join("");
	}
	console.log(unique(array)) // 12qwe34567dsfa98ljhkzxcv 本文由 @IT·平头哥联盟-首席填坑官∙苏南分享

	//方案四:
	function unique (arr) {
		let obj={};
		for(var i=0;i<arr.length;i++){
			let key = arr[i];
			if(!obj[key] ){
					obj[key]=1;
			}else{
				obj[key]+=1;
			}
 
		};
		return obj;
	}
	console.log(unique(array)) // object 对应每个 key 以及它重复的次数 

</script>

7、项目上线前,你们做过哪些性能优化:
8、你对重绘、重排的理解?
8、有用过promise吗?请写出下列代码的执行结果,并写出你的理解思路:
setTimeout(()=>{
		console.log(1);
}, 0);

new Promise((resolve)=>{
		console.log(2);
		for(var i = 1; i < 200; i++){
				i = 198 && resolve();
		}
		console.log(3);
}).then(()=>{
		console.log(4);
});
console.log(5);

// 结果:2、3、5、4、1;

说细步骤如下: setTimeout 是异步,不会立即执行,加入执行队列; new Promise 会立即执行 输出 2、3,而在 2、3 之间执行了 resolve 也就是微任务; 再到 console.log(5)了,输出 5; 然后异步里的微任务先出,那就得到 4; 最后执行宏任务 setTimeout 输出 1; 如有错误欢迎纠正!

9、new SouthSu() 在这个过程中都做了些什么?
function SouthSu(){
 		this.name = "苏南";
 		this.age = 18;
 		this.address = "深圳";
 		this.address = "首席填坑官";
};

 let South = new SouthSu();
 console.log(South,South.__proto__ === SouthSu.prototype) //true 

执行过程:
创建一个空的对象
 let p1 = new Object();


设置原型链
	p1.__proto__ = SouthSu.prototype;

让 构造函数 的 this 指向 p1 这个空对象

	let funCall = SouthSu.call(p1);

处理 构造函数 的返回值:判断 SouthSu 的返回值类型,如果是值类型则返回 obj,如果是引用类型,就返回这个引用类型的对象;

10、工作中如果让你使用 js 实现一个持续的动画,你会怎么做(比如转盘抽奖)??

window.requestAnimationFrame() 方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用,回调的次数通常是每秒 60 次,是大多数浏览器通常匹配 W3C 所建议的刷新频率。在大多数浏览器里,当运行在后台标签页或者隐藏的<iframe> 里时,requestAnimationFrame() 会暂停调用以提升性能和电池寿命。

小结:以往项目开发中大数人可能都是第一时间选择 JS 定时器setInterval 或者setTimeout 来控制的动画每隔一段时间刷新元素的状态,来达到自己所想要的动画效果,但是这种方式并不能准确地控制动画帧率,因为这是开发者主动要求浏览器去绘制,它这可能会因为动画控制的时间、绘制的频率、浏览器的特性等而导致丢帧的问题; requestAnimationFrame 是浏览器什么时候要开始绘制了浏览器它自己知道,通过requestAnimationFrame告诉我们,这样就不会出现重复绘制丢失的问题。

//一个持续旋转的正方形,
<div class="angle-div"></div>
<script>
	let timer = null;
	let Deg = 0;
	let distance = 360;
	var _requestAnimationFrame_ = window.requestAnimationFrame || window.webkitRequestAnimationFrame;//本文由 @IT·平头哥联盟-首席填坑官∙苏南分享
	let angleDiv = document.querySelector(".angle-div");
	cancelAnimationFrame(timer);
	let fn = ()=>{
		if(Deg < distance){ 
			Deg++;
		}else{
			Deg=0;
		};
		angleDiv.style.transform = `rotateZ(${Deg}deg) translateZ(0)`; 
		angleDiv.style.WebkitTransform = `rotateZ(${Deg}deg) translateZ(0)`;
		timer = _requestAnimationFrame_(fn);
	}
	timer = _requestAnimationFrame_(fn);
</script>

11、如何设置 http 缓存?

1)、Expires

2)、Cache-Control

总结:——几者之间的关系

  • Cache-Control设置为max-age=xx并且同事设置Expires时,Cache-Control的优先级更高
  • ETagLast-Modified同时存在时,服务器先会检查ETag,然后再检查Last-Modified,最终决定返回 304 还是 200
  • 该题由 本文由 @IT·平头哥联盟-成员(ZodiacSyndicate )补充
12、随机打乱一个数组
//该题由 本文由 @IT·平头哥联盟-成员(ZodiacSyndicate )补充
const shuffle = arr => {
  let end = arr.length - 1
  while(end) { // 当 end 为 0 时不需要交换
    const index = Math.floor(Math.random() * (end + 1))
    [arr[index], arr[end]] = [arr[end], arr[index]]
    end -= 1
  }
  return arr
}
13、用 React 实现一个显示鼠标位置的高阶组件
//该题由 本文由 @IT·平头哥联盟-成员(ZodiacSyndicate )补充
const mousePosition = Component => class extends React.Component {
  state = {
    x: 0,
    y: 0,
  }

  handleMouseMove = e => {
    this.setState({
      x: e.clientX,
      y: e.clientY
    })
  }

  render() {
    const { x, y } = this.state
    return (
      <>
        <div onMouseMove={this.handleMouseMove}>
          <Component {...this.props} />
        </div>
        <span>x: {x}</span>
        <span>y: {y}</span>
      </>
    )
  }
}

文本将持续更新,整理收集自己 /群友的面经分享给大家,如果觉得不错那就请关注下方的 公众号,有惊喜哦。

作者:苏南 - 首席填坑官
交流群:912594095,公众号:honeyBadger8
本文原创,著作权归作者所有。商业转载请联系@IT·平头哥联盟获得授权,非商业转载请注明原链接及出处。

1355 次点击
所在节点    分享创造
3 条回复
southSu
2018-11-04 15:29:17 +08:00
去做想做的事,去爱值得的人;
去成为自己喜欢的模样,
去让自己发光!浑身充满力量,
充实的日子最美好!——我是苏南,感谢您耐心读完此文,愿你一切安好!
fobven
2018-11-05 09:28:51 +08:00
您好,异步队列真执行的时候是先微任务里拿对应回调函数,然后才轮到宏任务的队列回调执行的,这句话不是很清楚,能请教一下详细的解释吗?
southSu
2018-11-05 23:16:16 +08:00
@fobven

考虑一千次,不如去做一次
犹豫一万次,不如实践一次
将来的你,一定会感谢现在奋斗的你——晚上好,我是苏南,感谢您耐心读完此文,建议可以执行一下问题的代码,可能有助于进一步理解,也就是说队列里有两种 queue,并不是先进就先出的,setTimeout 先加入队列,resolve 后加入的,就是一个证明,晚安!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/504321

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX