专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

元宵节,更应该搞起来!中高级Web前端面经:JavaScript篇

ins518 2024-10-04 01:51:59 技术文章 12 ℃ 0 评论

前言

今天是元宵节,猿宵节。一个作为程序员通宵加班的节日,就应该来篇文章祝个兴。承接之前俩篇文章的内容。今天仍是JavaScript的面试内容。

接招吧~

zhen

1. 闭包

闭包属于一种特殊的作用域,称为 静态作用域。它的定义可以理解为: 父函数被销毁 的情况下,返回出的子函数的[[scope]]中仍然保留着父级的单变量对象和作用域链,因此可以继续访问到父级的变量对象,这样的函数称为闭包。

  • 闭包会产生一个很经典的问题:
  • 多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。
  • 解决:
  • 变量可以通过 函数参数的形式 传入,避免使用默认的[[scope]]向上查找
  • 使用setTimeout包裹,通过第三个参数传入
  • 使用 块级作用域,让变量成为自己上下文的属性,避免共享

2. script 引入方式:

  • html 静态<script>引入
  • js 动态插入<script>
  • <script defer>: 异步加载,元素解析完成后执行
  • <script async>: 异步加载,但执行时会阻塞元素渲染

3. 对象的拷贝

  • 浅拷贝: 以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响
  • Object.assign
  • 展开运算符(...)
  • 深拷贝: 完全拷贝一个新对象,修改时原对象不再受到任何影响
  • JSON.parse(JSON.stringify(obj)): 性能最快
  • 具有循环引用的对象时,报错
  • 当值为函数、undefined、或symbol时,无法拷贝
  • 递归进行逐一赋值

4. new运算符的执行过程

  • 新生成一个对象
  • 链接到原型: obj.__proto__ = Con.prototype
  • 绑定this: apply
  • 返回新对象(如果构造函数有自己 retrun 时,则返回该值)

5. instanceof原理

能在实例的 原型对象链 中找到该构造函数的prototype属性所指向的 原型对象,就返回true。即:

// __proto__: 代表原型对象链
instance.[__proto__...] === instance.constructor.prototype
// return true
复制代码

6. 代码的复用

当你发现任何代码开始写第二遍时,就要开始考虑如何复用。一般有以下的方式:

  • 函数封装
  • 继承
  • 复制extend
  • 混入mixin
  • 借用apply/call

7. 继承

在 JS 中,继承通常指的便是 原型链继承,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。

  • 最优化: 圣杯模式
var inherit = (function(c,p){
	var F = function(){};
	return function(c,p){
		F.prototype = p.prototype;
		c.prototype = new F();
		c.uber = p.prototype;
		c.prototype.constructor = c;
	}
})();
复制代码
  • 使用 ES6 的语法糖 class / extends

8. 类型转换

大家都知道 JS 中在使用运算符号或者对比符时,会自带隐式转换,规则如下:

  • -、*、/、% :一律转换成数值后计算
  • +:
  • 数字 + 字符串 = 字符串, 运算顺序是从左到右
  • 数字 + 对象, 优先调用对象的valueOf -> toString
  • 数字 + boolean/null -> 数字
  • 数字 + undefined -> NaN
  • [1].toString() === '1'
  • {}.toString() === '[object object]'
  • NaN !== NaN 、+undefined 为 NaN

9. 类型判断

判断 Target 的类型,单单用 typeof 并无法完全满足,这其实并不是 bug,本质原因是 JS 的万物皆对象的理论。因此要真正完美判断时,我们需要区分对待:

  • 基本类型(null): 使用 String(null)
  • 基本类型(string / number / boolean / undefined) + function: 直接使用 typeof即可
  • 其余引用类型(Array / Date / RegExp Error): 调用toString后根据[object XXX]进行判断

很稳的判断封装:

let class2type = {}
'Array Date RegExp Object Error'.split(' ').forEach(e => class2type[ '[object ' + e + ']' ] = e.toLowerCase()) 
function type(obj) {
 if (obj == null) return String(obj)
 return typeof obj === 'object' ? class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof obj
}

尾声

无论怎么样,在这个元宵佳节,还是祝各位开开心心,一年没bug~

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表