「offer来了」保姆级巩固你的js知识体系(4.0w字)
Posted 星期一研究室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「offer来了」保姆级巩固你的js知识体系(4.0w字)相关的知识,希望对你有一定的参考价值。
「面试专栏」前端面试之javascript篇
- 🧐序言
- 🥳思维导图环节
- 😏一、JS规范
- 😲二、数据类型
- 1、问:0.1+0.2 === 0.3吗?为什么?
- 2、js数据类型有哪些?具体存在哪里?判断方式是什么?
- 3、什么是浅拷贝?什么是深拷贝?说明并分别写出代码。
- 4、JS整数是怎么表示的?
- 5、Number的存储空间是多大?如果后台发送了一个超过最大数字怎么办?
- 6、NAN是什么,用typeof会输出什么?
- 7、Symbol有什么用处?
- 8、null,undefined的区别
- 9、JS隐式转换,显示转换
- 10、介绍下js有哪些内置对象
- 11、js有哪些方法定义对象
- 12、如何判断一个对象是不是空对象?
- 13、手写题:获取url参数getUrlParams(url)
- 14、数组能够调用的函数有哪些?
- 15、函数中的arguments是数组吗?类数组转数组的方法了解一下?
- 16、手写题:如何判断数组类型?
- 17、手写题:sort快速打乱数组
- 18、手写题:数组去重操作
- 19、手写题:数组扁平化
- 20、`new` 操作符具体干了什么呢?
- 21、手写题:手写一个new方法
- 22、js如何实现继承?
- 23、JS中的垃圾回收机制
- 🤐三、作用域、原型链、闭包
- 😜四、事件
- 🤪五、this问题
- 😋六、Ajax问题
- 🥰七、手写题补充
- 😉八、结束语
- 🐣彩蛋 One More Thing
🧐序言
大家都知道, js
在前端面试中的占比可以说是非常大了。基本上在每一场面试中,有 40% 以上的题都是 js
的题目。 js
不仅考察一个前端人的基础能力,更重要的是前端可以说是以 js
为本,所以也很考察我们的代码能力和逻辑思维。如果说在面试前端中 js
都不过关,那其实还是蛮危险的。
下面的这篇文章中,将讲解我整个秋招备试过程的所有题目。其中,有些知识点是一个很大的范围,但是放在面试系列中整理的话只能是概括性介绍,我将会以链接的方式,将我之前写的文章和其他相关模块的文章,放在题目后进行标注,方便大家更详细的了解当下模块的扩展知识点。
下面开始本文的讲解~📚
🥳思维导图环节
在真正开篇之前,先用一张思维导图来了解全文的内容。详情见下图👇
思维导图收入囊中了,就该开始来架起 js
的知识体系啦~
😏一、JS规范
1、说几条JavaScript的基本规范。
for-in
循环中的变量应该使用let关键字明确限定作用域,从而避免作用域污染。
for(let i in obj){
}
- 比较布尔值/数值时,需用
===
/!==
来比较; switch
语句必须带有default
分支;- 不要使用全局函数;
- 使用对象字面量替代
new Array
这种形式,以下给出对象字面量的例子。
let person = {
name:'张三',
age:13,
like:['打篮球','打排球']
}
2、对原生JavaScript的了解。
数据类型、运算、对象、 Function
、继承、闭包、作用域、原型链、事件、RegExp
、JSON
、Ajax
、DOM
、BOM
、内存泄漏、异步装载、模板引擎、前端MVC
、路由、模块化、Canvas
、ECMAScript
。
3、说下对JS的了解吧。
是基于原型的动态语言,主要特性有this、原型和原型链。
JS严格意义上来说分为:语言标准部分( ECMAScript
)+ 宿主环境部分。
语言标准部分
2015年
发布ES6
,引入诸多特性,使得能够编写大型项目成为可能,标准自2015年
之后以年号作为代号,每年一更。
宿主环境部分
- 在浏览器宿主环境包括
DOM
+BOM
等 - 在
Node
,宿主环境包括一些文件、数据库、网络、与操作系统的交互等
4、JS原生拖拽节点
- 给需要拖拽的节点绑定
mousedown
,mousemove
,mouseup
事件。 mousedown
事件触发后,开始拖拽。mousemove
时,需要通过event.clientX
和clientY
获取拖拽位置,并实时更新位置。mouseup
时,拖拽结束。- 需要注意浏览器边界值,设置拖拽范围。
5、谈谈你对ES6的理解
- 新增模板字符串(为
JavaScript
提供了简单的字符串插值功能)。 - 箭头函数。
for-of
(用来遍历数据——例如数组中的值)。arguments
对象可以被不确定的参数和默认参数完美替代。ES6
将promise
对象纳入规范,提供了原生的promise
对象。- 增加了
let
和const
命令,用来声明变量。 - 还有就是引入
module
模块的概念。
6、知道ES6的class嘛?
ES6
中的 class
是,为这个类的函数对象直接添加方法,而不是加在这个函数对象的原型对象上。
7、说说你对AMD和Commonjs的理解
CommonJS
是服务器端模块的规范,Node.js
采用了这个规范。CommonJS
规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD
规范则是非同步加载模块,允许指定回调函数。AMD
推荐的风格通过返回一个对象作为模块对象。CommonJS
的风格则是通过对module.exports
或exports
的属性赋值来达到暴露模块对象的目的。
8、如何理解前端模块化
前端模块化就是复杂的文件编程中一个个独立的模块,比如js文件等等,分成独立的模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题,所以有了commonJS规范,AMD,CMD规范等等,以及用于js打包(变异等处理)的工具webpack。
9、面向对象编程思想
- 基本思想是使用对象,类,继承,封装等基本概念来进行程序设计;
- 易维护;
- 易扩展;
- 开发工作的重用性、继承性高,降低重复工作量;
- 缩短了开发周期。
10、用过 TypeScript 吗?它的作用是什么?
TypeScript
为 JS
添加类型支持,以及提供最新版的 ES
语法的支持,有利于团队协作和排错,开发大型项目。
11、PWA使用过吗?serviceWorker的使用原理是啥?
渐进式网络应用(PWA)
是谷歌在 2015年底
提出的概念。基本上算是web应用程序,但在外观和感觉上与 原生app
类似。支持 PWA
的网站可以提供脱机工作、推送通知和设备硬件访问等功能。
Service Worker
是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门。 现在,它们已包括如推送通知和后台同步等功能。 将来, Service Worker
将会支持如定期同步或地理围栏等其他功能。
注:渐进式网络应用 Progressive Network Application
😲二、数据类型
1、问:0.1+0.2 === 0.3吗?为什么?
在正常的数学逻辑思维中, 0.1+0.2=0.3
这个逻辑是正确的,但是在 JavaScript
中 0.1+0.2 !== 0.3
,这是为什么呢?这个问题也会偶尔被用来当做面试题来考查面试者对 JavaScript
的数值的理解程度。
0.1 + 0.2 == 0.3 // false
在 JS
中,二进制的浮点数 0.1
和 0.2
并不是精确的,所以它们相加的结果并非正好等于 0.3
,而是一个比较接近 0.3
的数字 0.30000000000000004
,所以条件判断结果为 false
。
原因在于在 JS
当中,采用的是 IEEE 754
的双精度标准,所以计算机内部在存储数据编码的时候,0.1在计算机内部不是精确的 0.1
,而是一个有舍入误差的 0.1
。当代码被编译或解析后, 0.1
已经被四舍五入成一个与之很接近的计算机内部数字,以至于计算还没开始,一个很小的舍入错误就已经产生了。这也就是 0.1 + 0.2
不等于 0.3
的原因。
那如何避免这样的问题?
最常用的方法就是将浮点数转化成整数计算,因为整数都是可以精确表示的。
通常就是把计算数字提升10的N次方倍再除以 10
的 N
次方,一般都用 1000
就行了。
(0.1*1000 + 0.2*1000)/1000 == 0.3 //true
2、js数据类型有哪些?具体存在哪里?判断方式是什么?
(1)js数据类型
js
数据类型包括基本数据类型和引用数据类型。
(2)具体存放在哪里?
基本数据类型:
基本数据类型,是指 Numer
、 Boolean
、 String
、 null
、 undefined
、 Symbol
(ES6新增的)、 BigInt(ES2020)
等值,它们在内存中都是存储在栈中的,即直接访问该变量就可以得到存储在栈中的对应该变量的值。
若将一个变量的值赋值给另一个变量,则这两个变量在内存中是独立的,修改其中任意一个变量的值,不会影响另一个变量。这就是基本数据类型。
引用数据类型:
那引用数据类型呢,是指 Object
、 Array
、 Function
等,他们在内存中是存在于栈和堆当中的,即我们要访问到引用类型的值时,需要先访问到该变量在栈中的地址(指向堆中的值),然后再通过这个地址,访问到存放在堆中的数据。这就是引用数据类型。
(3) 常用判断方式:typeof、instanceof、===
1)typeof:
定义:返回数据类型的字符串表达(小写)
用法:typeof + 变量
可以判断:
-
undefined/ 数值 / 字符串 / 布尔值 / function (返回 ‘undefined’ / ‘number’ / ‘string’ / ‘boolean’ / ‘function’)
-
null与object 、object与array (null、array、object都会返回 ‘object’ )
<script type="text/javascript">
console.log(typeof "Tony"); // 返回 string
console.log(typeof 5.01); // 返回 number
console.log(typeof false); // 返回 boolean
console.log(typeof undefined); // 返回 undefined
console.log(typeof null); // 返回 object
console.log(typeof [1,2,3,4]); // 返回 object
console.log(typeof {name:'John', age:34}); // 返回 object
</script>
2)instanceof:
定义:判断对象的具体类型
用法:b instanceof A
→表明 b
是否是 A
的实例对象
可以判断:
专门用来判断对象数据的类型: Object
, Array
与 Function
判断 String
, Number
, Boolean
这三种类型的数据时,直接赋值为 false
,调用构造函数创建的数据为 true
<script type="text/javascript">
let str = new String("hello world") //console.log(str instanceof String); → true
str = "hello world" //console.log(str instanceof String); → false
let num = new Number(44) //console.log(num instanceof Number); → true
num = 44 //console.log(num instanceof Number); → false
let bool = new Boolean(true) //console.log(bool instanceof Boolean); → true
bool = true //console.log(bool instanceof Boolean); → false
</script>
<script type="text/javascript">
var items = [];
var object = {};
function reflect(value) {
return value;
}
console.log(items instanceof Array); // true
console.log(items instanceof Object); // true
console.log(object instanceof Object); // true
console.log(object instanceof Array); // false
console.log(reflect instanceof Function); // true
console.log(reflect instanceof Object); // true
3)===:
可以判断: undefined
, null
<script type="text/javascript">
let str;
console.log(typeof str, str === undefined); //'undefined', true
let str2 = null;
console.log(typeof str2, str2 === null); // 'object', true
</script>
3、什么是浅拷贝?什么是深拷贝?说明并分别写出代码。
(1)浅拷贝
所谓浅拷贝,就是一个变量赋值给另一个变量,其中一个变量的值改变,则两个变量的值都变了,即对于浅拷贝来说,是数据在拷贝后,新拷贝的对象内部仍然有一部分数据会随着源对象的变化而变化。
// 分析
function shallowCopy(obj){
let copyObj = {};
for(let i in obj){
copyObj[i] = obj[i];
}
return copyObj;
}
// 实例
let a = {
name: '张三',
age: 19,
like: ['打篮球', '唱歌', '跳舞']
}
let b = shallowCopy(a);
a.name = '李四';
a.like[0] = '打打乒乓球';
console.log(a);
console.log(b);
(2)深拷贝
定义:深拷贝 就是,新拷贝的对象内部所有数据都是独立存在的,不会随着源对象的改变而改变。
深拷贝有两种方式:递归拷贝和利用JSON函数进行深拷贝。
- 递归拷贝的实现原理是:对变量中的每个元素进行获取,若遇到基本类型值,直接获取;若遇到引用类型值,则继续对该值内部的每个元素进行获取。
- JSON深拷贝的实现原理是:将变量的值转为字符串形式,然后再转化为对象赋值给新的变量。
局限性:深拷贝的局限性在于,会忽略 undefined
,不能序列化函数,不能解决循环引用的对象。
递归拷贝方式实现代码:
// 分析
function deepCopy(obj){
// 判断是否为引用数据类型
if(typeof obj === 'object'){
let result = obj.constructor === Array ? [] : {};
// 对引用类型继续进行遍历,如果遍历没有结束的话
for(let i in obj){
result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
}
return result;
}
// 为基本数据类型,直接赋值返回
else{
return obj;
}
}
// 实例 - 利用递归函数做深拷贝
let c = {
name:'张三',
age:12,
like:[
'打乒乓球',
'打羽毛球',
'打太极'
]
}
let d = deepCopy(c);
c.name = '李四';
c.like[0] = '打篮球';
console.log(c);
console.log(d);
JSON深拷贝实现代码:
// 实例 - 利用json函数做深拷贝
let e = {
name: '张三',
age: 19,
like:['打羽毛球', '唱歌', '跳舞']
}
let f = JSON.parse(JSON.stringify(e));
// 注意: JSON函数做深度拷贝时不能拷贝正则,Date,方法函数等
e.name = '李四';
e.like[0] = '打乒乓球';
// console.log(e);
// console.log(f);
这里可以在参考我之前写过的一篇文章辅助理解👉栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!
4、JS整数是怎么表示的?
JS整数通过 Number
类型来表示,遵循 IEEE 754
标准,通过 64位
来表示一个数字,即 1+11+52
(符号位+指数位+小数部分有效位),最大安全数字是 253 - 1,对应 16位
十进制数。
注:1位十进制数对应4位二进制数
5、Number的存储空间是多大?如果后台发送了一个超过最大数字怎么办?
Math.pow(2,53),53为有效数字;如果后台发送一个超过最大数字,会发生截断,等于 JS
能支持的最大安全数字 253 - 1。
6、NAN是什么,用typeof会输出什么?
Not a Number,表示非数字。
typeof NaN === 'number'; //true
7、Symbol有什么用处?
- 可以用来表示一个独一无二的变量,防止命名冲突。
- 除此之外,
Symbol
还可以用来模拟私有属性。
- 详细文章补充👇
- 原文:面试官:JavaScript 原始数据类型 Symbol 有什么用?
- 链接:https://www.cnblogs.com/lzkwin/p/12666300.html
8、null,undefined的区别
undefined
表示不存在这个值。undefined
是一个表示“无”的原始值或者说表示“缺少值”,就是此处应该有一个值,但是还没有定义。尝试读取时就会返回undefined
。- 例如变量被声明了,但没有赋值时,就等于
undefined
。 null
表示一个对象被定义了,值为“空值”。null
是一个对象(空对象,没有任何属性和方法)。- 例如作为函数的参数时,表示该函数的参数不是对象。
- 在验证
null
时,一定要使用===
,因为==
无法区分null
和undefined
。
9、JS隐式转换,显示转换
一般非基础类型进行转换时会调用valueOf,如果 valueOf
无法返回基本类型值,就会调用toString。
(1)字符串和数字
- “+”操作符,如果有一个为字符串,那么都转化到字符串然后执行字符串拼接。
- “-”操作符,转换为数字,相减(-a, a*1, a/1)都能进行隐式强制类型转换。
[] + {} 和 {} + []
(2)布尔值到数字
- 1 + true = 2;
- 1 + false = 1;
(3)转换为布尔值
- for中第二个
- while
- if
- 三元表达式
- || (逻辑或)和 &&(逻辑与)左边的操作个数
(4)符号
- 不能被转换为数字
- 能被转换为布尔值(都是true)
- 可以被转换成字符串“Symbol(cool)”
(5)宽松相等和严格相等
宽松相等允许进行强制类型转换,而严格相等不允许。
①字符串与数字
- 转换为数字然后比较
②其他类型与布尔类型
- 先把布尔类型转换为数字,然后继续进行比较
③对象与非对象
- 执行对象的
ToPrimitive
(对象)然后继续进行比较
④假值列表
- undefined
- null
- false
- +0,-0,NaN
- “”
10、介绍下js有哪些内置对象
Object
是Javascript
中所有对象的父对象;- 其他数据封装类对象:
Object
、Array
、Boolean
、Number
和String
; - 其他对象:
Function
、Arguments
、Math
、Date
、RegExp
、Error
。
11、js有哪些方法定义对象
- 对象字面量:
let obj = {}
; - 构造函数:
let obj = new Object()
; - Object.create():
let obj = Object.create(object.prototype)
;
12、如何判断一个对象是不是空对象?
Object.keys(obj).length === 0
13、手写题:获取url参数getUrlParams(url)
//封装函数getUrlParams, 将URL地址的参数解析为对象
function getUrlParams(url){
let obj = {};
if(url.indexOf('?') === -1){
return obj;
}
let first_res = url.split('?')[1];
let second_res = first_res.split('&');
for(let i in second_res){
third = second_res[i].split('=');
obj[third[0]] = third[1];
}
return obj;
}
// 测试代码
let URL = 'https://www.sogou.com/web?ie=UTF-8&query=搜索内容&_em=3';
console.log(getUrlParams(URL));
14、数组能够调用的函数有哪些?
push
向数组尾部添加元素pop
删除并返回数组最后一个元素splice
添加/删除元素slice
返回选定的元素shift
删除第一个元素并返回unshift
向数组开头添加一个或更多元素,并返回新长度sort
对数组元素进行排序find
返回通过测试的数组的第一个元素findIndex
map/filter/reduce
等函数式编程方法- 原型链上的方法:
toString/valueOf
15、函数中的arguments是数组吗?类数组转数组的方法了解一下?
是类数组,是属于鸭子类型的范畴,只是长得像数组。
- … 运算符
- Array.from
- Array.prototype.slice.apply(arguments)
16、手写题:如何判断数组类型?
// 方法一:instanceof方法
let arr = [1, 2, 3];
console.log(arr instanceof Array);
// 方法二:constructor方法
let arr = [1, 2, 3];
console.log(arr.constructor === Array);
// 方法三:isArray方法
let arr = [1, 2, 3];
console.log(Array.isArray(arr));
// 方法四:Object.prototype方法
let arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr) === '[object Array]');
// 方法五:Array.__proto__方法
let arr = [1, 2, 3];
console.log(arr.__proto__ === Array.prototype);
// 方法六:Object.getPrototypeOf方法
let arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype);
// 方法七:Array.prototype.isPrototypeOf方法
let arr = [1, 2, 3];
console.log(Array.prototype.isPrototypeOf(arr「offer来了」2种递进学习思维,24道计网题目,保姆级巩固你的计网知识体系
「offer来了」2种递进学习思维,24道计网题目,保姆级巩固你的计网知识体系
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系