征服前端面试(上篇)

JavaScript

原型

咱们建立的每个函数,均可以有一个prototype属性,该属性指向一个对象。这个对象,就是原型。javascript

当咱们在建立对象时,能够根据本身的需求,选择性的将一些属性和方法经过prototype属性,挂载在原型对象上。而每个new出来的实例,都有一个proto属性,该属性指向构造函数的原型对象,经过这个属性,让实例对象也可以访问原型对象上的方法。所以,当全部的实例都可以经过proto访问到原型对象时,原型对象的方法与属性就变成了共有方法与属性。java

经过图示咱们能够看出,构造函数的prototype与全部实例对象的proto都指向原型对象。而原型对象的constructor指向构造函数。es6

原型链

咱们知道全部的函数都有一个叫作toString的方法。那么这个方法究竟是在哪里的呢?json

先随意声明一个函数:跨域


其中foo是Function对象的实例。而Function的原型对象同时又是Object的实例。这样就构成了一条原型链。原型链的访问,其实跟做用域链有很大的类似之处,他们都是一次单向的查找过程。所以实例对象可以经过原型链,访问处处于原型链上对象的全部属性与方法。这也是foo最终可以访问处处于Object原型对象上的toString方法的缘由。数组

做用域链

做用域链的做用是保证执行环境里有权访问的变量和函数是有序的,做用域链的变量只能向上访问,变量访问到window对象即被终止,做用域链向下访问变量是不被容许的。浏览器

闭包

  • 第一种理解(红宝书):是指有权访问另外一个函数做用域中的变量的函数,建立闭包的最多见的方式就是在一个函数内建立另外一个函数,经过另外一个函数访问这个函数的局部变量缓存

  • 第二种理解(你不知道的javascript):当函数能够记住并访问所在的词法做用域时,就产生了闭包,这个函数持有对该词法做用域的引用,这个引用就叫作闭包安全

  • 闭包本质仍是函数,只不过这个函数绑定了上下文环境(函数内部引用的全部变量)性能优化

缺点:常驻内存,会增大内存使用量,使用不当很容易形成内存泄露。
做用(使用场景):能够用来管理私有变量和私有方法,将对变量(状态)的变化封装在安全的环境中,使得这些变量不能被外部随意修改,同时又能够经过指定的函数接口来操做。
闭包有三个特性:
1.函数嵌套函数
2.函数内部能够引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收

题外话:

  • JavaScript的做用域就是词法做用域而不是动态做用域,

  • 词法做用域最重要的特征是它的定义过程发生在代码的书写阶段

  • 动态做用域的做用域链是基于调用栈的 词法做用域的做用域链是基于代码中的做用域嵌套

this

JavaScript的this老是指向一个对象,而具体指向哪一个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

this的指向:

一、做为普通函数调用(this指向全局对象window对象)
二、做为对象的方法调用(this指向该对象)
三、构造器调用(this指向用new返回的这个对象)
四、call、apply、bind的调用(this指向第一个参数对象)

高阶函数

一、函数做为参数传递
二、函数做为返回值输出

new操做符具体干了什么呢?

一、建立一个新对象
二、将构造函数的做用域赋给新对象(所以this就指向了这个新对象)
三、执行构造函数中的代码(为这个新对象添加属性)
四、返回新对象

继承

一、简单原型链继承

缺点:修改sub1.name后sub2.name也变了,由于来自原型对象的引用属性是全部实例共享的。

二、构造函数式继承

 

缺点:没法实现函数复用,每一个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。。

三、组合式继承

 

缺点:子类原型上有一份多余的父类实例属性,由于父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上父类的。。。又是内存浪费。

四、寄生组合式继承

 

五、es6的class继承方式

es6引入了class、extends、super、static(部分为ES2016标准)

null和undefined的区别?

一、null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN。
二、undefined表示”缺乏值”,就是此处应该有一个值,可是尚未定义。
三、null表示”没有对象”,即该处不该该有值。

call、apply、bind的区别

  • 三者都是用来改变函数的this对象的指向的。

  • 三者第一个参数都是this要指向的对象,也就是想指定的上下文。

  • call 传入的参数数量不固定,第二部分参数要一个一个传,用,隔开。

  • apply 接受两个参数,第二个参数为一个带下标的集合,能够为数组,也能够为类数组。

  • bind 是返回一个改变了上下文的函数副本,便于稍后调用;apply 、call 则是当即调用 。

本地存储

  • sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问而且当会话结束后数据也随之销毁。所以sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。

  • localStorage用于持久化的本地存储,除非主动删除数据,不然数据是永远不会过时的。

cookie 和session

一、cookie数据存放在客户的浏览器上,session数据放在服务器上。
二、cookie不是很安全,别人能够分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
三、session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。
四、单个cookie保存的数据不能超过4K,不少浏览器都限制一个站点最多保存20个cookie。每次请求一个新的页面的时候Cookie都会被发送过去,与服务器进行交互。

XML和JSON的区别?

一、数据体积方面。
JSON相对于XML来说,数据的体积小,传递的速度更快些。
二、数据交互方面。
JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。
三、数据描述方面。
JSON对数据的描述性比XML较差。
四、传输速度方面。
JSON的速度要远远快于XML。

