前端面试JS ES6篇(持续更新 2021 4 18)


今天也有很努力的在赚猫粮钱

如若文章存在错误或不足,望理解并帮我指出,感激不尽


数据类型,存储方式

其中原始类型又分为七种类型,分别为:

boolean
number
string
undefined
null
symbol
bigint

对象类型分为两种,分别为:

Object
Function

原始类型存储在栈上,对象类型存储在堆上,但是它的引用地址还是存在栈上

var let const

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

var:

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。变量可以重复定义。(现在在开发中已经很少会使用)。

let:

变量需要声明后才可以使用,声明的变量存在块级作用域。

let不允许在相同作用域内,重复声明同一个变量。

const:

const 声明之后必须马上赋值,否则会报错。

const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。


let、const使用场景:

let使用场景:变量,用以替代var。

const使用场景:常量、声明匿名函数、箭头函数的时候。

作用域

  • 全局作用域

  • 函数作用域

  • 块级作用域

ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

第一种场景,内层变量可能会覆盖外层变量。

第二种场景,用来计数的循环变量泄露为全局变量。

注意ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

作用域链

在javascript的学习中,执行环境、作用域是2个非常非常重要和基本的概念。

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象 (variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器会处理数据时会在后台使用它。

在代码在一个环境执行时,会创建变量对象的一个 作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。整个作用域链是由不同执行位置上的变量对象(Variable Object)按照规则所构建一个链表。

作用域链的前端,始终都是当前执行的代码所在环境的变量对象。下一个变量对象来自包含(外部)环境,而下一个变量对象则来自下一个包含对象。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链的最后一个对象。

原型 原型链

原型

每个实例对象都有一个 constructor 属性,指向它的构造函数。

每个函数对象(包括构造函数) 都有一个 prototype 属性,指向函数的原型对象。这个原型对象的 constructor 属性,指向函数本身。

每个对象都有一个 [[prototype]] 私有属性,指向它的构造函数的原型对象,但这个属性是不允许访问的。某些浏览器(例如 Chrome)提供 __proto__ 属性用于访问 [[prototype]] 私有属性

构造函数的 constructor 属性都是指向 Function__proto__ 属性都是指向 Function.prototype。因为构造函数都是通过 new Function 来创建的,它们都是 Function 的实例对象,包括 FunctionObject

Object 外,其它构造函数的 prototype 属性的 __proto__ 属性都是指向 Object.prototype。 而 Objectprototype 属性的 __proto__ 属性指向 null

image.png

原型链

所有对象都有 __proto__ 属性,并且这个 __proto__ 属性指向一个原型对象。
因为原型对象也是对象,这个原型对象也有 __proto__ 属性,我们把这种关系称为原型链

当需要访问一个对象的属性时,首先从该对象开始查找,如果能够找到,那么到此返回。

如果没有找到,就在该对象的 __proto__ 属性指向的原型对象中继续查找,如果能够找到,那么到此返回。
如果没有找到,那么一直往上查找原型对象,直至 __proto__ 属性指向 null,也就是原型链的顶端

若原型链上的所有原型对象都没有该属性,则返回 undefined。

解决跨域问题 & 同源

明白跨域问题前,先了解一下同源策略,什么是同源,同源就是协议,域名,端口全都需要相同,有任何一项不同就会引起跨域问题:

  • Cookie、LocalStorage和IndexDB无法读取

  • DOM无法获取

  • AJAX请求不能发送

前端解决跨域的方式有很多,我常用如下1、2条:

  • nginx反向代理

     反向代理的优点:
      1. 保护网络安全,所有请求都先经过代理服务器。
      2. 负载均衡,把请求转发到压力较小的服务器。(内置策略,扩展策略可以了解一下)
      3. 可以做一些中间层设置,比如缓存静态资源。
    复制代码
  • config 中配置 proxyTable 中 changeOrigin : true

  • jsonp (只支持GET请求)

  • CORS

  • postMessage

  • node

  • webSocket

  • iframe

call apply bind

call()、apply()、bind()是Function.prototype上的方法,所有函数都可以调用,它们的第一个参数都是this的指向对象。

call方法可以将调用函数执行,并将this 指向第一个参数,后续其他参数将会全部传递给调用函数使用。

all()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

在非严格模式下,如果call()和apply()的第一个参数是null或者undefined,那么this的指向就是window全局变量。

bind返回的是方法。

总结:

call()、apply()和bind()都是可以用来改变this指向,可借助它们实现继承;

call()与apply()区别在于参数不一样,如果想一目了然表达形参和实参的对应关系,用call()比较合适;

bind()是返回一个新函数,可供以后调用,而apply()和call()是立即调用,并返回结果

箭头函数的特点

  • 用 => 代替 function,语法简单

  • 不绑定 this,箭头函数体内的 this 永远指向的是定义时所在的对象。 (建有函数中不会创建自己的this,而是从自己的作用域的上一层继承)

  • 不支持call apply bind

  • 不绑定arguments (普通函数通过arguments获取传入的参数值)

  • 支持嵌套

  • 不能使用箭头函数作为构造函数,没有prototype属性

JS常用内置对象和方法

javascript事件循环 / event Loop / JS执行机制

讲解事件循环前先提一下单线程和多线程

• 单线程:单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。

• 多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

浏览器组成原理

HTTP HTTPS HTTP2

ajax axios

javascript回收机制

垃圾回收有两种实现方式,分别是标记清除引用计数

标记清除:当变量进入执行环境时标记为“进入环境”,当变量离开执行环境时则标记为“离开环境”,被标记为“进入环境”的变量是不能被回收的,因为它们正在被使用,而标记为“离开环境”的变量则可以被回收

引用计数:统计引用类型变量声明后被引用的次数,当次数为 0 时,该变量将被回收。

内存泄漏

内存泄露就是不再被需要的内存, 由于某种原因, 无法被释放。

造成内存泄漏的方式:

  • 全局变量造成内存泄露

  • 未销毁的定时器和回调函数造成内存泄露

  • 闭包造成内存泄露

  • DOM引用造成内存泄露

判断数组的方法

数组去重

es6新特性

继承

类型转换事件冒泡

setInterval 和 setTimeout

forEach map filter

闭包

捕获过程 事件冒泡

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享