面试题

>1 原型对象和原型链

​ 每一个构造函数身上都有一个属性prototype指向原型对象 原型对象上又有一个属性constructor指向构造函数本身

​ 每一个·实例身上都有一个属性__proto__,指向所属构造函数的原型对象

​ 实例在查找成员的机制 如果自身没有 会沿着原型对象向上查找直到null

​ 所谓原型链就是对象成员的访问机制 实例在查找成员时 如果自身没有 会沿着原型对象向上查找 直到1null
> 2 数据类型检测()

​ type of 只能检测原始值类型 引用值类型无法很好的分辨

​ instance of 检测一个对象是否是构造函数的实例

​ constructor 检测实例是否属于某个构造函数 可以手动修改

​ Object.prototype.toString.call(要检测的数据).slice(8,-1)准确检测数据的数据类型
>3 JS中函数里的this指向什么地方

​ 普通函数的执行 this指向window

​ 对象方法的this指向对象本身

​ 谁调用的方法 this指向谁

​ 定时器 回调函数和立即执行函数的this指向window

​ 箭头函数没有自己的this 指向执行上下文

​ 事件处理函数中的this指向事件源

​ 可以利用call apply bind方法手动改变this

​ 构造函数中的this指向实例对象
> 4 JS如何拷贝一个数据?
​ 如果是原始值类型 直接用赋值等号
​ 如果是引用值类型 我们可以通过展开运算符做浅拷贝(还可以用JSON) 如果想实现深拷贝
呢 我们需要用递归操作对每一个内部的引用值类型再次拷贝 实际工作中我们一般引入lodash身上的工具函数来实现
> 5 JS如何实现继承?

​ ES6之前的实现继承一般有原型链继承 构造函数继承 组合式继承

​ 原型链继承:子类的原型对象指向父类的实例

​ 缺点1:子类实现不能传入参数配置自己的属性

​ 缺点2:如果父类实例的属性是引用值类型 子类实例会共享这个属性

​ 构造函数继承:在子类的构造器函数中通过call方法改变父类构造器的this指向

​ 缺点1:是不是不能继承父类原型上的方法

​ 组合式继承:原型链继承 +构造函数继承

​ ES6中,通过extends关键字实现完美的继承 以前的继承方法可以弃用了
> 6 get请求和post请求

​ get请求参数拼接在url后面 get传递的参数大小有限制 相对较小 安全程度不高

​ post请求参数放在send()的请求主体 post传递的内容会大很多 相对安全
>7 事件轮询机制

​ 代码进入执行的时候 浏览器会解析同步和异步代码

​ 同步代码进入执行环境栈 依次执行

​ 异步代码进入消息队列 等待同步代码执行完毕后 再按照顺序进入执行栈

​ 异步代码执行时会先执行微任务再执行宏任务

​ 异步代码进入主栈会再次进行解析 形成事件循环机制
> 8聊一下回调地狱 解决方案?

​ 在之前的异步代码书写中 经常会遇到回调函数反复嵌套 形成了所谓的回调地狱 对于代码的维护非常不友好

​ 在ES6中提出了promise这个概念 它是对异步编程的一个优化 聊清楚promise promise也不能完全舍弃回调函数

​ 在最新的ES6规范中 通过async和await来优化异步编程 让异步代码写的和同步代码一样简洁

> 9 ES6的模块化语法

​ 如果希望在不同的文件中引入模块 ES6提供了专门的模块化语法

​ 通过export关键字暴露模块 通过import关键字引入模块
> 10闭包 柯里化函数u

​ 变量的跨作用域方法 函数定义的作用域和执行的作用域不是同一个 都成为闭包

​ 持久性闭包的作用 :1.保存变量 2.保护变量

​ 柯里化函数 预处理思想 分布思想处理
> 11高阶函数

​ HOF函数的参数是函数 或者函数的返回值是函数 都可以视为高阶函数

​ 高阶函数可以实现对函数扩展(希望不直接修改原始函数,而是通过高阶函数对这个函数做功课能扩展)
> 12 rest参数和arguments的区别

