凯里网站建设公司哪家好,做视频类型的网站,东莞网站建设兼职,安阳前端面试基础知识题
1. es5 中的类和es6中的class有什么区别#xff1f;
在es5中主要是通过构造函数方式和原型方式来定义一个类#xff0c;在es6中我们可以通过class来定义类。
class类必须new调用#xff0c;不能直接执行。
class类执行的话会报错#xff0c;而es5中…
前端面试基础知识题
1. es5 中的类和es6中的class有什么区别
在es5中主要是通过构造函数方式和原型方式来定义一个类在es6中我们可以通过class来定义类。
class类必须new调用不能直接执行。
class类执行的话会报错而es5中的类和普通函数并没有本质区别执行肯定是ok的。
class类不存在变量提升 2报错说明class方式没有把类的定义提升到顶部。
class类无法遍历它实例原型链上的属性和方法
function Foo (color) {this.color color
}
Foo.prototype.like function () {console.log(like${this.color})
}
let foo new Foo()for (let key in foo) {// 原型上的like也被打印出来了console.log(key) // color、like
}class Foo {constructor (color) {this.color color}like () {console.log(like${this.color})}
}
let foo new Foo(red)for (let key in foo) {// 只打印一个color,没有打印原型链上的likeconsole.log(key) // color
}new.target属性 es6为new命令引入了一个new.target属性它会返回new命令作用于的那个构造函数。如果不是通过new调用或Reflect.construct()调用的new.target会返回undefined。
function Person(name) {if (new.target Person) {this.name name;} else {throw new Error(必须使用 new 命令生成实例);}
}let obj {}
Person.call(obj, red) // 此时使用非new的调用方式就会报错class类有static静态方法
static静态方法只能通过类调用不会出现在实例上另外如果静态方法包含 this 关键字这个 this 指的是类而不是实例。static声明的静态属性和方法都可以被子类继承。
class Foo {static bar() {this.baz(); // 此处的this指向类}static baz() {console.log(hello); // 不会出现在实例中}baz() {console.log(world);}
}Foo.bar() // hello
2. 背包问题 3. 全排列 4. 使用Promise封装一个异步加载图片的方法
这个比较简单只需要在图片的onload函数中使用resolve返回一下就可以了。
function loadImg(url) {return new Promise((resolve, reject) {const img new Image();img.onload function() {resolve(img);};img.onerror function() {reject(new Error(Could not load image at url));};img.src url;});5. 怎么使用 setTimeout 实现 setInterval
setInterval 的作用是每隔一段指定时间执行一个函数但是这个执行不是真的到了时间立即执行它真正的作用是每隔一段时间将事件加入事件队列中去只有当当前的执行栈为空的时候才能去从事件队列中取出事件执行。所以可能会出现这样的情况就是当前执行栈执行的时间很长导致事件队列里边积累多个定时器加入的事件当执行栈结束的时候这些事件会依次执行因此就不能到间隔一段时间执行的效果。
针对 setInterval 的这个缺点我们可以使用 setTimeout 递归调用来模拟 setInterval这样我们就确保了只有一个事件结束了我们才会触发下一个定时器事件这样解决了 setInterval 的问题。
// 思路是使用递归函数不断地去执行 setTimeout 从而达到 setInterval 的效果function mySetInterval(fn, timeout) {// 控制器控制定时器是否继续执行var timer {flag: true};// 设置递归函数模拟定时器执行。function interval() {if (timer.flag) {fn();setTimeout(interval, timeout);}}// 启动定时器setTimeout(interval, timeout);// 返回控制器return timer;
}6. Js 动画与 CSS 动画区别及相应实现
CSS3 的动画的优点 在性能上会稍微好一些浏览器会对 CSS3 的动画做一些优化 代码相对简单 缺点 在动画控制上不够灵活 兼容性不好 JavaScript 的动画正好弥补了这两个缺点控制能力很强可以单帧的控制、变换同时写得好完全可以兼容 IE6并且功能强大。对于一些复杂控制的动画使用 javascript 会比较靠谱。而在实现一些小的交互动效的时候就多考虑考虑 CSS 吧
7. 什么是“前端路由”什么时候适合使用“前端路由”“前端路由”有哪些优点和缺点
前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做之前是通过服务端根据 url 的不同返回不同的页面实现的。
在单页面应用大部分页面结构不变只改变部分内容的使用
优点用户体验好不需要每次都从服务器全部获取快速展现给用户 缺点单页面无法记住之前滚动的位置无法在前进后退的时候记住滚动的位置 实现方式 前端路由一共有两种实现方式一种是通过 hash 的方式一种是通过使用 pushState 的方式。
8. 什么是点击穿透怎么解决
在发生触摸动作约300ms之后移动端会模拟产生click动作它底下的具有点击特性的元素也会被触发这种现象称为点击穿透。
常见场景
情景一蒙层点击穿透问题点击蒙层mask上的关闭按钮蒙层消失后发现触发了按钮下面元素的click事件。 情景二跨页面点击穿透问题如果按钮下面恰好是一个有href属性的a标签那么页面就会发生跳转。 情景三另一种跨页面点击穿透问题这次没有mask了直接点击页内按钮跳转至新页然后发现新页面中对应位置元素的click事件被触发了。 情景四不过概率很低就是新页面中对应位置元素恰好是a标签然后就发生连续跳转了。
发生的条件
上层元素监听了触摸事件触摸之后该层元素消失 下层元素具有点击特性监听了click事件或默认的特性a标签、input、button标签
解决点击穿透的方法
方法一书写规范问题不要混用touch和click。既然touch之后300ms会触发click只用touch或者只用click就自然不会存在问题了。 方法二吃掉或者说是消费掉touch之后的click依旧用tap只是在可能发生点击穿透的情形做额外的处理拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测配合全局flag等。
9. 介绍些 setTimeout 的运行机制
setTimeout简介
setTimeout()函数用来指定某个函数或某段代码在多少毫秒之后执行。它返回一个整数表示定时器timer的编号可以用来取消该定时器。
先看个简单的例子
console.log(1);
setTimeout(function () {console.log(2);
}, 0);
console.log(3);问最后的打印顺序是什么如果不了解js的运行机制就会答错
正确答案1 3 2
解析无论setTimeout的执行时间是0还是1000结果都是先输出3后输出2这就是面试官常常考查的js运行机制的问题接下来我们要引入一个概念JavaScript 是单线程的。
JavaScript 单线程
JavasScript引擎是基于事件驱动和单线程执行的JS引擎一直等待着任务队列中任务的到来然后加以处理浏览器无论什么时候都只有一个JS线程在运行程序即主线程。那么单线程的JavasScript是怎么实现“非阻塞执行”呢是通过任务队列。 所有任务可以分成两种一种是同步任务synchronous另一种是异步任务asynchronous。 单线程就意味着所有任务需要排队前一个任务结束才会执行后一个任务。如果前一个任务耗时很长后一个任务就不得不一直等着。但是如果有些任务很慢时比如Ajax操作从网络读取数据我还是要等结果在执行后一个任务吗于是有了一种异步任务。 同步任务指的是在主线程上排队执行的任务只有前一个任务执行完毕才能执行后一个任务而异步任务指的是不进入主线程、而进入任务队列task queue的任务只有主线程执行完毕主线程去通知任务队列某个异步任务可以执行了该任务才会进入主线程执行。 所以js的运行机制如下 1.所有同步任务都在主线程上执行形成一个执行栈Call Stack 2.主线程之外还存在一个任务队列task queue。只要异步任务有了运行结果就在任务队列之中放置一个事件
-3. 一旦执行栈中的所有同步任务执行完毕系统就会读取任务队列看看里面有哪些事件。那些对应的异步任务于是结束等待状态进入执行栈开始执行。
4.主线程不断重复上面的第三步。
setTimeout运行机制
setTimeout 和 setInterval的运行机制其实就是将指定的代码移出本次执行等到下一轮 Event Loop 时再检查是否到了指定时间。如果到了就执行对应的代码如果不到就等到再下一轮 Event Loop 时重新判断。
这意味着setTimeout指定的代码必须等到本次执行的所有同步代码都执行完才会执行。
10. Promise.all 和 Promise.allSettled 有什么区别
一句话概括Promise.allSettled和Promise.all的最大不同Promise.allSettled永远不会被reject。
Promise.all的痛点
当需要处理多个Promise并行时大多数情况下Promise.all用起来是非常顺手的比如下面这样
const delay n new Promise(resolve setTimeout(resolve, n));const promises [delay(100).then(() 1),delay(200).then(() 2),]Promise.all(promises).then(valuesconsole.log(values))
// 最终输出 [1, 2]可是是一旦有一个promise出现了异常被reject了情况就会变的麻烦。
const promises [delay(100).then(() 1),delay(200).then(() 2),Promise.reject(3)]Promise.all(promises).then(valuesconsole.log(values))
// 最终输出 Uncaught (in promise) 3Promise.all(promises)
.then(valuesconsole.log(values))
.catch(errconsole.log(err))
// 加入catch语句后最终输出3尽管能用catch捕获其中的异常但你会发现其他执行成功的Promise的消息都丢失了仿佛石沉大海一般。
要么全部成功要么全部重来这是Promise.all本身的强硬逻辑也是痛点的来源不能说它错但这的确给Promise.allSettled留下了立足的空间。
Promise.allSettled
假如使用Promise.allSettled来处理这段逻辑会怎样呢? const promises [ delay(100).then(() 1),delay(200).then(() 2),Promise.reject(3)]Promise.allSettled(promises).then(valuesconsole.log(values))
// 最终输出
// [
// {status: fulfilled, value: 1},
// {status: fulfilled, value: 2},
// {status: rejected, value: 3},
// ]可以看到所有promise的数据都被包含在then语句中且每个promise的返回值多了一个status字段表示当前promise的状态没有任何一个promise的信息被丢失。
因此当用Promise.allSettled时我们只需专注在then语句里当有promise被异常打断时我们依然能妥善处理那些已经成功了的promise不必全部重来。