2020前端面试总结(持续更新)

目录

1: 常见的数据类型 以及 基本(原始)数据类型和引用数据类型的区别

2:  闭包的优缺点

3:解释一下原型和原型链

4: 优化前端性能的方法

5: 解释一下axios 和 await

6: promise有几个状态 分别是什么

7: promise 是异步还是同步

8: new 一个构造函数的时候都做了什么

9: display: none 和 class="hidden" 的区别 

10:标准的盒子模型

11:伪类选择器什么时候会用到 ,为什么要用伪类选择器

12: 如何解决跨域问题 ,为什么会有跨域的问题

13: ajax工作原理

14: sessionId详解

15: 构造函数

16:长连接和短连接

17:Cookie、sessionStorage、localStorage的区别


1: 常见的数据类型 以及 基本(原始)数据类型和引用数据类型的区别

首先解释一下栈(stack) 和 堆(heap)

heap:是由malloc之类函数分配的空间所在地。地址是由低向高增长的。 动态分配的内存,大小也不一定会自动释放

stack:是自动分配变量,以及函数调用的时候所使用的一些空间。地址是由高向低减少的。为自动分配的内存空间,它由系统自动释放    

基本(原始)数据类型:String, Null,Undefined,Number,Boole

引用数据类型:Object

区别:基础数据类型是值引用, 地址数据类型是地址引用

原始类型(基本类型)(存放在栈中):按值访问,可以操作保存在变量中实际的值。原始类型汇总中null和undefined比较特殊

  引用类型(存放在堆内存中的对象,每个空间大小不一样,要根据情况进行特定的配置):按地址访问,在操作对象时,实际上是在操作对象的引用而不是实际的对象。

扩展:引用类型是存放在堆内存中的对象,变量其实是保存的在栈内存中的一个指针(保存的是堆内存中的引用地址),这个指针指向堆内存。引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个                               引用地址可以快速查找到保存中堆内存中的对象

总结基本数据类型和引用数据类型区别

1、声明变量时内存分配不同

*原始类型:在栈中,因为占据空间是固定的,可以将他们存在较小的内存中-栈中,这样便于迅速查询变量的值
     *引用类型:存在堆中,栈中存储的变量,只是用来查找堆中的引用地址。
      这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响

2、不同的内存分配带来不同的访问机制

在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。
        而原始类型的值则是可以直接访问到的。

3、复制变量时的不同、

1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
        2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)。多了一个指针

4、参数传递的不同(把实参复制给形参的过程)

首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。
     但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。  
     1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
     2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心!因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。

2:  闭包的优缺点

(闭包是将函数内部和函数外部连接起来的桥梁。  说白了就是一个环境,能够读取其他函数内部的变量。)

优点:一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

缺点:
        1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
        2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

3:解释一下原型和原型链

原型:其实原型就只是个普通对象,里面存放着所有实例对象需要共享的属性和方法!所以,我们把需要共享的放到原型对象里,把那些不需要共享的属性和方法存在在构造函数里! 

function Person(name,age){
     this.name = name;
}
Person.prototype.sex = 'female';

var person1 = new Person("Summer");
var person2 = new Person("Lily");
        
console.log(person1.sex)      // female
console.log(person2.sex)      // female

Person.prototype.sex = 'male';

console.log(person1.sex)      // male
console.log(person2.sex)      // male

修改prototype属性会影响它的所有实例的sex的值!!

实例对象的属性和方法一般分为两种:一种是自身的,一种是引用自prototype的。 

原型链: 是由子对象对父对象进行多次原型继承形成的链式关系。当调用子对象的某个属性或方法时,javascript会向上遍历原型链,直到找到为止,没有返回undefined。但是注意: 属性在查找的时候是先查找自身的属性,如果没有再查找原型,再没有,再往上走,一直插到Object的原型上。

    1: prototype是函数的原型对象,即prototype是一个对象,它会被对应的__proto__引用。
    2: 要知道自己的__proto__引用了哪个prototype,只需要看看是哪个构造函数构造了你,那你的__proto__就是那个构造函数的prototype。
    3: 所有的构造函数的原型链最后都会引用Object构造函数的原型,即可以理解Object构造函数的原型是所有原型链的最底层,即Object.prototype.__proto===null