​ 1.rest参数和arguments都可以用来收集函数调用时传入的实参

​ 2.使用rest参数 必须在形参中写上...rest 使用arguments可以直接在函数体中使用

​ 3.rest参数是ES6中新增的语法 可以收集部分实参 但是必须写在形参最后一个参数 arguments参数是ES5之前的语法 收集所有的实参

​ 4.rest参数将收集的参数整理为一个真数组 而arguments收集的参数整理成一个类数组
> 13 么是作用域和作用域链

​ 1.作用域是执行时内部标识符起作用的范围 可以分为全局作用域 局部作用域 块级作用域

​ 2.作用域链是标识符查找的一个机制 函数调用时 标识符会在当前作用域查找,如果没有 则向外层作用域查找 直至window
> 14 JS中遍历数组的方法有哪些? 它们有什么区别

​ forEach 没有返回值 不可终止

​ map 返回了一个执行了函数条件的数组

​ filter 返回一个满足了函数条件的数组

​ some 如果有一个数组元素满足条件 返回true

​ every 如果所有数组元素都满足条件 返回true

​ find 找到第一个满足条件的数组元素
> 15 call apply bind 是什么 它们有什么区别?

​ 这3个方法是函数实例的方法 定义在Function构造函数的原型对象上

​ call apply 会立即执行函数 并且改变函数中this的指向(指向传入的第一个参数) call会接收多个剩余参数

​ apply接收一个数组收集剩余参数 有了展开运算符可以只用call完全代替apply

​ bind不会立即执行函数 会返回一个新函数 同样会改变函数中的this指向 (指向传入的第一个参数)后面也会接收多个剩余参数

 

>16 箭头函数和普通函数的区别,哪些场景不适合使用箭头函数?
  1.从结构上看,普通函数要用关键function来定义 箭头函数用=>来定义
  2.从使用来看,普通函数有自己的this和arguments,而箭头函数不能使用argumens(可以使用rest参数),箭头函数的this从外部作用域获得
  3.普通函数可以用new关键字生成实例对象 箭头函数不能使用new关键字

>17 函数执行的过程?
  词法分析=>初始化 arguments this 作用域链 变量提升 =>形参赋值=>执行函数体代码

>18 JS中的堆栈内存?
  JS变量储存数据在内存中会分配不同的地址 原始值类型会被分配到栈内存中 引用值类型会被分配到堆内存中 同时在栈内存中生成了1个16进制的引用值地址 变量保存的是这个引用值地址

>19 new 关键字干了些什么?
  1.定义一个空对象 让空对象的隐式原型等于构造函数的显示原型
​   2.让构造函数的this指向空对象
​   3.执行构造函数
​   4.返回实例对象

>20 JS中如何遍历一个对象?
  一般地 我们可以用for in循环来遍历一个对象 但是这种遍历方式会遍历到原型身上的属性 所以我们可以用Object.getOwnPropertyNames()来获取自身身上的属性

>21 JS中如何判断一个对象是否具有某个属性?
  in运算符来判断 但更推荐使用 hasOwnProperty()来判断

>22 类和构造函数的区别?
​  这2者都可以批量生产对象
  类是ES6新增的语法 它的本质还是通过构造函数实现的 在类中我们新增了constructor super等关键字 constructor挂载实例的属性 super可以继承父类的成员
​  类不能当作普通函数执行 只能配合new执行 构造函数可以当作普通函数执行 也可以配合new执行
​  类中定义的方法不可枚举 构造函数定义的方法是可以枚举的
​  类的语法更符合面向对象的思想 它将所有的相关代码都封装到一个独立的区域

>23 constructor super关键字干什么用?
​ constructor 是类中用来挂载实例属性的构造器函数 new一个类的时候会自动调用构造器函数
​ 如果希望继承父类的成员 可以使用super关键字 在构造器函数
super作为一个函数使用 super必须写在构造器的第一行(必须写在this前面) 在方法中super可以作为对象来使用 可以代表父类

posted @ 2021-11-23 16:16  FlatWhite  阅读(40)  评论(0)    收藏  举报