zoukankan      html  css  js  c++  java
  • 前端面试基础总结(个人整理_彦超)

    前端面试基础总结

    1、跨域解决办法:

    1、 通过jsonp跨域
    2、 document.domain + iframe跨域
    3、 location.hash + iframe
    4、 window.name + iframe跨域
    5、 postMessage跨域
    6、 跨域资源共享(CORS)
    7、 nginx代理跨域
    8、 nodejs中间件代理跨域
    9、 WebSocket协议跨域
    

    2、同源策略下有几个标签不受限制:

    <img src="" alt="" />
    <link rel="stylesheet" type="text/css" href="style.css" />
    <script type="text/javascript" src=""></script>    
    

    3、JS代码压缩原理:

    基于Base62 encode压缩方式
    	简单来说就是将相同的单词进行压缩,具体为将所有单词抽取出来作为一个词典,
    	然后将源代码中表示单词的地方改为引用词典的下标
    

    4、Object.create()

    创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
    Object.create(null)在该对象上没有继承 Object.prototype 原型链上的属性或者方法
    	如:toString(), hasOwnProperty()等方法
        正确的写法:Object.create(Object.prototype);   
    

    5、canvas绘图环境

    通过调试canvas对象的getContext()方法。
    

    6、进制转换:

    Number.toString(radix)

    	这个函数只能将十进制数字转换为任意进制的字符串形式,同样,radix表示进制,取值2~36。
    		(10).toString(2)//"1010"转2进制
    		(1000).toString(36)//"rs" 转36进制
    

    Number.parseInt(string , radix)

    	这个是把字符串(只能由字母和数字组成),这个只能是由低进制转高进制,
    		Number.parseInt('010',8)//8
    		Number.parseInt('20',2)//NaN
    

    7、koa2洋葱模型:

    回调函数的嵌套
    	compose函数中将`context`一路传下去给中间件
    	将`middleware`中的下一个中间件`fn`作为未来`next`的返回值
    	我们在使用use的时候将middleware存在一个数组里面,当拦截到请求时执行callback方法,callback中调用了compose,
    	compose方法使用递归执行中间件,遍历完成返回promise.resolve(),实际最后执行的代码也是promise嵌套的形式。
    

    8、Array.of和new Array:

    1、Array.of(3)输出[3];new Array(3)输出[undefined,undefined,undefined,]    
    

    9、DNS在进行域名解析时

    DNS在进行域名解析时使用UDP,但是在域名服务器之间传输时使用的是TCP
    

    10、CSS权重:

    !important>行内样式>id选择器>类选择器>标签选择器>通配符>继承,color可继承则为最高    
    

    11、:before和:after的使用方法:

    在类选择器后面用:before和:after连接,表示输出在标签前后的行内样式,
    如果加上display:block输出在标签上下的块级样式,也可用于清楚浮动
    

    12、闭包的定义:

        1、函数内部的变量为私有变量,外部不能访问,但是函数内部的函数可以访问,
    	   闭包就是在函数内返回一个函数,使得在全局下可以通过函数内返回的函数访问到函数的变量
        2、函数执行形成不能被释放的私有栈内存
    

    闭包的使用场景:

    	    1、使用场景一:给对象设置私有变量并且利用特权方法去访问私有属性
    	    2、封装相关功能集
        优缺点:
            1.保护函数内的变量安全,加强了封装性
            2.在内存中维持一个变量(用的太多就变成了缺点,占内存)
        原因:
            1.在闭包的作用域链中引用了html元素未释放内存
            2.出现了循环引用    
    

    13、文件传输

    1、FormData(二进制文件信息 提交为文件格式)

    		文件名需要通过md5加密+时间戳+hash进行处理,产生唯一的文件名,使用FormData()
    

    2、base64编码(流信息 提交为表单格式)

    		let file='表单id'.files[0]
    		let file_=new FileReader()
    		file_.readAsDataURL(file)   获取文件base64编码
    		   //file_.readAsDataBuffer(file)也可以转换成ArryBuffer格式
    		file_.onload=e=>{
    			console.log(e.target.result)//拿到编码
    		}   
    

    大文件上传

    1、blob切片(blob.prototype.slice)

    	   同时发送请求(利用http可以多个并发传递6~7)
    	   都上传之后向服务器发送合并请求(两次请求)
    	   chunk:文件切片
    	   filename:切片的名字 hash-数字后缀
    	   传输接片文件的时候为提交为文件格式,传输合并请求时为表单格式
    

    前端静态文本下载

    	纯文本:  down_.href = window.URL.createObjectURL(new Blob(["Hello World"]));
    	对象  :	 var obj_blob = new Blob([JSON.stringify([1, 2, 3], null, 2)])
    		     URL.createObjectURL(obj_blob)
    

    14、null 与 undefined:

    JavaScript 中,null 是一个可以被分配的值,设置为 null 的变量意味着其无值。
    而 undefined 则代表着某个变量虽然声明了但是尚未进行过任何赋值。
    

    15、Loader和Plugin的不同?

    不同的作用

      1、Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,
    		   如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack
    		   拥有了加载和解析非JavaScript文件的能力。
      2、Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 
    	       在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,
    		   在合适的时机通过 Webpack 提供的 API 改变输出结果。
    

    不同的用法

      1、Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,
    	   里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)
      2、Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。
    

    16、对象类型:

    普通对象-Object 数组对象-Array 正则对象-RegExp 日期对象-Date 数学函数-Math 函数对象-Function   
    

    17、事件冒泡(Event Bubbling) :

    Event Bubbling 即指某个事件不仅会触发当前元素,还会以嵌套顺序传递到父元素中。
    直观而言就是对于某个子元素的点击事件同样会被父元素的点击事件处理器捕获。
    

    18、事件流被分为3个阶段:

    捕获阶段,目标阶段,冒泡阶段   
    

    19、如果存在多个事件:

    document.onclick=function(){}后注册的事件会覆盖先注册的事件,
    使用addEventListener(type,listener,useCapture)则不会,
    useCapture:默认为false,事件冒泡从下往上逐级打印,true时相反
    

    20、V8 中执行一段JS代码的整个过程:

    1、生成了 AST (类对象类型)
    2、将 AST 通过 V8 的解释器(也叫Ignition)转换为字节码
    3、在执行字节码的过程中,如果发现某一部分代码重复出现,那么 V8 将它记做热点代码(HotSpot),
       然后将这么代码编译成机器码保存起来,这个用来编译的工具就是V8的编译器,代码执行的时间越久,那么执行效率会越来越高
    //通过解释器逐行解释代码,省去了一次性将全部的字节码都转换成机器码大大降低了内存的压力
    

    21、对象的遍历

    for...in  								可枚举属性  实例属性  原型属性
    Object.keys() 							可枚举属性  实例属性   
    Object.getOwnPropertyNames() 不可枚举属性+可枚举属性			原型属性
    Reflect.ownKeys()			 不可枚举属性+可枚举属性  实例属性	原型属性 Symbol类型属性
    

    22、window.open && window.location

    	window.location.search(获取当页面参数"?ww=xx&ww=xx")
    	window.location.href(获取当前页面地址)
    	window.open(url, name, [strWindowFeatures]);
    			url === 要在新打开的窗口中加载的URL。
    			name === 新窗口的名称。
    			strWindowFeatures === 一个可选参数,列出新窗口的特征(大小,位置,滚动条等)作为一个DOMString。
    			
    	*外链用了 target="_blank",新页面能通过window.opener获取到来源页面的window对象 CSRF 攻击
    			解决方案:加上rel="noopener"或者rel="noreferrer"。这样新窗口的window.openner就是null了,
    			而且会让新窗口运行在独立的进程里,不会拖累原来页面的进程		
    

    23、require.context():

    	如果遇到从一个文件夹引入很多模块的情况,可以使用require.context(),
    	它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块
    	require.context():
    		可以使用 require.context() 方法来创建自己的(模块)上下文。
    			这个方法有 3 个参数:
    				要搜索的文件夹目录
    				是否还应该搜索它的子目录
    				以及一个匹配文件的正则表达式。
    				
    	require.context("./test", false, /.test.js$/);
    	//(创建了)一个包含了 test 文件夹(不包含子目录)下面的、所有文件名以 `.test.js` 结尾的、
    	// 能被 require 请求到的文件的上下文。
    	
    	require.context模块导出(返回)一个(require)函数
    		导出的方法有 3 个属性: resolve, keys, id。
    		resolve 接受一个参数request,request为test文件夹下面匹配文件的相对路径
    		keys 返回匹配成功模块的名字组成的数组
    		id 是上下文模块里面所包含的模块 id
    

    24、事件循环:

    (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
    (2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
    (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。
    	那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
    (4)主线程不断重复上面的第三步。
    

    25、Class 和构造函数的区别:

    1. 不存在变量提升 
    2. 方法默认是不可枚举的 
    3. class 必须使用 new 调用  
    4. ES6可以继承静态方法,而构造函数不能   
    

    26、MVVM模式:

    1、M就是Model模型层,存的一个数据对象。
    2、V就是View视图层,所有的html节点在这一层。
    3、VM就是ViewModel,它通过data属性连接Model模型层,通过el属性连接View视图层。    
    

    27、垃圾回收机制:

    栈内存:
     按照执行顺序,也就是上下文切换之后,栈顶的空间会自动被回收
    v8引擎的堆垃圾回收机制:
    	新生代内存:64 位和 32 位系统下分别为 32MB 和 16MB
     	新生代中的变量如果经过多次回收后依然存在,那么就会被放入到老生代内存中
    	新生代的对象主要通过 Scavenge算法 进行垃圾回收。
    	老生代的对象主要通过进行标记-清除进行垃圾回收:
    		首先会遍历堆中的所有对象, 对它们做上标记,然后对于代码环境中使用的变量以及被强引用的变量取消标记,
    		剩下的就是要删除的变量了,在随后的清除阶段对其进行空间的回收。
    引发内存碎片的问题?
    	存活对象的空间不连续对后续的空间分配造成障碍,V8在清除阶段结束后,把存活的对象全部往一端靠拢。(最耗时间)		   
    	为了降低全堆垃圾回收带来的停顿时间,回收方式为增量标记(incremental marking)。
    
    Map和WeakMap,WeakMap只能以复杂数据类型作为key,并且key值是弱引用,对于垃圾回收更加友好。	
    

    28、position:sticky:

    position:relative 和 position:fixed 两种定位功能于一体的特殊定位,且position:sticky元素的任意父节点的 
    overflow 属性必须是 visible    
    

    29、CORS原理

    CORS原理只需要向响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的
    Access-Control-Allow-Origin,则就可以跨域操作了,CORS需要浏览器和服务器同时支持。IE浏览器不能低于IE10。
    简单请求
     HEAD GET POST HTTP头部信息不超出几个字段
       Content-Type字段类型是application/x-www-form-urlencoded、multipart/form-data、text/plain
    非简单请求
       请求方法是PUT或DELETE,Content-Type字段类型是application/json  
    

    30、四种类型的常见 JavaScript 内存泄露:

    1:意外的全局变量 
    2:被遗忘的计时器或回调函数 
    3:脱离 DOM 的引用 
    4:闭包     
    

    31、数组的数据存储*:

    初始化空数组时,使用快数组,快数组使用连续的内存空间,当数组长度达到最大时,JSArray 会进行动态的扩容,
    以存储更多的元素,相对慢数组,性能要好得多。当数组中 hole 太多时,会转变成慢数组,即以哈希表的方式
    ( key-value 的形式)存储数据,以节省内存空间。
    

    两种存储方式

     fast:是 V8 实现的一个类似于数组的类,它表示一段连续的内存,可以使用索引直接定位。
    	   新创建的空数组默认就是快数组。当数组满(数组的长度达到数组在内存中申请的内存容量最大值)的时候,
    	   继续 push 时, JSArray 会进行动态的扩容,以存储更多的元素。
     slow:以哈希表的形式存储在内存空间里,它不需要开辟连续的存储空间,
    	   但需要额外维护一个哈希表,与快数组相比,性能相对较差。      
    

    存储方式转换

    fast 转变为 slow

    1、当加入的索引值 index 比当前容量 capacity 差值大于等于 1024 时
    2、快数组新容量是扩容后的容量 3 倍之多时
    	例:var arr = [1, 2, 3]
    		arr[2000] = 10;
    		当往 arr 增加一个 2000 的索引时,arr 被转成慢数组。节省了大量的内存空间
    

    slow 转变为 fast

    当慢数组的元素可存放在快数组中且长度在 smi 之间且仅节省了50%的空间,则会转变为快数组
    
    数组进行push操作时
    	申请新的长度内存空间
    	将数组拷贝到新的数组中
    	把新数组放到当前length位置
    	数组的length+1
    	返回 length
    

    32、对象进行比较:

    通过JSON.stringify()转为字符串,在进行比较,或者递归,或者Deep Equal模组方法
    

    33、前端登录方案:

    session: 1、客户端访问login接口,服务器收到后校验信息,正确后会在服务器端存储一个sessionId和session的映射关系
    	     2、服务器端返回response,并且将sessionId以set-cookie的方式发送到客户端,这样sessionId就存在了客户端。
    	     3、客户端发送非登录请求时,服务端就能通过cookie中的sessionId找到对应的session来知道这次请求是谁发的
    token: 1、客户端访问login接口,服务器收到后校验信息,正确后返回一个包含用户信息的token
    	   2、客户端拿到token后,每次请求将token加入http请求的header中
    单点登录(SingleSign-On,SSO):在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。  
    

    34、前端性能监控

    performance
    memory字段代表JavaScript对内存的占用。
    navigation字段统计的是一些网页导航相关的数据:
    	redirectCount:重定向的数量(只读),但是这个接口有同源策略限制,即仅能检测同源的重定向;
    	type 返回值应该是0,1,2 中的一个。分别对应三个枚举值:
    		0 : TYPE_NAVIGATE (用户通过常规导航方式访问页面,比如点一个链接,或者一般的get方式)
    		1 : TYPE_RELOAD (用户通过刷新,包括JS调用刷新接口等方式访问页面)
    		2 : TYPE_BACK_FORWARD (用户通过后退按钮访问本页面)
    最重要的是timing字段的统计数据,它包含了网络、解析等一系列的时间数据。
    	var time = performance.timing
    	performance.getEntries()
    	'重定向时间:' + (time.redirectEnd - time.redirectStart) / 1000
    	'DNS解析时间:' + (time.domainLookupEnd - time.domainLookupStart) / 1000
    	'TCP完成握手时间:' + (time.connectEnd - time.connectStart) / 1000
    	'HTTP请求响应完成时间:' + (time.responseEnd - time.requestStart) / 1000
    	'onload事件时间:' + (time.loadEventEnd - time.loadEventStart) / 1000
    

    34.1、首屏和白屏时间如何计算

    原生: onload 事件
    ios :webViewDidFinishLoad 事件
    android :onPageFinished 事件
    
    方法1:当页面的元素数小于x时,则认为页面白屏。比如“没有任何内容”,可以获取页面的DOM节点数,判断DOM节点数少于某个阈值X,则认为白屏。
    方法2:当页面出现业务定义的错误码时,则认为是白屏。比如“网络或服务异常”。 
    方法3:当页面出现业务定义的特征值时,则认为是白屏。比如“数据加载中”。
    

    35、块级元素:

    <h1>~<h6>、<p>、<div>、<ul>、<ol>、<li>等

    (1)总是从新行开始
    (2)高度,行高、外边距以及内边距都可以控制。
    (3)宽度默认是容器的100%
    (4)可以容纳内联元素和其他块元素。
    

    36、行内元素:

    <a>、<strong>、<b>、<em>、<i>、<del>、<s>、<ins>、<u>、<span>等

    (1)和相邻行内元素在一行上。
    (2)高、宽无效,但水平方向的padding和margin可以设置,垂直方向的无效。
    (3)默认宽度就是它本身内容的宽度。
    (4)行内元素只能容纳文本或则其他行内元素。(a特殊 a里面可以放块级元素 )  
    

    37、行内元素:

    <img />、<input />、<td>

    (1)和相邻行内元素(行内块)在一行上,但是之间会有空白缝隙。
    (2)默认宽度就是它本身内容的宽度。
    (3)高度,行高、外边距以及内边距都可以控制。     
    

    38、重绘(repaint):

     当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少
    

    39、回流(reflow):

     当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为回流。
     此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。会触发回流的操作
     当我改变了元素的一个样式会导致浏览器发生回流或重绘时 ,它会进入一个渲染队列 ,然后浏览器继续往下看,
     如果下面还有样式修改 ,那么同样入队 ,直到下面没有样式修改 ,浏览器会按照渲染队列批量执行来优化重排过程,
     一并修改样式 ,这样就把本该4次的回流优化为1次 
    

    40、JSON.parse():

     JSON.parse(JSON.stringify(c,['title'])),JSON.stringify只选取数组内的进行格式化     
    

    41、cdn

    cdn 也叫内容分发网络,cdn就是通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,
    	使得提高用户访问响应速度和命中率。
    

    42、js中i++与++i的区别:

    使用i++时,i先将自身的值赋值给变量a,然后再自增1
    使用++i时,i先将自身的值自增1,再将自增后的值赋值给变量a
    

    43、怪异盒子模型:

    1、元素的宽度和高度指的是元素内容的宽度和高度,而在怪异的盒子模型中宽度和高度还包含了 padding 和 border。
    2、行内元素在怪异盒子模型中设置高度会生效
    

    44、监听页面位置

    event.clientX,event.clientY表示点击事件发生时候的位置
    x轴:pageXOffset
    y轴:pageYOffset
    

    懒加载:

    第一种

    	获取屏幕可视窗口高度:document.documentElement.clientHeight
    	获取观测元素相对于文档顶部的距离:element.offsetTop
    	获取可视窗口距离文档顶部的距离即滚动条的距离:document.documentElement.scrollTop
    	offsetTop - scrollTop - clientHeight <= 0(该元素出现)
    

    第二种

    	Element.getBoundingClientRect()方法
    	   方法返回的一组矩形的集合,就是该元素的 CSS 边框大小,位置
    	function isInSight(el){
    		const bound = el.getBoundingClientRect();
    		const clientHeight = window.innerHeight;
    		return bound.top <= clientHeight + 100;
    	}
    

    45、promise

    promise是js中的一个对象,用于生成可能在将来产生结果的值且返回一个promise对象

    promise 可以有三种状态,一旦确定就不能返回:
        pending:初始状态,既不是成功也不是失败
        fulfilled:意味着操作完全成功
        rejected:意味着操作失败  
    

    catch和reject

    Promise.then的第二个参数捕捉不了‘异常捕获’和‘冒泡错误’,只能由catch语句进行捕获,
    并且reject是用来抛出异常的,catch是用来处理异常的;
    

    46、javascript会阻塞dom的解析

    当解析过程中遇到<script>标签的时候,便会停止解析过程,转而去处理脚本
    

    <script defer>浏览器会异步的下载该文件并且不会影响到后续DOM的渲染;
    <script async>并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。

    47、宏任务和微任务

    宏任务中如果有微任务则继续执行,如果依然为宏任务则跳出执行
    微任务中如果有宏任务则跳出执行,如果依然为微任务则继续执行
    
    		Promise.resolve().then(() => {
    			console.log('promise1');
    			const timer2 = setTimeout(() => {
    				console.log('timer2')
    			}, 0)
    		});
    		const timer1 = setTimeout(() => {
    			console.log('timer1')
    			Promise.resolve().then(() => {
    				console.log('promise2')
    			})
    		}, 0)
    		
    		console.log('start');
    		'start'
    		'promise1'
    		'timer1'
    		'promise2'
    		'timer2
    

    48、闭包作用域

    闭包中return function(){}其实是返回给全局了,this的作用域已经是window了
    闭包中的this指向调用函数环境的上一级
    
    var num = 1
    var obj = {
    	num: 2,
    	getone: function() {
    		var num = 3
    		window.num = 4
    		return function() {
    			return this.num
    		}
    	}
    }
    obj.getone()() //4
    
    var name = "window作用域";
    var object = {
    	name: "对象作用域",
    	getNameFunc: function() {
    		return function() {
    			return this.name;
    		};
    	}
    };
    object.getNameFunc()(); //"window作用域"
    

    49、css特效:

    rotateY:定义沿 Y 轴的 3D 旋转,可实现翻书的效果
    translateY:沿着 Y 轴移动元素
    perspective(n):改变3D元素是怎样查看透视图(注:只影响 3D 转换元素)
    scaleY:定义 2D 缩放转换时,改变元素的高度;定义 3D 缩放转换时,通过给定一个 Y 轴的值
    

    50、jquery链式调用原理:

    jq的方法都是挂在原型的,那么如果我们每次在内部方法返回this,也就是返回实例对象,
    那么我们就可以继续调用原型上的方法了,这样的就节省代码量,提高代码的效率,代码看起来更优雅
    

    51、jwt:

    优点:
        1. 可扩展性好 session是保存在服务端的,而jwt是保存在客户端的
        2. 无状态 jwt不在服务端存储任何状态
    缺点:
        1. 安全性 jwt的payload是使用base64编码的,并没有加密
        2. 性能 由于是无状态使用JWT,所有的数据都被放到JWT里导致jwt太长。
        3. 一次性 jwt是一次性的。想修改里面的内容,就必须签发一个新的jwt。    
    

    52、TCP 和 UDP 的区别:

    TCP是一个面向连接的、可靠的、基于字节流的传输层协议。

    UDP是一个面向无连接的传输层协议,基于报文。

    简述三次握手
    	1、从最开始双方都处于CLOSED状态。然后服务端开始监听某个端口,进入了LISTEN状态	
    	2、然后客户端主动发起连接,发送 SYN , 自己变成了SYN-SENT状态
    	3、服务端接收到,返回SYN和ACK(对应客户端发来的SYN),自己变成了SYN-REVD。
    	4、之后客户端再发送ACK给服务端,自己变成了ESTABLISHED状态;服务端收到ACK之后,也变成了ESTABLISHED状态。
    	5、另外需要提醒你注意的是,从图中可以看出,SYN 是需要消耗一个序列号的,
    	下次发送对应的 ACK 序列号要加1,为什么呢?只需要记住一个规则:
    		凡是需要对端确认的,一定消耗TCP报文的序列号。
    

    53、关于meta标签的几个常见作用

    1、向搜索引擎说明你的网页的关键词
    2、告诉搜索引擎你的站点的主要内容
    3、告诉搜索引擎你的站点的制作的作者
    4、禁用缓存
    

    54、垂直居中:

    1、 利用 line-height实现居中,这种方法适合纯文字类
    2、 通过设置父容器 相对定位,子级设置 绝对定位,标签通过margin实现自适应居中
    3、 父级设置相对定位,子级设置绝对定位,并且通过位移 transform实现
    	 绝对定位和margin-left: -width/2, 前提是父元素position: relative
    3、 flex布局使用justify-content:center   
    

    55、函数柯里化

    用闭包把参数保存起来,当参数的数量足够执行函数了,就开始执行函数

    		const curry = fn =>
    		// 返回一个新函数,接收参数为 ...args
    			judge = (...args) =>  
    		//新函数接收的参数长度是否等于 fn 参数需要接收的长度	  
    			args.length === fn.length ?  
    		// 满足要求,执行 fn 函数,传入新函数的参数
    			fn(...args) :
    		// 不满足要求,递归 currying 函数
    		// 新的 fn 为 bind 返回的新函数,新的 length 为 fn 剩余参数的长度
    			(...arg) => judge(...args, ...arg)
    
    		var fn = curry(function(a, b, c) {
    			return a + b + c;
    		});
    		
    		console.log(fn(1, 2, 3)) // ["a", "b", "c"]
    		console.log(fn(1, 2)(3)) // ["a", "b", "c"]
    		console.log(fn(1)(2)(3)) // ["a", "b", "c"] 
    

    56、对象中的valueOf

    如何让 if(a == 1 && a == 2 &&a == 3) 条件成立?

        var a = {
        value: 0,
        valueOf: function() {
            this.value++;
            return this.value;
          }
        };
    	
        返回自身,相当于自身自增       
    

    57、用省略号代表多余的字符:

        .box{
            display: inline-block;
            white-space: nowrap;
             50%;
            overflow: hidden;
            text-overflow:ellipsis;
        }     
    

    58、浅拷贝

    只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,
    换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
    

    数组常用的浅拷贝方法有:

    slice、
    Array.from()、
    var arr2 = arr.map(item=> item)、
    以及es6的解构、
    var arr2 = [...arr]  
    

    对象常用的浅拷贝方法:

    Object.assign(),es6解构
    

    59、深拷贝:

    在计算机中开辟了一块新的内存地址用于存放复制的对象。
    

    深拷贝方法:JSON.parse(JSON.stringify()) 面临问题:

        对象的属性值是函数时,无法拷贝。
        原型链上的属性无法拷贝
        不能正确的处理 Date 类型的数据
        不能处理 RegExp
        会忽略 symbol
        会忽略 undefined    
    

    60、commonJS AMD CMD

    commonJS(通过node的fs的功能,内部添加一个匿名函数并返回)
    	commonJS运行于服务器端,node.js的模块系统,就是参照CommonJS规范实现的,每个模块都是一个单独的作用域。
    	模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象。
    	
    AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块 
    	AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,
    	这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行
    			define('xxx',[],function(){
    				return 'AMD'
    			})
    			require(['xxx'],function(xxx){
    				console.log(xxx)//'AMD'
    			})
    	
    CMD推崇就近依赖,只有在用到某个模块的时候再去require 	
    	CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,
    	遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的
    	
    	这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行的原因
    

    60.1、Common.js 和 es6 module

    CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
    CommonJS 模块是运行时加载,ES6 模块是编译时输出接口、静态编译
    CommonJs 是单个值导出,ES6 Module可以导出多个
    CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
    CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
    	export default 导出已声明的对象 例如 export default Windows
    	export 导出多个声明的对象 例如 export const c={}
    

    61、变量提升:

    1、如果声明一个变量的时候没有使用var关键字,那么这个变量将是一个全局变量
    2、局部变量优先级大于全局变量
    3、函数是一等公民,所以函数声明会覆盖变量声明,但是,如果这个变量或者函数其中是赋值了的,那么另外一个将无法覆盖它
    4、全局变量:所有在函数外面声明的变量都处于全局作用域中。在浏览器环境中,这个全局作用域就是Window对象。
    5、变量的提升:只是其声明(定义)提升,而变量的赋值并不会提升。
    6、var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部     
    

    62、性能优化:

    (1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 
    (2) 减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,减少请求次数 
    (3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。 
    (4) 当需要设置的样式很多时设置className而不是直接操作style。 
    (5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。 
    (6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。 
    (7) 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。   
    

    63、内存泄漏:

    内存泄露是指一块被分配的内存既不能使用,又不能回收,多个对象循环引用、循环引用自己、直到浏览器进程结束。
    
    新旧虚拟dom 的比较,如果有差异就以新的为准,然后再插入的真实的dom中,重新渲染不设key,newCh和oldCh只会进行头尾两端的相互比较,
    设key后,除了头尾两端的比较外,还会从用key生成的对象oldKeyToIdx中查找匹配的节点,所以为节点设置key可以更高效的利用dom
    流程:
        1、用JS对象模拟DOM(虚拟DOM)
        2、把此虚拟DOM转成真实DOM并插入页面中(render)
        3、如果有事件发生修改了虚拟DOM,比较两棵虚拟DOM树的差异,得到差异对象(diff)
        4、把差异对象应用到真正的DOM树上(patch)          
    

    65、跨域:

    cookie跨域:
    	path表示cookie所在的目录,path子路径下的页面都可以访问path
    	domain表示的是cookie所在的域
    		如域A为love.haorooms.com,域B为resource.haorooms.com,
    		domain设置为.haorooms.com;A B皆可访问
    		domain设置为resource.haorooms.com; 只有B可以访问
    localStorage跨域:
    	可以使用postMessage和iframe  
    

    66、JSONP:

    利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,可以解决跨域提交Ajax请求的问题。

    JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;

              它的兼容性更好,在更加古老的浏览器中都可以运行,
              不需要XMLHttpRequest或ActiveX的支持;
              并且在请求完毕后可以通过调用callback的方式回传结果。
    

    JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;

                它只支持跨域HTTP请求这种情况,
                不能解决不同域的两个页面之间如何进行JavaScript调用的问题。   
    

    67、进程与线程:

    浏览器是多 进程 的

    Browser 进程、GPU 进程、浏览器渲染进程等
    

    浏览器的渲染进程是多线程

    GUI 渲染线程、JavaScript 引擎线程、事件触发线程、定时触发器线程
    

    68、解决高度塌陷:

    1、在塌陷的父元素的最后添加一个空白的div,然后对该div进行清除浮动
    2、设置元素的类型为inline-block
    3、设置overflow为一个非默认值,一般都是使用overflow:hidden来开启BFC !最推荐   
    4、使用after伪类,向父元素后添加一个块元素,并对其清除浮动。
    

    69、TCP的三次握手和四次挥手:

    第一次握手:客户端发送一个SYN码给服务器,要求建立数据连接;
    第二次握手: 服务器SYN和自己处理一个SYN(标志);叫SYN+ACK(确认包);发送给客户端,可以建立连接
    第三次握手: 客户端再次发送ACK向服务器,服务器验证ACK没有问题,则建立起连接;
    
    第一次挥手: 客户端发送FIN(结束)报文,通知服务器数据已经传输完毕;
    第二次挥手: 服务器接收到之后,通知客户端我收到了SYN,发送ACK(确认)给客户端,数据还没有传输完成 
    第三次挥手: 服务器已经传输完毕,再次发送FIN通知客户端,数据已经传输完毕
    第四次挥手: 客户端再次发送ACK,进入TIME_WAIT状态;服务器和客户端关闭连接; 
    

    70、TCP与UDP区别总结:

    1、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
    2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
    3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的   
    

    71、 http知识点

    1、 看到网页有乱码,则很有可能是某个请求的 Content-Type 响应头丢失或者是值设置不当造成的
    2、 即便是不需要发送请求体的 GET 请求,请求头区域下方也必须留一个空行(CRLF)
    3、 服务端可以根据客户端发送的 Accept-Encoding 请求头来分别返回不同压缩格式(Gzip、Brotli)的文件
    4、 服务端返回的 Date 响应头表示服务器上的系统时间,Date 响应头有参与缓存时长的计算
    5、 HTTP 是无状态的,网站是通过 Cookie 请求头来识别出两个请求是不是来自同一个浏览器的
    6、 Access-Control-Allow-Origin 响应头只支持配置单个的域名或者是 * ,不支持配置多个特定的域名
    7、 如果请求头或响应头中包含Connection: Keep-Alive,表示建立了持久连接,这样TCP连接会一直保持,之后请求统一站点的资源会复用这个连接。
    	浏览器中的缓存作用分为两种情况,一种是需要发送HTTP请求,一种是不需要发送
    

    71、数组转对象

    var a = Object.assign({}, [1, 2, 3]);
    var a =  {...[1, 2, 3]};
    

    72、

  • 相关阅读:
    20181205关于android动态权限管理的总结与思考。
    pixel2坑
    Picasso遇到的坑
    集成主流框架搭建项目
    outdoor-youwin
    利用scatter()绘制颜色映射的二次方曲线
    一个有意义的Day类
    [Hadoop] Yarn & k8s
    hadoop 操作
    yarn 图形化监控
  • 原文地址:https://www.cnblogs.com/GET-one/p/13511241.html
Copyright © 2011-2022 走看看