事实上,js里完全依靠"原型链"(prototype chain)模式来实现继承。

  • proto:事实上就是原型链指针!!

  • prototype:上面说到这个是指向原型对象的

  • constructor:每一个原型对象都包含一个指向构造函数的指针,就是constructor

    下面来详解原型与原型链

对象有__proto__属性,函数有prototype属性;
    对象由函数生成;
    生成对象时,对象的__proto__属性指向函数的prototype属性。
    在没有手动修改__proto__属性的指向时,以上三条便是JavaScript默认原型链指向逻辑

var obj = {};
console.log(obj.prototype); //undefined
console.log(obj.__proto__); //Object {}
var obj2 = function(){}
console.log(obj2.prototype); //obj2 {}
console.log(obj2.__proto__); //function() {}

 

  •  
  • 大致总结一下就是:

    1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }

    2、Function是作为众多function出来的函数的基类 function Function(){ [ native code ] }

    3、构造函数的proto(包括Function.prototype和Object.prototype)都指向Function.prototype

    4、原型对象的proto都指向Object.prototype

    5、Object.prototype.proto指向null

4: 优化前端性能的方法

1: 压缩图片

压缩图片的方法:

a、雪碧图
          即css sprites, 就是把很多小图片制作成一个大图,然后作为背景图片使用,定位即可。
          优点: 很明显: 减少了大量的http请求。
          缺点: 背景定位较为麻烦,其实不算缺点。

b、图片压缩
          图片压缩是很简单的,就是无损压缩了。优先使用png而不是GIF,压缩png,去掉jpg的metadata,压缩gif动画,尝试使用  png8,避免使用AlphaImageLoader,压缩动态生成的图像,使 favicon 更小,可缓存、使用css sprites 

c、base64
            base64编码的大小比原图大小更大一些,但是可以减少http请求。
        d、响应式图片
            一般我们对于图片的设定方法都是设置图片为width: 100%, 但是如果加载的图片的实际尺寸很大,而我们所需要的很小,那么不可避免的就会造成浪费, 所以这时就可以使用响应式图片。 主要用到的属性就是 srcset 和 sizes 属性。 

e、延迟加载
            假设我的网页很长很长,图片很多很多(比如多图慎点那种),但是我可能看了一下就没兴趣了,那是不是完全没有必要加载后面的图片了,这个时候就要有一个延迟加载的思想。
            图片延迟加载也称懒加载,通常应用于图片比较多的网页,如果一个页面图片比较多,且页面高度或宽度有好几屏,页面初次加载时,只显示可视区域的图片(非可视区域图片使用1*1的图片占位,图片大小css控制),当页面滚动的时候,图片进入了可视区域再进行加载(修改src),这样可以显著的提高页面的加载速度,更少的图片并发请求数也可以减轻服务器的压力。如果用户仅仅在首屏停留,还可以节省流量。具体的实现方法可以看一个插件,就叫lazeload。

f、 图标字体
            用过bootstrap的同学肯定对方便的fontawesome图标字体印象深刻,可以无损放大缩小,可以修改颜色,只要加个类名就可以使用图标,感觉是不是很爽🌚。优势呢。。。矢量&方便好用,不过图标没有一定的量可能不大需要,而且矢量图可能美工压力也比较大,我们只要知道怎么用就行啦,有的时候用现成的图标减轻一下美工同学的工作量也是极好的。可以看一下一个专门用来做图标字体的网站。

h、 SVG
            svg作为矢量图,和iconfont对比起来优势可能就是字体可能在样式修改方面受限较多,其次字体文件一般都弄的挺大的,然后兼容性差点。svg也可以认为就是图片,使用方法也很简单。

