1、描述一下JavaScript中的数据类型?(就是基本类型和引用类型,有些面试人员基本类型会叫做值类型)
答:基本类型有String、Number、Boolean、Null、Undefined。剩下的都是引用类型,Array、Object、Date,Function等。
追问: 怎么判断基本类型和引用类型?
答: 只有单一的一个值,只存放在栈中。比如说字符串、数字、布尔这几个就是一个单一的值,他们就是基本类型。剩下的就是引用类型,引用类型就是对象。Function、Object、Array、Date等在js里都属性对象。引用类型是同时存储在堆栈中,我们访问的是栈上的变量标识符(变量名字)和指向该类型指向堆中的内存地址。
2、javascript中prototype是什么,描述一下js中的原型链?(大部分公司会问)
答:在js中函数也属于对象,每个函数都有一个子对象prototype, prototype就是该函数的原型,包含一个类的所有成员。在js里类是以函数的形式呈现( js使用function来声明一个类,使用new创造一个实例(Object),新的es6提供了一个语法糖class来声明一个类,相对去function来说结构更清晰 )。
通过new的过程,类(function)中的所有成员都会实例成Object中的属性。Object的属性__proto__和function的属性prototype都指向了同一个对象(原型对象)。原型既然是对象,那也必须通过某一个类(function)来实现(实例),这个地方就是继承的关键,一般来讲外我们不设计继承的话他默认继承Object,这个就是js的顶层对象,如果你要在这里继承于某个对象,比如说son类(function)继承于father(Object),那就可以通过prototype实现继承。然后father是默认继承Object, Object作为一个对象,那他就有构造函数(他自己的类 function)。Objecet由Object()的函数实例过来,所以我们在在创建对象的时候可以写成 new Object();Object上面是null,空对象指针。所有的函数都会继承于一个顶层函数Function()。这样son到father到Object到null,下面的对象都能访问到上层对象属性,而对象又是类(function)的实例。所有的function继承于顶层函数Function(), 所以函数会默认由3个方法bind,apply,call 3个方法 这就是继承自顶层函数Function()。不然函数后面怎么能使用点号来访问一个方法。let son = function ( ) { }.bind(father); 这个bind()就是继承Function()用于改变指针。(这个内容或多或少会问到,我写的有点乱,知识点有点抽象,大家可以搜集一些文章来看,建议看比较有权威的书本里面的讲解)
3、js里面的this指针是什么?
答: js的this关键字是调用函数的对象,也叫函数运行是的上下文。运行在script里面就是window、global。作为对象的一个属性运行指向改对象。严格模式下this没有被执行环境定义,所以值会是一个undefined(严格模式下才会出现)。
Ps: 某些文档上会说明两个地方的this指针,第一个是闭包的this指针,第二个是被当作变量名赋值给另外一个变量的函数的指针。就这两个情况的指针会给人迷惑性。但是万变不离其宗,所有的指针都是通过上下文来进行判断,有些文章里讲到某个对象下一个函数当作参数赋值给另外一个变量,这个指针就变成的window,说这是javascript的一个缺陷,我个人认为这并不是一个缺陷,而是变量赋值的时候原有函数的指针丢失,改变成了新函数执行的上下文,新函数正好是在window对象上运行。
4、apply, call, bind 有什么区别?手动实现一个bind()? (实现bind有些公司会问,但是不多)
答:3个函数都是Function原型链上的函数,用于改变函数执行时候的上下文,也就是this指针。apply 和call 的区别只在于 第二个参数的格式,前者是数组,后者把数组里面的值一个个列出来用逗号隔开。bind()会创建一个新的函数方便后面调用(return function() { } )。apply和call立即执行。
原理:在调用call()和apply()函数的时候我们能获取到2个内容,一个是调用这个方法的函数,另外一个是需要绑定的对象。基本的思路是在call()或者apply() 函数里去改变执行时候的上下文,从调用的函数转向绑定的对象来实现指针的变化。call和apply的区别仅仅只是在处理arguments(函数运行时的实参列表)有区别。bind()方法和上面的两个方法基本原理一致,call和apply方法立即执行。bind()方法内部返回一个函数,使用es6的箭头函数来返回比较简单,箭头函数的this指针不会跟随执行上下文来变化。
5、js实现继承的方法有哪些?
答:
1.原型继承:原型继承的基本方法是重写子类的prototype,子类 prototype的值改变为父类的实例来实现继承。需要变换原型内的构造函数。这种继承方式不能向父类传递参数,而且在使用引用类型值会被所有实例所共享。(所有被new出来的对象在对属性进行操作时都会对这个值进行修改,后面的实例在次使用属性时使用的是被修改的值,这个问题有一部分源于引用类型内存地址的问题)
2.经典继承:经典继承的使用方法为在子类函数里面调用父函数的call方法。原理 是在子函数里调用父函数,因为函数的this指针指向的是函数运行时候的上下文, 这里使用call函数让正在执行的父函数的this指向子函数来实现父函数内部属性的继承(作用域的改变)。此继承的方式无法继承父函数原型上的内容。(残废的继承方法,如果父类原型上有方法就没法继承到原型上的方法)
3.组合继承:前2中继承方式的结合。原型属性使用原型的方式来进行继承。通过经典继承使得父类的属性继承到子类的属性里,来解决引用类型的属性被所有实例共享的问题。(最常见的没有基本没有缺陷的继承)
4.寄生组合式继承:这种继承的方式其实式对组合继承的一种优化,性能优化,原理和组合继承无差别。组合继承子类在设置原型的时候会实例一次父类。在子类的内部为了继承使用call又调用了一次父类函数。所以组合继承中调用了2次父类函数。组合继承过程相当于在一个函数里面对父类原型设置为一个空函数的原型,在把子类的原型替换成该原型。
5.es6 的class来实现继承: 使用class来实现继承式最好的一种方式。class的语言更像其它语言中的类。继承方式语法上更像基于类的继承。但是底层仍然基于原型的继承。
ps: 现在写类以及类的继承都是使用class来写,这种语法更方便维护。面试时候会问到上面的4中继承方式,一般只需要记住前三种继承的原理就可以了。而且3中继承核心概念只有2个,变换作用域,变换原型。(可能早期js设计就没有想到过在语法里优化继承这个内容,没有语法糖只能用最老的原型继承写法来写。现在用class开发的话好很多了。不过项目中一般也不涉及不到继承,除非是写公司的整体框架。Class继承语法除了在react中比较突出之外其它框架基本不怎么用继承)
6、事件循环机制 ?(js中一个非常核心的内容,面试题也可以问做阻塞、非阻塞、消息队列、任务队列、宏任务、微任务等。这些内容都属于事件循环机制下的内容)
答: 在js里我们创建一些变量对象或者函数的时候我们先是在堆里开辟一些内容空间用于存储变量。当调用函数时形成一个栈帧存放在栈内,根据作用域遵循堆栈中的先进后出、后就先出的原则,执行完成弹出栈,直到栈内为空(这里需要使用到堆栈的概念)。
事件循环机制:javascript中有2个重要内容。一个是js执行主线程,另外一个是调用栈。 js引擎为单线程,执行函数会一个一个放在调用栈中等待主线程来执行,如果碰到阻塞,如异步函数settimeout或ajax等会把事件的回调函数放到任务队列(也就是消息队列)中等待主线程空闲的时候执行,线程会继续执行主线程上上的方法,主线程遵循先进后出的执行顺序(最先放入栈中的是父函数,然后继续执行父函数内的子函数,子方法,子函数执行完成后垃圾回收机制弹出栈内,直至函数内所有子方法全部执行完毕,此时弹出父函数,调用栈内为空)。调用栈内空置,开始事件循环,检测任务队列是否有函数,有的话放入栈中执行,但是任务队列此时的执行顺序为先进先出,其实就是哪一个函数写在前面先执行哪一个。执行完成后此时调用栈和消息队列内已没有内容,代码执行完毕。
这里有一个特别的地方,异步函数都会被推到任务队列(消息队列)内执行,但是任务队列里的任务分为两种,一种是宏任务,一种是微任务。宏任务有setTimeout、 UI事件(点击、触摸等事件的回调)、setInterval、requestAnimationFrame(页面重绘),微任务浏览器常用的就一个Promise,其它的不会考。微任务和宏任务都属于任务队列里的内容,区别在于微任务优先于宏任务执行。事件循环机制就是这些内容,考点会从里面抽取,有些公司也会考代码,但是只要知道事件循环机制根本不是什么事。
7、闭包是什么,闭包的优缺点,闭包里面的this指针指向哪里?
答: 闭包就是定义在函数内部的子函数。他可以在外部访问函数内部的变量。 闭包的优点就是外部能访问函数内部的变量,缺点是变量会一直存储在内存里。闭包的this指向window或者是global。
追问:为什么闭包的this指向的是window?
答: 闭包的结构为父函数里嵌套子函数,要调用子函数父函数必须把子函数return出来。上面说到过this指向函数执行时候的上下文,父函数执行时被可能会被某个对象调用指向该对象,但是父函数执行完成之后返回的子函数就不被任何对象调用,相当于执行在window上,所以闭包的this指向的是window。
8、数组和对象上的方法有哪些?(考点在于对数据的处理能力,虽然不同公司问法可能有些差别,但是思路是一样的。有些公司可能会给一些数据然后把数据处理成想要的内容)
答: 常用的数组方法有: join(数组转字符)、push(添加元素),pop(删除末尾元素并返回),sort(数组排序),reverse(反转数组), concat(链接数组),includs(查找数组是含有某一个,返回true), find(查找是否函数元素,返回元素), findIndex(查找是否含有元素,返回下标,没有返回-1), filter(过滤数组,返回新的数组),slice(切割数组),splice(删除数组)
常用的对象方法: assign(对象合并),create(创建对象),keys(返回键数组),hasOwnProperty(判断是否含有指定的属性)。其它的有很多,但是不常见。
9、说一下深拷贝和浅拷贝?(这个问题会经常被问,也是一个小核心内容)
答:浅拷贝和深拷贝只在引用类型上由区别,基本类型没差别。潜拷贝就是简单的赋值,在引用类型上变量的简单赋值变换只是变量标识符,比如说let a = [1,2,3]; let b = a; 这种浅拷贝只是变换了变量的名称,他们的内存地址(引用地址,在堆里面的地址)还是一样的。如果改变b,b.push(4),则a也会被改变。深拷贝就是在内存里开辟一个新的内存地址用来存储新变量,相对于潜拷贝他不仅仅是简单的赋值,他还在堆里创建了新的内存地址,改变b就不会影响到a。常用的深拷贝方法, 我这边是转成JSON在转过来。Let b = JSON.parse(JSON.stringify(a))。
10、说说几种js中的设计模式?
答: 工厂模式、原型模式、单例模式、订阅发布模式、状态模式。 工厂模式、单例模式和观察者模式是最常见的。其它的没有什么必要去了解。下面可能会问模式的一些特性。
11、简述一下ajax的内容?(笔试题里比较常见,可以从 什么是ajax、基本原理、优缺点去描述ajax)
答:
什么是ajax:ajax是一种创建交互式网页应用的网页开发技术。(新的交互式网页开发技术)。
基本原理:ajax基于ajax引擎“XMLHttpRequest”对象来向服务器发送数据并对数据响应。使用new XMLHttpRequest()对象下的方法向服务器发送请求和接收数据。使用js来操作dom实现页面的刷新,对请求错误以及其它一些情况进行处理。(IE浏览器的ajax引擎对象为ActiveXObject(“Microsoft.XMLHttp”), 和其它浏览器有一些差别,如果写ajax第一次封装插件的话需要对这个进行判断。IE戏就是多)。
优点:
1. 在不刷新页面的情况下更新数据。早期的数据交互是通过配置form 表单的 action,method,submit后提交form表单来完成,form表单是浏览器带的功能,在提交返回后页面会进行一次页面刷新。而ajax是使用ajax引擎来完成数据获取,使用js对dom进行操作。不会刷新页面。
2.异步数据传输。 ajax使用异步方式与服务器进行通信。Js是单线程。使用异步方式能降低页面白屏时间,减少用户等待时间,防止页面卡死在请求期间而无法加载后续内容,增强用户体验。
3.降低前端和后端的负担。 使用form表单需要提交大量的内容,后端还需要对内容进行解析,使用ajax只需要关注传输的数据即可。后端根据请求头返回值,前端使用js对dom进行操作。(最主要的就是这3个点,不刷新页面跟新数据,异步传输, 降低前后端负担。)
12、描述一下es6、es7的新特性?(说常用特性即可)
答:新的变量声明方式let const ; 解构赋值; 箭头函数;新异步函数Promise;async
await ,新数据结构Set, Map。新的类声明方式class。遍历方式map, forEach, for...of 。 以及一些常用的数组对象方法includes、filter等
追问:新特性解决哪些问题?
答:1. let const: 解决var声明变量没有块级作用域的问题,let 和const都不能重复声明,const 值不能被修改。
2.箭头函数:函数的this指针是其运行时的上下文,箭头函数的指针在函数定义时候所在的对象,而不是运行时候的对象,减少了赋值指针的操作。箭头函数的书写更简洁。
3. Promise、async、await 新的异步函数。(这个内容使用面广,也是es新特性中比较重要的一个内容,大部分公司或多或少都会问到这个问题,下面会单独提出来问)
4.新数据结构Set, Map: Set数据结构和数组上基本一模一样,优点在于Set数据里面不存在重复的值,可以使用new Set()对数组进行查重。排除重复的值或者做一些其它的事情。Map:在老的数据类型中,对象的属性名称只能是一个字符串,(字符串--值)的结构,而Map(Map也是键值对的数据结构)里属性名可以变成值(值--值的结构)是一个更完善的Hash结构。
13、promise、 await async 、setTimeout 的区别?(重点)
答: 4个函数都为异步函数,setTimeout属于事件循环机制中的宏任务,优先级低于Promise, await
async , Promise 为新的es异步函数,await
async 是作为对promise的一部分。 async 会返回一个promise对象,await 触发async返回promise,等待返回,在这里此函数的进程中断,继续执行函数外的其它函数,等待事件循环机制完成await 触发的promise后继续执行await后面的代码。(关联事件循环机制)
Ps:这个考题都会考,有些可能不会问await async;但是promise是肯定会考的,promise的应用面非常的广。
14、浏览器有哪些数据存储方法?区别在哪?
答: cookie,sessionStorage,localStorage.(浏览器下的storage对象)
Cookie: 早期的前端开发中大量使用的一种存储技术。在比较早的网站里服务器发送到客服端的数据的响应头里可以设置存储一些值到客户端的cookie里方便客户端和服务器联系。如登录等信息。在下一次客户端对改服务器发送请求的时候都会将cookie发送到服务器用于验证用户信息(登录状态等)。Cookie也可以用来存储其它一些客户端的内容优化客户端的体验。Cookie可以自定义设置值、域、过期时间等。大小为4M内。
sessionStorage: 继承于Storage的存储,页面关闭消失。存储大小为5M左右,不同浏览器存储大小有差别。
LocalStorage: 同样继承与Storage,页面关闭不会消失。永久存储,除非手动清除或使用clear方法清除。谷歌最大5M左右,不同浏览器存储大小有差别。
15、前端的优化过程?
答: 优化方法有很多,减少http请求,压缩css html js 文件(gulp等构建工具就有压缩功能),压缩image图片,使用icon, 减少重绘,减少dom节点,预加载、按需加载、雪碧图等很多方法。
16、跨域有几种? 怎么解决跨域问题?原理?
答: 浏览器对js的同源策略限制,不同域之间不能相互访问,所以出现了跨域问题。同域为相同端口、协议、域名。Jquery中的话是使用Jsonp。(使用jquery多的话就会问你jsonp的问题,使用vue多就会问代理的问题,vue的proxyType是将请求发送给自己的服务器,在由服务器转向后台服务器,实现浏览器跨域,和jsonp有区别)
Jsonp的基本原理:jsonp是一种为了处理跨域问题的一种方案,像ajax,但是他并不是ajax。ajax获取不到存在跨域问题的文件的,因为受到同源策略的影响,但是页面上的使用script标签引入文件是不受影响,比如说<script src=“www.aaa.cn/page/index.js”> 这种情况是能访问到这个js文件。不仅是js文件,带有src的标签都不会受到同源策略的影响。那jsonp就可以理解为你在页面添加了一个script标签,服务器为我们生成js文件,script标签指向这个js文件地址,callback为js文件里面存放数据的函数名字,服务器动态生成js,script标签去取js文件里的callback 函数名字内的参数。所以jsonp和ajax的不同就在于ajax是new XMLHttpRequest() 来获取文件,jsonp使用script标签来引入存储了数据的js文件来解决跨域问题。在Jquery中看起来都是在使用数据请求,但是jsonp和ajax是2个不用的东西。(缺点:jsonp只能get,post跨域的话需要后端配合,指定域名或者所有域名都能访问)
17、有没有使用过css 预处理语言?有哪些?介绍一下基本特性和优点?
答: css 预处理有sass,less,sylus 三种预处理语言的都有一些共同特性,支持声明css变量,css常量,css函数,混淆、嵌套、引入(@import)等功能。特性和优点:既然支持常量变量和函数,那在原来需要使用js来改变css的场景就不需要大量使用js,样式列表里已经支持加减乘除等其它运算。可以定义全局css块变量,全局字体样式变量。比如主题颜色的切换。大部分内容的标题、内容样式的统一修改。css的嵌套让css代码更简洁更具有层级性更方便维护。
18、前端模块化的发展历程?
答:CommonJs 、AMD 、CMD、 ES6Module
(script type=“module”);
会问一些前端模块化问题,js模块防止数据污染,不依赖闭包封装。组件模块就是什么样情况会设计成组件,答高复用,低耦合就可以了。
19、有没有了解过npm、bower、gulp、webpack 等前端架构工具?
20、说一下http协议?(关于http的一些内容)
ps: 也就是请求协议、请求体、响应内容等进行阐述。
21、页面的整体加载过程 ?
22、其它就是一些框架上的问题,这一个部分会大量的问及,大部分问的内容是经验上的问题,如有没有使用过JQuery写过扩展、封装一个长按事件等?
23、jq的链式调用的原理?
24、浏览器的兼容性?
CSS
Css内的内容我就直接放问题啦,这里的内容都是老生常谈的内容了。
1、Css 盒子模型 ;
2、定位有哪些,特点;
3、实现一个垂直居中;(定位, css3 transform , 弹性等)
4、Px 、rem、em 特点;
5、一些不常见的属性如vertical-align基线等问题;
6、IE和W3C标准下的box-sizing 的差别 ;
7、@import 特点 ;
8、清除浮动的方式;
9、Css伪类的内容;
10、Css3 的一些内容,过渡动画等;
其它的就是一些待遇规划等。规划最好以3年以内来进行阐述,这样比较容易思考而且符合实际,可以提一些以后的内容,面试官的面试印象也很重要,反正别紧张、自信就可以。