接上一篇的 曾经面试踩过的坑,都在这里了~ HTML/CSS
//本文由 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 种数据类型:
Boolean
Null
Undefined
Number
String
Symbol
:(ECMAScript 6 新定义 ,Symbol 生成一个全局唯一、表示独一无二的值)Object
:( Array、Function、Object )//方法 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)补充
for
循环 数组下标的 typeof 类型:number
, for in 循环数组下标的 typeof 类型:string
;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·平头哥联盟-首席填坑官
}
for
循环 无法用于循环对象,获取不到 obj.length; for in 循环遍历对象的属性时,原型链上的所有属性都将被访问,解决方案:使用hasOwnProperty
方法过滤或 Object.keys 会返回自身可枚举属性组成的数组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·平头哥联盟-首席填坑官∙苏南分享
}
<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>
<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>
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;
宏任务
:js 异步执行过程中遇到宏任务,就先执行宏任务,将宏任务加入执行的队列(event queue),然后再去执行微任务;微任务
:js 异步执行过程中遇到微任务,也会将任务加入执行的队列(event queue),但是注意这两个 queue 身份是不一样的,不是你先进来,就你先出去的(就像宫里的皇上选妃侍寝一样,不是你先进宫(或先来排队)就先宠幸的 ),真执行的时候是先微任务里拿对应回调函数,然后才轮到宏任务的队列回调执行的;说细步骤如下: setTimeout 是异步,不会立即执行,加入执行队列; new Promise 会立即执行 输出 2、3,而在 2、3 之间执行了 resolve 也就是微任务; 再到 console.log(5)了,输出 5; 然后异步里的微任务先出,那就得到 4; 最后执行宏任务 setTimeout 输出 1;
如有错误欢迎纠正!
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,如果是引用类型,就返回这个引用类型的对象;
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>
1)、Expires
Expires
的值为服务端返回的到期时间,响应时告诉浏览器可以直接从浏览器缓存中读取无需再次请求。
缺点:返回的是服务端的时间,比较的时间是客户端的时间,如果时间不一致有可能出现错误。2)、Cache-Control
Cache-Control
可设置的字段有:private
:客户端可以缓存public
:客户端和代理服务器都可以缓存max-age=xxx
:缓存内容在 xxx 秒后失效no-cache
:需要用另一种缓存策略来验证缓存(ETag
,Last-Modified
)no-store
:不进行缓存Last-Modified
:浏览器请求获得文件后,服务器返回该文件的最后修改时间Last-Modified
,下一次请求会带上If-Modified-Since
标识,如果If-Modified-Since
等于服务器的文件修改时间,则表示文件没有修改,返回 304 状态码,浏览器从浏览器缓存中读取文件。如果If-Modified-Since
小于服务端的文件修改时间,则浏览器会重新发送请求获取文件,返回状态码 200。ETag
:服务器文件的一个唯一标识,例如对文件内容取 md5 值作为ETag
的字段返回给浏览器。当文件变化时ETag
的值也会发生变化。下次请求会带上If-None-Match
即浏览器保留的ETag
值,如果发送了变化,则文件被修改,需要重新请求,返回 200 状态码。反之浏览器就从缓存中读取文件,返回 304 状态码。总结:——几者之间的关系
- 当
Cache-Control
设置为max-age=xx
并且同事设置Expires
时,Cache-Control
的优先级更高- 当
ETag
和Last-Modified
同时存在时,服务器先会检查ETag
,然后再检查Last-Modified
,最终决定返回 304 还是 200- 该题由 本文由 @IT·平头哥联盟-成员(
ZodiacSyndicate
)补充
//该题由 本文由 @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
}
//该题由 本文由 @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·平头哥联盟
获得授权,非商业转载请注明原链接及出处。
1
southSu OP 去做想做的事,去爱值得的人;
去成为自己喜欢的模样, 去让自己发光!浑身充满力量, 充实的日子最美好!——我是苏南,感谢您耐心读完此文,愿你一切安好! |
2
fobven 2018-11-05 09:28:51 +08:00
您好,异步队列真执行的时候是先微任务里拿对应回调函数,然后才轮到宏任务的队列回调执行的,这句话不是很清楚,能请教一下详细的解释吗?
|