如何实现浏览器内多个标签页之间的通讯?

调用localstorge、cookies等本地存储方式

线程与进程的区别

一、一个程序至少有一个进程,一个进程至少有一个线程.
二、线程的划分尺度小于进程,使得多线程程序的并发性高。
三、进程在执行过程当中拥有独立的内存单元,而多个线程共享内存,从而极大地提升了程序的运行效率。
四、线程在执行过程当中与进程仍是有区别的。每一个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。可是线程不可以独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
五、从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分能够同时执行。但操做系统并无将多个线程看作多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

渐进加强和优雅降级

  • 渐进加强 :针对低版本浏览器进行构建页面,保证最基本的功能,而后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

  • 优雅降级 :一开始就构建完整的功能,而后再针对低版本浏览器进行兼容。

性能优化

  • 网页内容

    • 减小 http请求次数

    • 减小 DNS查询次数

    • 避免页面跳转

    • 缓存 Ajax

    • 延迟加载

    • 提早加载

    • 减小 DOM元素数量

    • 避免 404

  • 服务器

    • 使用CDN(内容分发网络)

    • 添加Expires或Cache-Control报文头

    • Gzip压缩传输文件

  • CSS

    • 将样式表置顶

    • 用代替@import

  • JavaScript

    • 把脚本置于页面底部

    • 使用外部JavaScript和CSS

    • 精简JavaScript和CSS

    • 去除重复脚本

    • 减小DOM访问

  • 图片

    • 优化图像

    • 优化CSS Spirite

    • 不要在HTML中缩放图片

    • favicon.ico要小并且可缓存

如何解决跨域问题?

jsonp、CORS、document.domain+iframe、window.name、window.postMessage

jsonp的原理是动态插入script标签

请解释一下 JavaScript 的同源策略。

这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。

指一段脚本只能读取来自同一来源的窗口和文档的属性。

哪些操做会形成内存泄漏?

一、内存泄漏指任何对象在您再也不拥有或须要它以后仍然存在。
二、垃圾回收器按期扫描对象,并计算引用了每一个对象的其余对象的数量。若是一个对象的引用数量为 0(没有其余对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象的内存便可回收。
三、setTimeout 的第一个参数使用字符串而非函数的话,会引起内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

Javascript垃圾回收方法

一、标记清除:这是JavaScript最多见的垃圾回收方式,当变量进入执行环境的时候,好比函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。

二、引用计数:引用计数的策略是跟踪记录每一个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,若是该变量的值变成了另一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值无法被访问了,所以能够将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

事件、IE与火狐的事件机制有什么区别? 如何阻止冒泡?

事件处理机制:IE是事件冒泡、firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件。

阻止冒泡:ev.stopPropagation()

说说严格模式的限制

  • 变量必须声明后再使用

  • 函数的参数不能有同名属性,不然报错

  • 禁止this指向全局对象

  • 不能使用with语句

  • 增长了保留字

  • arguments不会自动反映函数参数的变化

设立”严格模式”的目的:

消除Javascript语法的一些不合理、不严谨之处,减小一些怪异行为;

消除代码运行的一些不安全之处,保证代码运行的安全;

提升编译器效率,增长运行速度;

为将来新版本的Javascript作好铺垫。

请解释什么是事件代理

事件代理(Event Delegation),又称之为事件委托。便是把本来须要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是能够提升性能。

Event Loop、消息队列、事件轮询

异步函数在执行结束后,会在事件队列中添加一个事件(回调函数)(遵循先进先出原则),主线程中的代码执行完毕后(即一次循环结束),下一次循环开始就在事件队列中“读取”事件,而后调用它所对应的回调函数。这个过程是循环不断的,因此整个的这种运行机制又称为Event Loop(事件循环)

主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码(同步任务)调用各类外部API,它们在”任务队列”中加入各类事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取”任务队列”,依次执行那些事件所对应的回调函数。

执行栈中的代码(同步任务),老是在读取”任务队列”(异步任务)以前执行。

缓存

浏览器缓存(Browser Caching)是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用能够避免重复的网络请求和浏览器快速地读取本地数据,

http缓存

http缓存是基于HTTP协议的浏览器文件级缓存机制。即针对文件的重复请求状况下,浏览器能够根据协议头判断从服务器端请求文件仍是从本地读取文件
判断expires,若是未过时,直接读取http缓存文件

indexDB

是一个在客户端存储可观数量的结构化数据,而且为这些数据添加索引进行高性能检索。

cookie

指通常网站为了辨别用户身份、储存在用户本地终端上的数据(一般通过加密)。cookie通常经过http请求中在头部一块儿发送到服务器端。一条cookie记录主要由键、值、域、过时时间、大小组成,通常用户保存用户的认证信息。

localstorage

localStorage是h5的一种新的本地缓存方案,加快下次页面打开时的渲染速度,除非主动删除数据,不然数据是永远不会过时的。

sessionstorage

也是h5的一种本地缓存方案,数据的存储仅特定于某个会话中,也就是说数据只保持到浏览器关闭,当浏览器关闭后从新打开这个页面时, 以前的存储已经被清除。

相关文章
相关标签/搜索