前端面试的热门问题之 JavaScript

一、说一下闭包

一句话可以概括:闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。

二、继承

原型链继承

  • 特点:基于原型链,既是父类的实例,也是子类的实例
  • 缺点:无法实现多继承

构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

  • 特点:可以实现多继承
  • 缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。

实例继承:为父类实例添加新特性,作为子类实例返回

拷贝继承:拷贝父类元素上的属性和方法

组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

  • 特点:可以继承实例属性/方法,也可以继承原型属性/方法
  • 缺点:调用了两次父类构造函数,生成了两份实例

寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性。

三、如何解决异步回调地狱

promise、generator、async/await

四、如何让事件先冒泡后捕获

在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获之间。

五、说一下事件委托

事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。

好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。

六、说一下图片的懒加载和预加载

预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。

懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。

七、mouseover和mouseenter的区别

mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是mouseout

mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave

八、js的new操作符做了哪些事情

new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。

九、改变函数内部this指针的指向函数(bind,apply,call的区别)

通过apply和call改变函数的this指向,他们两个函数的第一个参数都是一样的表示要改变指向的那个对象,第二个参数,apply是数组,而call则是arg1,arg2…这种形式。通过bind改变this作用域会返回一个新的函数,这个函数不会马上执行。

十、异步加载js的方法

defer:只支持IE如果您的脚本不会改变文档的内容,可将 defer 属性加入到script标签中,以便加快处理文档的速度。因为浏览器知道它将能够安全地读取文档的剩余部分而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。

async,HTML5属性仅适用于外部脚本,并且如果在IE中,同时存在defer和async,那么defer的优先级比较高,脚本将在页面完成时执行。

十一、JS中的垃圾回收机制

由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。

十二、eval是做什么的

它的功能是将对应的字符串解析成js并执行,应该避免使用js,因为非常消耗性能(2次,一次解析成js,一次执行)

十三、如何理解前端模块化

前端模块化就是复杂的文件编程一个一个独立的模块,比如js文件等等,分成独立的模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题,所以有了commonJS规范,AMD,CMD规范等等,以及用于js打包(编译等处理)的工具webpack。

十四、说一下Commonjs、AMD和CMD

一个模块是能实现特定功能的文件,有了模块就可以方便的使用别人的代码,想要什么功能就能加载什么模块。

Commonjs:开始于服务器端的模块化,同步定义的模块化,每个模块都是一个单独的作用域,模块输出,modules.exports,模块加载require()引入模块。

AMD:中文名异步模块定义的意思。

十五、实现一个两列等高布局,讲讲思路

为了实现两列等高,可以给每列加上 padding-bottom:9999px;margin-bottom:-9999px;
同时父元素设置overflow:hidden;

十六、js判断类型

判断方法:typeof(),instanceof,Object.prototype.toString.call()等

十七、数组常用方法

push(),pop(),shift(),unshift(),splice(),sort(),reverse(),map()等

十八、数组去重

  • indexOf循环去重
  • ES6 Set去重;Array.from(new Set(array))
  • Object 键值对去重;把数组的值存成 Object 的 key 值,比如 Object[value1] =
    true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。

十九、性能优化

减少HTTP请求、使用内容发布网络(CDN)、添加本地缓存、压缩资源文件、避免使用CSS表达式、减少DNS查询、使用外部javascript和CSS、避免重定向、图片懒加载

二十、Js基本数据类型

undefined、null、number、boolean、string、symbol

二十一、跨域的原理

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制,那么只要协议、域名、端口有任何一个不同,都被当作是不同的域。跨域原理,即是通过各种方式,避开浏览器的安全限制。

二十二、webpack用来干什么的

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。

二十三、vue的生命周期

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

二十四、简单介绍一下symbol

Symbol是ES6 的新增属性,代表用给定名称作为唯一标识,这种类型的值可以这样创建,let id=symbol(“id”)

二十五、介绍一下promise,及其底层如何实现

Promise是一个对象,保存着未来将要结束的事件,有两个特征:

  • 对象的状态不受外部影响,Promise对象代表一个异步操作,有三种状态,pending进行中,fulfilled已成功,rejected已失败,只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也就是promise名字的由来。

  • 一旦状态改变,就不会再变,promise对象状态改变只有两种可能,从pending改到fulfilled或者从pending改到rejected,只要这两种情况发生,状态就凝固了,不会再改变,这个时候就称为定型resolved。

二十六、js字符串转数字的方法

通过函数parseInt(),可解析一个字符串,并返回一个整数,语法为parseInt(string ,radix)

  • string:被解析的字符串
  • radix:表示要解析的数字的基数,默认是十进制,如果radix<2或>36,则返回NaN

二十七、let const var的区别

提起这三个最明显的区别是var声明的变量是全局或者整个函数块的,而let,const声明的变量是块级的变量,var声明的变量存在变量提升,let,const不存在,let声明的变量允许重新赋值,const不允许。

二十八、ES6箭头函数的特性

箭头函数与普通函数的区别在于:

  • 箭头函数没有this,所以需要通过查找作用域链来确定this的值,这就意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this
  • 箭头函数没有自己的arguments对象,但是可以访问外围函数的arguments对象
  • 不能通过new关键字调用,同样也没有new.target值和原型

二十九、简单讲一讲ES6的一些新特性

  • 块级作用域:ES5只有全局作用域和函数作用域,块级作用域的好处是不再需要立即执行的函数表达式,循环体中的闭包不再有问题。
  • rest参数:用于获取函数的多余参数,这样就不需要使用arguments对象了。
  • promise:一种异步编程的解决方案,比传统的解决方案回调函数和事件更合理强大
    模块化:其模块功能主要有两个命令构成,export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

三十、call和apply是用来做什么?

Call和apply的作用是一模一样的,只是传参的形式有区别而已

1、改变this的指向

2、借用别的对象的方法,

3、调用函数,因为apply,call方法会使函数立即执行

三十一、知道private和public吗

public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用

private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用

三十二、async和await具体该怎么用?

(async () = > {
await new promise();
})()
原创文章 22 获赞 4 访问量 778

猜你喜欢

转载自blog.csdn.net/weixin_42224055/article/details/105775873