前言
事情是这样的,我在2月出头大概3号左右投的简历,投的是实习岗。然后一直就没有消息,本来以为没有希望了,结果在22号通知我进行面试。总共差不多50到一个小时吧。问了一些八股和代码输出的问题,还有一些手撕。
自我介绍
先来了一段自我介绍,在讲了下项目,讲了大概有20分钟。感觉面试官听我项目的时候觉得有点不好。
大家也可以看下敖丙大佬面试自我介绍5句话公式 - 掘金 (juejin.cn)一文,里面有个公式:我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任。
八股
let, var ,const
(1)块级作用域: 块作用域由 { }
包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:
- 内层变量可能覆盖外层变量
- 用来计数的循环变量泄露为全局变量
(2)变量提升: var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。
(3)给全局添加属性: 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
(4)重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。
(5)暂时性死区: 在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。
(6)初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
函数是否存在变量提升
在代码执行之前,JavaScript 引擎会将变量和函数声明提升到当前作用域的顶部。但只有声明会被提升,而赋值不会被提升。
举个例子:
函数声明会被提升:
js
foo(); // 输出 "Hello, world!"
function foo() {
console.log("Hello, world!");
}
在这个例子中,即使 foo()
的调用在函数声明之前,JavaScript 引擎也会将函数 foo
的声明提升到作用域的顶部,因此函数可以在声明之前被调用。
但是,需要注意的是函数表达式并不会被提升,只有函数声明会被提升:
js
baz(); // 报错:baz is not a function
var baz = function() {
console.log("This is a function expression");
};
在这个例子中,由于 baz
是一个函数表达式而不是函数声明,因此在声明之前调用它会导致错误。
vue组件通信
这个可以看作者的这篇文章打破组件孤岛,带你了解组件通信,讲的非常详细。
防抖和节流
手撕的话,作者在总结一些面试遇到的一些手撕题中总结了,感兴趣可以看看。
防抖
防抖会等待最后一次操作完成后的一段时间,如果还有其他的操作请求,在此期间被触发,则重新计时。这样可以保证在一段时间内只执行一次函数,而不是频繁地执行。这对于输入框的自动完成搜索建议非常有用,当用户停止输入一段时间后,才发送请求。
节流
节流 会限制在一定时间内只能执行一次函数,即使在这个时间内多次触发了事件。节流可以保证在一段时间内有规律地执行函数,而不是频繁地执行。这对于滚动事件处理非常有用,使用节流后滚动不再会不断地调用函数,而是会在滚动停止后固定时间间隔执行一次函数。
浏览器跨域的原因,以及怎么解决
跨域是指浏览器限制从一个源加载的资源与来自另一个源的资源进行交互的安全机制。源由协议、域名和端口组成。
跨域产生的主要原因是浏览器的同源策略,当协议、域名、端口有一个不同就会产生跨域,该策略限制了一个源下的文档或脚本如何与来自另一个源的资源进行交互。
跨域问题可以通过以下方式解决:
- CORS(跨域资源共享) : 在服务端设置 CORS 头部来允许跨域请求。服务器端可以设置 Access-Control-Allow-Origin 头部来指定允许访问的源,也可以设置其他相关头部,如 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers,以控制允许的方法和请求头。在服务器端进行这些配置可以让浏览器知道哪些跨域请求是安全的。
- JSONP(JSON with Padding) : JSONP 是一种利用
<script>
标签不受同源策略限制的特性,通过动态创建<script>
标签来请求跨域资源。服务器端返回的数据需要包裹在指定的回调函数中,客户端定义这个回调函数来处理返回的数据。但 JSONP 只支持 GET 请求,并且存在安全风险,因为它是通过<script>
标签加载 JavaScript 代码执行的。 - 代理: 在同源的服务器端设置一个代理,让代理服务器去请求目标服务器上的资源,然后再将结果返回给客户端。这种方法需要在自己的服务器上部署额外的代理程序,增加了服务器的负担和复杂性。
- CORS Anywhere: CORS Anywhere 是一个开源项目,允许跨域请求通过一个中间代理服务器,然后再发送到目标服务器。你可以部署自己的 CORS Anywhere 代理服务器,也可以使用公共的已经部署好的服务。但需要注意,使用公共服务可能会受到一些限制。
- WebSocket: WebSocket 是一种全双工通信协议,不受同源策略限制。通过 WebSocket 可以建立跨域的实时通信连接。使用 WebSocket 进行跨域通信需要服务端和客户端都支持 WebSocket 协议。
Cookie,Sessionstorage,Localstorage的区别
Cookie、SessionStorage 和 LocalStorage 都是在客户端存储数据的方式,但它们之间有一些区别:
-
Cookie:
- Cookies 是由服务器发送到浏览器并存储在浏览器上的小型文本文件。
- Cookies 主要用于在客户端和服务器之间传递会话信息,如用户身份验证、跟踪用户行为等。
- Cookies 在每次 HTTP 请求中都会被发送到服务器,包括图片、CSS 文件、JavaScript 文件等。
- Cookies 有大小限制(通常为4KB)。
-
SessionStorage:
- SessionStorage 中的数据在当前会话结束时(即浏览器关闭)会被清除。
- SessionStorage 只能在当前会话中的同一个页面或标签页中访问,不能在不同页面或标签页之间共享数据。
-
LocalStorage:
- LocalStorage 与 SessionStorage 类似,但数据存储在本地并且不会随会话结束而被清除。
- LocalStorage 中的数据可以跨会话和跨浏览器窗口进行共享,直到被显式删除。
- LocalStorage 拥有较大的存储容量限制(通常为5MB),比 Cookies 大得多。
总的来说,Cookie 主要用于在客户端和服务器之间传递数据,而 SessionStorage 和 LocalStorage 则主要用于在客户端存储数据。SessionStorage 用于会话级别的数据,而 LocalStorage 用于长期存储的数据。
判断数据类型的方法,以及区别
-
typeof:typeof 是一个 JavaScript 运算符,用于确定给定变量的数据类型。它返回一个表示变量类型的字符串。
jstypeof 42; // "number" typeof "hello"; // "string" typeof true; // "boolean" typeof {}; // "object" typeof []; // "object"(数组也是对象) typeof null; // "object"(这是 typeof 的一个已知问题) typeof undefined; // "undefined" typeof function() {}; // "function"
-
instanceof:instanceof 操作符用于检查对象是否属于某个特定的对象类型。它用于检查对象的原型链。
jsvar arr = []; arr instanceof Array; // true arr instanceof Object; // true(因为数组也是对象)
-
Object.prototype.toString.call():这是一个通用的方法,可以返回准确的对象类型。通过调用 call 方法并传递要检查的值作为上下文,可以获取该值的内部 [[Class]] 属性,从而得到准确的类型。
js
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(function() {}); // "[object Function]"
使用过哪些CSS预处理器
这个我当时没有答上来,事后想起来觉得当时脑袋肯定是抽了。
- Sass:Sass 是最流行的 CSS 预处理器之一,它提供了 Sass(带缩进)和 SCSS(类似于 CSS 的语法)两种语法。Sass 具有强大的功能,如变量、嵌套、混合、继承、模块化等,同时还有大量的工具和框架支持。
- Less:Less 是另一个流行的 CSS 预处理器,它也提供了类似 Sass 的功能,如变量、嵌套、混合等。Less 的语法更接近标准的 CSS,因此有些开发者可能更容易上手。
- Stylus:Stylus 是一个基于 Node.js 的 CSS 预处理器,它采用了极简的语法,允许使用缩进或者括号来定义样式。Stylus 的语法非常灵活,可以通过插件来扩展功能。
- PostCSS:PostCSS 不同于 Sass、Less 和 Stylus,它更像是一个工具集,可以用来转换和增强 CSS。PostCSS 通过插件的形式提供了许多功能,如变量、嵌套、自动前缀、代码优化等。
- CSS-in-JS:CSS-in-JS 并不是传统的 CSS 预处理器,而是一种将 CSS 代码写入 JavaScript 中的方法。通过 CSS-in-JS 库,开发者可以在 JavaScript 中编写样式,从而更好地管理样式与组件之间的关系。
vue-router 有哪些模式
- Hash 模式
- History 模式
区别:
-
URL 格式:
- Hash 模式 :URL 中的路由会以
#
符号开头,如http://example.com/#/about
。 - History 模式 :URL 中的路由不带
#
符号,如http://example.com/about
。
- Hash 模式 :URL 中的路由会以
-
浏览器兼容性:
- Hash 模式:由于 Hash 模式不需要服务器支持,可以在所有浏览器中良好地运行,包括较老的浏览器。
- History 模式:History 模式需要服务器支持,并且要求服务器能够正确地处理所有页面请求,否则可能会导致 404 错误。在不支持 HTML5 History API 的浏览器中可能会出现问题。
-
历史记录处理:
- Hash 模式:路由的改变不会导致浏览器向服务器发送请求,所有的路由都是基于客户端的。因此,在使用浏览器的前进和后退按钮时,会在浏览器的历史记录中添加或删除 hash,但不会触发页面的重新加载。
- History 模式:当路由发生变化时,浏览器会向服务器发送请求,服务器需要返回正确的页面。因此,在使用浏览器的前进和后退按钮时,会触发页面的重新加载,但不会添加或删除页面的浏览历史记录。
[] == ![]
[] == ![]
的结果是 true
。 解题思路:
[]
是一个空数组,它被认为是一个true
。![]
是对空数组进行逻辑非操作,所以![]
的结果是false
。- 现在我们有
[] == false
。
在 JavaScript 中,当使用双等号(==)进行比较时,如果操作数的类型不同,会发生类型转换。在这种情况下,空数组 []
和布尔值 false
的类型不同。
根据 JavaScript 的类型转换规则,当对象与布尔值进行相等比较时,对象会被转换为数字类型。空数组会被转换为数字类型时变成 0。
- 所以,
[] == false
相当于0 == false
。
除了这道还问了一道关于事件循环的题,具体已经想不起来了。
反问
面试感觉我怎么样,有什么需要改进的。
基础比较扎实,但是项目写的有点差,看不出什么。
实习的工作内容是什么
总结
面试了大概有一个小时,然后到现在也没有二面的消息,估计是寄了。然后这次写文章也是为了帮助大家了解下面试。如果感觉有帮助的话,可以点个赞激励下作者吧,求求了。