挑战一轮大厂后的面试总结 (含六个方向) - javascript 篇(万字长文)

在去年底开始换工作,直到现在算是告了一个段落,断断续续的也面试了不少公司,现在回想起来,那段时间经历了被面试官手撕,被笔试题狂怼,悲伤的时候差点留下没技术的泪水。

这篇文章我打算把我找工作遇到的各种面试题(每次面试完我都会总结)和我自己复习遇到比较有意思的题目,做一份汇总,年后是跳槽高峰期,也许能帮到一些小伙伴。

先说下这些题目难度,大部分都是基础题,因为这段经历给我的感觉就是,不管你面试的是高级还是初级,基础的知识一定会问到,甚至会有一定的深度,所以基础还是非常重要的。

我将根据类型分为几篇文章来写:

面试总结:javascript 面试点汇总(万字长文)(已完成) 强烈大家看看这篇,面试中 js 是大头

面试总结:nodejs 面试点汇总(已完成)

面试总结:浏览器相关 面试点汇总(已完成)

面试总结:css 面试点汇总(已完成)

面试总结:框架 vue 和工程相关的面试点汇总(已完成)

面试总结:面试技巧篇(已完成)

六篇文章都已经更新完啦~

这篇文章是对 javascript 相关的题目做总结,内容有点长,大致算了下,有接近 2W 字,推荐用电脑阅读,欢迎朋友们先收藏在看。

先看看目录(这长图在手机上比较模糊,可点击图片看大图)

Q:介绍下原型链

原型链这东西,基本上是面试必问,而且不是知识点还都是基于原型链扩展的,所以我们先把原先链整明白。
我们看一张网上非常流行的图
js-object-layout
嗯,箭头有点多且有点绕,没关系,我们可逐步分析,我们从结果倒推结论,这样更直观些,看代码

function person() {
   
  this.name = 10
}
person.prototype.age = 10
const p = new person()
分析构造函数

我们通过断点看下 person 这个函数的内容

prototype

它是一个自定义的函数类型,看关键的两个属性 prototype__proto__ ,我们一一分析

  1. prototype 分析

prototype 展开看,是个自定义的对象,这个对象有三个属性 age constructor __proto__
age 的值是 10 ,那么可以得出通过person.prototype 赋值的参数都是在 prototype 这个对象中的。

点开 constructor,发现这个属性的值就是指向构造器 preson 函数,其实就是循环引用,这时候就有点套娃的意思了

constructor

那么,根据字面意思, prototype 可以翻译成,原先对象,用于扩展属性和方法。

  1. __proto__ 分析
    __proto__ 展开看看

prop

person 中的 __proto__ 是一个原始的 function 对象,在 function 对象中,又看到了 __proto__ 这个属性,这时候它的值是原始的 Object 对象,在 Object 对象中又再次发现了 __proto__ 属性,这时候 __proto__ 等于 null

js 中数据类型分为两种,基本类型和对象类型,所以我们可以这么猜测,person 是一个自定义的函数类型,它应该是属于函数这一家族下的,对于函数,我们知道它是属于对象的,那么它们几个是怎么关联起来的呢?

没错,就是通过 __proto__ 这个属性,而由这个属性组成的链,就叫做原型链。

根据上面的例子我们,可得出,原型链的最顶端是 null ,往下是 Object 对象,而且只要是对象或函数类型都会有 __proto__ 这个属性,毕竟大家都是 js-family 的一员嘛。

分析生成的对象

上面我们已经知道了原型和原型链,那么对于 new 出来的对象,它们的关系又是怎么样的呢?继续断点分析

p

p 对象中有个 __proto__ 属性,我们已经知道这是个原型链,通过它可以找到我们的祖先,展开 __proto__ ,大家看到这里有没有发现很眼熟,在看一张图,

p1

没错!p.__proto__ 就是 person 函数的 prototype ,这一步也就是 new 的核心点(下个题目我们会说到)。

那么 p 这实例的原型链是怎么样的?
p.__proto__ => {constructor:func}.__proto__ => Object => null

proto-link

对于实例对象来说,原先链主要用来做什么呢?

  • 实现继承:如果没有原型链,每个对象就都是孤立的,对象间就没有关联,所以原型链就像一颗树干,从而可以实现面对对象中的继承
  • 属性查找:首先在当前实例对象上查找,要是没找到,那么沿着 __proto__ 往上查找
  • 实例类型判断:判断这个实例是否属于某类对象

