前端框架
前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。
以 Vue 为例,我整理了如下的面试题。
如果你觉得对你有帮助,可以戳这里获取:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
let count = 0;
setTimeout(() => {
console.log(“base.count”, ++count);
}, 500)
exports const count = count;
// es6.js
import { count } from’./base1’;
setTimeout(() => {
console.log(“count is” + count + ‘in es6’);
}, 1000)
答案:1,0,1,1
解析:
-
CommonJs模块输出的是一个值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
-
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
详细分析请看《require和import的区别》
2.下面代码输出什么
console.log((function() {
console.log(1);
setTimeout(function() {
console.log(2)
}, 1000)
setTimeout(function() {
console.log(3)
}, 0);
setTimeout(function() {
console.log(4)
}, 0);
console.log(5)
})());
答案:1, 5, undefined, 3, 4, 2
3.下面代码输出什么
console.log((typeofnull ));
console.log((typeof []));
console.log((typeofSymbol()));
console.log((typeof123n) );
function foo() {
console.log(111);
};
console.log((typeof foo));
答案
-
object
-
object
-
symbol
-
bigint
-
function
4.下面代码输出什么
function *foo(x) {
const y = 2 * (yield (x + 1));
const z = yield (y / 3);
return (x + y + z);
}
const a = foo(5);
console.log(a.next());
console.log(a.next());
console.log(a.next());
const b = foo(5);
console.log(b.next());
console.log(b.next(12));
console.log(b.next(13));
答案:
{ value: 6, done: false }
{ value: NaN, done: false }
{ value: NaN, done: true }
{ value: 6, done: false }
{ value: 8, done: false }
{ value: 42, done: true }
解析:先看使用Generator函数生成的迭代器a
:
-
第一次调用next方法,遇到 yield 停止,返回yield表达式的值,此时为
5 + 1 = 6
; -
第二次调用next方法,遇到 yield 停止,返回yield表达式的值,由于next方法没有带参数,上一个yield表达式返回值为
undefined
, 导致y
的值等于2*undefined
即(NaN
),除以3
以后还是NaN
,因此返回对象的value
属性也等于NaN
。 -
第三次调用next方法,执行的是
return (x + y + z)
,此时x
的值为5
,y
的值为NaN
, 由于next方法没有带参数,上一个yield表达式返回值为undefined
,导致z为 undefined,返回对象的 value属性等于5 + NaN + undefined
,即 NaN
再来看看使用Generator函数生成的迭代器b
:
-
第一次调用next方法,遇到 yield 停止,返回yield表达式的值,此时为
5 + 1 = 6
; -
第二次调用next方法,遇到 yield 停止,返回yield表达式的值,由于next方法带有参数
12
,所以上一个yield表达式返回值为12
, 因此y
的值等于2*12
即(24
),除以3
是8
,因此返回对象的value
属性为8
。 -
第三次调用next方法,执行的是
return (x + y + z)
,此时x
的值为5
,y
的值为24
, 由于next方法没有带参数13
,因此z为13
,返回对象的 value属性等于5 + 24 + 13
,即42
详细分析请看《Generator函数》
5.下面代码输出什么
let z = 1;
function *foo() {
const x = yield2;
z++;
const y = yield (x * z);
console.log(x, y, z);
}
const a = foo();
const b = foo();
let val1 = a.next().value;
console.log(val1);
let val2 = b.next().value;
console.log(val2);
val1 = a.next(val2 * 10).value;
console.log(val1);
val2 = b.next(val1 * 5).value;
console.log(val2);
a.next(val2 / 2);
b.next(val1 / 4);
答案:
-
2
-
2
-
40
-
600
-
20 300 3
-
200 10 3
解析
-
*foo()
的两个实例同时启用,两个next()
分别从yield 2
语句得到2
-
val2 * 10
也就是2 * 10
,发送到第一个生成器实例a
, 因为x得到的值20
。z
从1
增加到2
,然后20 * 2
通过yield
发出,将val1
设置为40
-
val1 * 5
也就是40 * 5
,发送到第二个生成器实例b
,因此x得到的值200
。z
再从2
递增到3
,然后200*3
通过yield
发出,将val2
设置为600
-
val2 / 2
也就是600 / 2
发动到第一个生成器实例a
, 因此 y得到值300
, 然后打印出x y z
的值分别为20, 300, 3
。 -
val1 / 4
也就是40 / 4
, 发送到第二个生成器实例b
, 因此y
得到的值10
, 然后打印出x y z
的值分别为200, 10, 3
。
详细分析请看《Generator函数》
简答题
1. commonjs模块和ES6模块的区别
-
CommonJs模块输出的是一个值的拷贝,ES6模块输出的是值的引用。
-
CommonJs模块是运行时加载,ES6模块是编译时输出接口。
详细分析请看《require和import的区别》
2. JS有哪几种数据类型
JavaScript有八种内置类型
-
空值(null)
-
未定义(undefined)
-
布尔值(boolean)
-
数字(number)
-
字符串(string)
-
对象 (object)
-
符号(symbol, ES6中新增)
-
大整数(BigInt, ES2020 引入)
除对象外,其他统称为“基本类型”。
注意新增的
symbol
和BigInt
3. typeof 原理是什么
typeof
原理:不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。
-
000: 对象
-
010: 浮点数
-
100:字符串
-
110:布尔
-
1:整数
typeof null 为"object", 原因是因为 不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"。
关键词:JavaScript数据类型的相关底层机制
4. instanceof 原理是什么,自己可以自定义一个么
instanceof
的语法:
object instanceofconstructor
// 等同于
constructor.prototype.isPrototypeOf(object)
-
object:要检测的对象
-
constructor:某个构造函数
instanceof
原理:检测constructor.prototype
是否存在于参数 object的 原型链上。instanceof
查找的过程中会遍历object
的原型链,直到找到constructor
的prototype
,如果查找失败,则会返回false
,告诉我们,object
并非是constructor
的实例。
对象的Symbol.hasInstance
属性,指向一个内部方法。当其他对象使用instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo
在语言内部,实际调用的是FooSymbol.hasInstance。
class MyClass {
return foo instanceofArray;
}
}
[1, 2, 3] instanceofnew MyClass() // true
关键词:instanceof 用法,原型链,
Symbol.hasInstance
。详细分析请查看《 typeof和instanceof原理》
5. setTimeout和setInterval 区别是什么,怎么用 setTimeout实现 setInterval
-
setTimeout: 指定延期后调用函数,每次setTimeout计时到后就会去执行,然后执行一段时间后才继续setTimeout,中间就多了误差,(误差多少与代码的执行时间有关)。
-
setInterval:以指定周期调用函数,而setInterval则是每次都精确的隔一段时间推入一个事件(但是,事件的执行时间不一定就不准确,还有可能是这个事件还没执行完毕,下一个事件就来了).
setTimeout(function fn(){
console.log(‘我被调用了’);
setTimeout(fn, 100);
},100);
6. 怎么理解setTimeout(()=> {}, 0)
执行该语句时,是立即把当前定时器代码推入事件队列,当定时器在事件列表中满足设置的时间值时将传入的函数加入任务队列,之后的执行就交给任务队列负责。但是如果此时任务队列不为空,则需等待,所以执行定时器内代码的时间可能会大于设置的时间。
HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔)不得低于4毫秒。当指定的时间低于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的延迟时间设置为0,实际上可能为 4毫秒后才事件推入任务队列。
7. requestAnimationFrame是什么,有什么应用场景, requestIdleCallback是什么,有什么应用场景
-
requestAnimationFrame
是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。 -
requestIdleCallback()
常用来切割长任务,利用空闲时间执行,避免主线程长时间阻塞。
8. for…of 原理是什么?
for…of 不只是用来遍历数组的,只要有iterator
接口的数据结构都可以用它来遍历。一个数据结构只要部署了Symbol.iterator
属性,就被视为具有iterator
接口。iterator
的实现思想来源于单向链表
。
关键词:
iterator
,Symbol.iterator
, 单向链表。详细分析请看《for…of原理解析》
9. 自己实现一个迭代器?
function makeIterator(array) {
var nextIndex = 0;
return {
基础面试题
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
主要内容包括:HTML,CSS,JavaScript,浏览器,性能优化等等
requestIdleCallback()
常用来切割长任务,利用空闲时间执行,避免主线程长时间阻塞。
8. for…of 原理是什么?
for…of 不只是用来遍历数组的,只要有iterator
接口的数据结构都可以用它来遍历。一个数据结构只要部署了Symbol.iterator
属性,就被视为具有iterator
接口。iterator
的实现思想来源于单向链表
。
关键词:
iterator
,Symbol.iterator
, 单向链表。详细分析请看《for…of原理解析》
9. 自己实现一个迭代器?
function makeIterator(array) {
var nextIndex = 0;
return {
基础面试题
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
主要内容包括:HTML,CSS,JavaScript,浏览器,性能优化等等
[外链图片转存中…(img-eGWLTjHM-1715620238816)]