2: 减少http请求
        CSS Sprites:还可通过css中的background-position来定位图片中的某一具体部分,它比图片地图更灵活,建议大家使用。
        内联图片:通过使用data:URL数据形式可以替代http请求,甚至可以用于script和a标签中,其缺陷是Base64编码会增加图片的大小,并且嵌在网页中,会加大网页的数据量,但它可以减少http网络请求耗时。这里提供图片生成dataurl数据的方法。
        

var can = document.createElement("canvas");
    var ctx = can.getContext("2d");
    img.onload = function(){  
         ctx.drawImage(this, 0, 0, width, height);
         can.toDataURL();
 }

3: 合并脚步和样式表

4:配置多个域名和CDN加速
        通常浏览器对于一个域名的并发请求是有限的,比如:有100个文件要加载,但浏览器一次只可能并发请求10个文件,这样并发多次就会耗时。
        因此配置多个域名能够最大限度的增加并发请求量,但这里有个缺点就是会增加浏览器域名解析的次数,这里建议利用CDN来加载不是经常更新和修改的静态资源(图片,css库,js第三方库等等)。一个是CDN域名一般都会缓存到本地中,另一个是CDN网络请求速度是非常快的。
        由于CDN部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载

5: 解释一下axios 和 await

Axios特性
        1、可以在浏览器中发送 XMLHttpRequests
        2、可以在 node.js 发送 http 请求
        3、支持 Promise API
        4、拦截请求和响应
        5、转换请求数据和响应数据
        6、能够取消请求
        7、自动转换 JSON 数据
        8、客户端支持保护安全免受 XSRF 攻击
    Axios用在什么场景?
        在特性里面已经有提到,浏览器发送请求,或者Node.js发送请求都可以用到Axios。像Vue、React、Node等项目就可以使用Axios,如果你的项目里面用了Jquery,此时就不需要多此一举了,jquery里面本身就可以发送请求。

6: promise有几个状态 分别是什么

pending、fulfilled、rejected(未决定,履行,拒绝),同一时间只能存在一种状态,且状态一旦改变就不能再变。promise是一个构造函数,promise对象代表一项有两种可能结果(成功或失败)的任务,它还持有多个回调,出现不同结果时分别发出相应回调。

1.初始化,状态:pending

2.当调用resolve(成功),状态:pengding=>fulfilled

3.当调用reject(失败),状态:pending=>rejected

3.promise的优缺点

​ 优点:

​ 1.Promise 分离了异步数据获取和业务逻辑,有利于代码复用。

​ 2.可以采用链式写法

​ 3.一旦 Promise 的值确定为fulfilled 或者 rejected 后,不可改变。

​ 缺点:代码冗余,语义不清。

详解 Promise几种状态详解

7: promise 是异步还是同步

Promise作用:解决异步回调的问题

promise本身是同步的

let oP = new Promise( (res, rej) => {
     console.log(1);
});
console.log(2);

//  1
//  2

执行的结果先打印出1再打印出2,如果promise是异步的应该先打印出2,所以promise本身是同步

promise的回调then是异步的

let oP = new Promise( (res, rej) => {
     console.log(1);
});
oP.then(res => {
     console.log(3);
});
console.log(2);

// 1
// 2
// 3

执行的结果1,2,3,因为then是异步的,所以先打印了2,最后再执行回调打印出3

ES6 同步和异步、Promise

8: new 一个构造函数的时候都做了什么

    1.新创建一个空对象: var fn = new Object();
    2.构造函数的显示原型等于实例对象的隐式原型,实例对象的constructor属性为构造函数的名称: Fn.prototype = fn.__proto__
    3.通过调用call、apply方法执行构造函数并改变this对象(绑定到实例对象上): Fn.call(f)
    4.如果没有手动返回其他任何对象或返回值是基本类型(Number、String、Boolean)的值,会返回 this 指向的新对象,也就是实例,若返回值是引用类型(Object、Array、Function)的值,则实际返回值为这个引用类型。