还有就是,光看文字的解释还是有点费解的,要想深入理解,还是需要多动手断点调试,才能很快理顺。

若还是不太理解实例对象的原型链关系,可以看下一题:解释构造函数

Q:介绍下构造函数是什么?

构造函数与普通函数在编码上没有区别,只要可以通过 new 来调用的就是构造函数。

那么什么函数不可以作为构造函数呢?

箭头函数不可以作为构造函数。

new 是一个语法糖,对执行的原理一步步拆分并自己写一个模拟 new 的函数:
0. 自定义一个 objectFactory 模拟 new 语法糖,函数可以接受多个参数,但要求第一个参数必须为构造函数

  1. 创建一个空对象 obj ,分配内存空间

  2. 从参数列表中获取构造函数,并将 obj__proto__ 属性指向构造函数的 prototype

  3. 通过 apply 执行构造,并将当前 this 的指向改为 obj

  4. 返回构造函数的执行结果,或者当前的 obj 对象

function objectFactory() {
   
  var obj = {
   },
  Constructor = [].shift.call(arguments);
  obj.__proto__ = Constructor.prototype;
  var ret = Constructor.apply(obj, arguments);
  return typeof ret === 'object' ? ret : obj;
};
function fnf() {
   
    this.x = 123
}
let a2 = objectFactory(fnf) // 模拟 new fnf()
console.log(a2.x) // 123

可看出并不复杂,关键点在第二步,设置对象的原型链,这也是创建实例对象的核心点。

Q:typeof 和 instanceof 有什么区别

js 中数据类型分为两类,一类是基本数据类型,一类是对象类型。

基本数据类型有:Number String Boolean Null Undefined BigInt Symbol

对象类型: Object 也叫引用类型

  1. typeof(a) 用于返回值的类型,有 “number”、“string”、“boolean”、“null”、“function” 和 “undefined”、“symble”、“object”
let a = 1
let a1 = '1'
let a2 = true
let a3 = null
let a4 = undefined
let a5 = Symbol
let a6 = {
   }
console.log(typeof(a),typeof(a1),typeof(a2),typeof(a3),typeof(a4),typeof(a5),typeof(a6))
// number string boolean object undefined function object
  1. instanceof 用于判断该对象是否是目标实例,根据原型链 __proto__ 逐层向上查找,通过 instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。

有这么个面试题

function person() {
   
    this.name = 10
}
console.log(person instanceof person)

结果是 false ,看下 person 函数的原型链 person.proto_ => Function.proto=> Object.proto=> null ,所以在原型链上是找不到 person

Q:数据类型有哪几种?

  • 7 种原始数据类型: Null Undefined String Number Boolean BigInt Symbol
  • Object 对象类型,也称为引用类型

Q:JS中基本数据类型和引用类型在内存上有什么区别?

基本类型:存储在栈内存中,因为基本类型的大小是固定,在栈内可以快速查找。

引用类型:存储在堆内存中,因为引用类型的大小是不固定的,所以存储在堆内存中,然后栈内存中仅存储堆中的内存地址。

我们在查找对象是从栈中查找,那么可得知,对于基本对象我们是对它的值进行操作,而对于引用类型,我们是对其引用地址操作。

var name = 'xiaoming'
var name1 = name; // 值拷贝
var obj = {
   age:10}
var obj1 = obj // 引用地址的拷贝,所以这两个对象指向同一个内存地址,那么他们其实是同一个对象

stack-heap

关于函数的传参是传值还是传引用呢?

很多人说基本类型传值,对象类型传引用,但严格来说,函数参数传递的是值,上图可以看出,就算是引用类型,它在栈中存储的还是一串内存地址,所以也是一个值。不过我觉得没必要过于纠结这句话,理解就行。

Q:描述 NaN 指的是什么

NaN 属性是代表非数字值的特殊值,该属性用于表示某个值不是数字。

NaN 是 Number 对象中的静态属性

typeof(NaN) // "number"
NaN == NaN // false

那怎么判断一个值是否是 NAN 呢? 若支持 es6 ,可直接使用 Number.isNaN()

若不支,可根据 NAN !== NAN 的特性

function isReallyNaN(val) {
   
    let x = Number(val);
    return x !== x;
}

Q:描述 null

null 是基本类型之一,不是 Object 对象,至于为什么?答曰:历史原因,咱也不敢多问


                
  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值