new做了下面这些事:

  • 创建一个临时对象
  • 给临时对象绑定原型
  • 给临时对象对应属性赋值
  • 将临时对象return

9: display: none 和 class="hidden" 的区别 

相同点是都能把网页上某个元素隐藏起来 

不同点:

display:none  ---  不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失,通俗来说就是看不见也摸不到。     

class="hidden"--- 使对象在网页上不可见,但该对象在网页上所占的空间没有改变,通俗来说就是看不见但摸得到

     .hidden {

              display: none!important;

              visibility: hidden!important;

     }

bootstarp

10:标准的盒子模型

11:伪类选择器什么时候会用到 ,为什么要用伪类选择器

12: 如何解决跨域问题 ,为什么会有跨域的问题

    跨域问题是因为浏览器的同源策略引起的,一种浏览器的安全机制,要求协议,域名,端口,都要一致!
    如何解决跨域?
        jsonp,只支持get,不支持post,需要调用前端和被调用后端配合(比较常用)
        后端HttpClient进行转发,两次请求,效率低,安全(类似Nginx反向代理)
        服务端设置响应头,允许跨域,适于小公司快速解决问题
        Nginx搭建API接口网关
        Zuul搭建API接口网关
        后四种都属于服务端设置,对于目前还是一个纯前端的我来说,先把前端的搞懂再说,所以在此只说前端的jsonp

        jsonp工作原理理解
            jsonp实际上是通过动态插入js的方式实现的跨域,因为通过script标签引入js文件没有跨域一说
            web客户端通过调用脚本的方式去调用跨域服务端动态生成的js文件(一般以json为后缀),同时传递一个callback参数给服务端,服务端以这个参数名为函数名,调用此函数以参数的形式将数据传到web端,这样就实现了前端跨域请求服务端数据。

13: ajax工作原理

ajax是一种不重载整个页面的情况下局部更新页面数据的一种异步请求方法。核心是XMLHttpRequest对象。

14: sessionId详解

sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。服务端在创建了Session的同时,会为该Session生成唯一的sessionId,而sessionId会在随后的请求中会被用来重新获得已经创建的Session;Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有sessionId;当客户端再次发送请求的时候,会将这个sessionId带上,服务器接受到请求之后就会依据sessionId找到相应的Session,从而再次使用之。当客户端第一次请求session对象时候,服务器会为客户端创建一个session,并将通过特殊算法算出一个session的ID,用来标识该session对象。

15: 构造函数

构造函数是什么?构造函数与其他函数唯一的区别在于调用方式不同。任何函数只要通过new来调用就可以作为构造函数,它是用来创建特定类型的对象。

通过new命令来生成一个person实例:

var person1 = new Female("Summer")

这里,构造函数Female就是实例对象person1的原型!!!Female里的this关键字就指的是person1这个对象! 

16:长连接和短连接

在http1.0中,采用的是短连接,即每一次请求都要建立http连接,随后立刻关掉,比如一个网站要请求100张图片,就要建立100次http连接。

在http1.1中,添加了keep-alive属性,可以持续一段时间。

长连接虽然提高了连接的复用性,但长时间不关闭也带来了缺点,比如一个网站收到了大量http请求,且都不会在短期释放,那么就会引发性能问题。

17:Cookie、sessionStorage、localStorage的区别

共同点:都是保存在浏览器端,并且是同源的

  • Cookie:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下,存储的大小很小只有4K左右。 (key:可以在浏览器和服务器端来回传递,存储容量小,只有大约4K左右)

  • sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持,localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。(key:本身就是一个回话过程,关闭浏览器后消失,session为一个回话,当页面不同即使是同一页面打开两次,也被视为同一次回话)

  • localStorage:localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。(key:同源窗口都会共享,并且不会失效,不管窗口或者浏览器关闭与否都会始终生效)

补充说明一下cookie的作用:

  • 保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。 cookie还可以设置过期时间,当超过时间期限后,cookie就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个 月、一年等。

  • 跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了 cookie后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后 台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便

  • 定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页