jacascript 面试题整理

一、React 中 keys 的做用是什么?

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。javascript

render () {  
    return (
        <ul>
            {this.state.todoItems.map(
                ({item, key}) => { 
                    return <li key={key}>{item}</li>
                })
            }    
        </ul>  
    )}
复制代码

在开发过程当中,咱们须要保证某个元素的 key 在其同级元素中具备惟一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近建立的仍是被移动而来的元素,从而减小没必要要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,所以咱们毫不可忽视转换函数中 Key 的重要性。css

二、正则表达式验证相关面试题。

// 手机号码
function checkPhone(phone){ 
    if(!(/^1[3456789]\d{9}$/.test(phone))){ 
        alert("手机号码有误,请重填");  
        return false; 
    } 
}
// 判断字符串以字母开头,后面能够是数字,下划线,字母,长度为6-30
function checout(str){
    var reg=/^[a-zA-Z]\w{5,29}$/;
    if(str && reg.test(str)){
        alert('正确')
    }
}
// 写一个function,清除字符串先后的空格。
function trim(str) {
    if (str & typeof str === "string") {
        return str.replace(/(^s*)|(s*)$/g,""); 
    }
}
复制代码

三、javascript的typeof返回哪些数据类型.

string,boolean,number,undefined,function,objecthtml

四、例举3种强制类型转换和2种隐式类型转换?

答案:强制(parseInt,parseFloat,number) 隐式(== ===)前端

四、split() join() 的区别

答案:前者是将字符串切割成数组的形式,后者是将数组转换成字符串vue

五、 ajax请求的时候get 和post方式的区别

  • GET请求会将参数跟在URL后进行传递,而POST请求则是做为HTTP消息的实体内容发送给WEB服务器。固然在Ajax请求中,这种区别对用户是不可见的
  • GEt传输数据容量小,不安全,post传输数据内容大,更加安全;

六、call和apply的区别

相同点:改变函数的this指向java

var obj = {name: 'lisi'}
function fn() {
   console.log(this) 
}
fn.call(null)    //this指向window
fn.apply(null)   //this指向window
fn.call(obj)     //this指向obj
fn.apply(obj)    //this指向obj
复制代码

不一样点: call传参形式是,从第二个开始一个一个传,apply的第二个参数为数组,数组的每一项为函数的参数react

Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
复制代码

七、事件委托是什么

利用事件冒泡的原理,让本身的所触发的事件,让他的父元素代替执行!git

八、闭包是什么,有什么特性,对页面有什么影响,有什么好处,闭包使用场景:

***闭包***就是可以读取其余函数内部变量的函数,使得函数不被GC回收,若是过多使用闭包,容易致使内存泄露(再也不用到的内存,没有及时释放,就叫作内存泄漏) 闭包的好处 但愿一个变量长期驻扎在内存当中(不被垃圾回收机制回收), 避免全局变量的污染,私有成员的存在,安全性提升 闭包使用场景: 函数做为返回值;函数做为参数传递;闭包实际应用中主要用于封装变量,收敛权限;web

九、如何阻止事件冒泡,如何阻止默认事件

阻止事件冒泡:ev.stopPropagation();何阻止默认事件: (1)return false;(2) ev.preventDefault();面试

十、 解释jsonp的原理,以及为何不是真正的ajax

动态建立script标签,回调函数,Ajax是页面无刷新请求数据操做

十一、”==”和“===”的不一样

前者会自动转换类型,再判断是否相等,后者不会自动类型转换,直接去比较

十二、函数声明与函数表达式的区别?

在Javscript中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并不是是一视同仁的,解析器会率先读取函数声明,并使其在执行任何代码以前可用(能够访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。

// 函数声明   
 function add(){} 
 // 函数表达式
var del = function del(){} // 命名函数函数表达式
var update= function(){} // 命名函数函数表达式
function(){} // 匿名函数表达式
复制代码

函数表达式能够直接在函数定义后面加小括号执行,而函数声明则不行

var mult = function(x,y){ return(x*y); }();//正常
function div(x,y){ return(x/y); }()//报错 
复制代码

1三、对做用域上下文和this的理解,看下列代码:

var User = {
 count: 1,
 getCount: function() {
  return this.count;
 }
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?
复制代码

问两处console输出什么?为何? 答案:是1和undefined。  func是在window的上下文中被执行的,因此不会访问到count属性。

1四、看下面代码,给出输出结果

for(var i = 1; i <= 3; i++){  //建议使用let 可正常输出i的值
  setTimeout(function(){
      console.log(i);   
  },0); 
};
复制代码

答案:4 4 4。 缘由:Javascript事件处理器在线程空闲以前不会运行。

1五、Javascript的事件流模型都有什么?以及事件流的典型应用事件代理

  • “事件冒泡”:事件开始由最具体的元素接受,而后逐级向上传播
  • “事件捕捉”:事件由最不具体的节点先接收,而后逐级向下,一直到最具体的
  • “DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡

事件代理

  • 事件代理的原理用到的就是事件冒泡和目标元素,把事件处理器添加到父元素,等待子元素事件冒泡,而且父元素可以经过target(IE为srcElement)判断是哪一个子元素或者e.stopPropagation()阻止冒泡,从而作相应处理。
  • 1)将多个事件处理器减小到一个,由于事件处理器要驻留内存,这样就提升了性能。想象若是有一个100行的表格,对比传统的为每一个单元格绑定事件处理器的方式和事件代理(即table上添加一个事件处理器),不可贵出结论,事件代理确实避免了一些潜在的风险,提升了性能。 2)DOM更新无需从新绑定事件处理器,由于事件代理对不一样子元素可采用不一样处理方法。若是新增其余子元素(a,span,div等),直接修改事件代理的事件处理函数便可,不须要从新绑定处理器,不须要再次循环遍历。

1六、下满代码输出什么

var a = null;
alert(typeof a);
答案:object
复制代码

解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,因此用typeof检测会返回”object”。

1七、回答如下代码,alert的值分别是多少?

<script>
    var a = 100;  
    function test(){  
        alert(a);  
        a = 10;  //去掉了var 就变成定义了全局变量了
        alert(a);  
    }  
    test();
    alert(a);
</script>
复制代码

正确答案是: 100, 10, 10

1八、javaScript的2种变量范围有什么不一样?

  • 全局变量:当前页面内有效
  • 局部变量:函数方法内有效

1九、js 实现一个函数对javascript中json 对象进行克隆

var oldObject ="sdf";
var newObject = JSON.parse(JSON.stringify(oldObject));
console.log(newObject);
复制代码

20、js 实现 ajax 请求或者submit请求时 锁屏功能以及开锁功能(请求时界面Loading以及元素不能点击,请求完成即消除Loading)

function(url, fn) {
    // XMLHttpRequest对象用于在后台与服务器交换数据
    var obj = new XMLHttpRequest(); 
    obj.open('GET', url, true);
    obj.onreadystatechange = function() {
        if(obj.readyState == 4 && obj.status == 200||obj.status == 304){
            loading.style.display = "none"
        } else {
            alert("不能点击,哈哈哈!");
        }
    };
    obj.send(null);
}
复制代码

2一、请用js计算1-10000中出现的0 的次数

// 建立一个1-10000的数组集合
var arr = new Array(10000).fill('').map((item, index) => {
     return index + 1
    }
)
// 筛选出了全部带0的数字
var nerArrrr = arr.filter(item => /0/.test(item))
var length = nerArrrr.reduce((count, item) => { 
    return count + (String(item).match(/0/g)).length
}, 0)
console.log(length)
复制代码

2二、数组降维

var arr = [[0,1,2,3], [4,5,6,7], [8,9,0,1], [2,3,4,5]];
// 方法一
var result = [];
for(var i=0;i<arr.length;i++){
    for(var j=0;j<arr[i].length;j++){
        result.push(arr[i][j]);
    }
}
// 方法二
var result = [];
for(var i=0;i<arr.length;i++){
    result = result.concat(arr[i]);
}
// 方法三
function Jw(obj){
    return Array.prototype.concat.apply([],obj);
}
Jw(arr);
复制代码

2三、将url的查询参数解析成字典对象

function getUrlDic(){
    var queryDec = window.location.search.substring(1).split("&")
    var decObect = {}
    for(var i = 0; i < queryDec.length; i++){
        var searchHash = queryDec[i].split("=")
        var key = decodeURIComponent(searchHash[0])
        var value = decodeURIComponent(searchHash[1])
        decObect[key] = value   
    }
    console.log(decObect)
}
getUrlDic()
复制代码

2四、判断一个字符串中出现次数最多的字符,统计这个次数

let str = 'asfjasiofoivnoi';
function count(str){
   let obj = {},
   arr = str.split('');
   //遍历数组
   arr.forEach(function(val,index){
       //将数组的元素存入对象,初始值为1,若是后面遍历的元素以前已存在就+1
       if(obj[val]){
           obj[val]+=1;
       }else{
           obj[val]=1                      
       }
   })
   //遍历对象中的属性(字符),值(出现的次数)
   let num=0
   for(let key in obj){
       if(num < obj[key]){
           //将最多的次数赋给num
           num = obj[key];
       }
   }
   for(let key in obj){
       if(num == obj[key]){
           console.log('最多的字符串是'+key+', 出现次数是'+num);
       }
   }
}
count(str);
复制代码

2五、null和undefined的区别?

一、首先看一个判断题:null和undefined 是否相等

console.log(null==undefined)//true
    console.log(null===undefined)//false
    typeof null; // "object"
    typeof undefined; // "undefined"
复制代码
  • 缘由:null: Null类型,表明“空值”
  • 当一个声明了一个变量未初始化时,获得的就是undefined。

二、那到底何时是null,何时是undefined呢?null表示"没有对象",即该处不该该有值。典型用法是

  • 做为函数的参数,表示该函数的参数不是对象。

  • 做为对象原型链的终点。

undefined表示"缺乏值",就是此处应该有一个值,可是尚未定义。典型用法是:

  • 变量被声明了,但没有赋值时,就等于undefined。
  • 调用函数时,应该提供的参数没有提供,该参数等于undefined。
  • 对象没有赋值的属性,该属性的值为undefined。
  • 函数没有返回值时,默认返回undefined。

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

咱们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象。

new共通过了4几个阶段 一、建立一个空对象

var obj=new Object();
复制代码

二、设置原型链

obj.__proto__= Base.prototype;
复制代码

三、让Base中的this指向obj,并执行Base的函数体。

var result =Base.call(obj);
复制代码

四、判断Base的返回值类型:若是是值类型,返回obj。若是是引用类型,就返回这个引用类型的对象。

if (typeof(result) == "object"){
  Base=result;
}
else{
    Base=obj;;
}
复制代码

2七、defer和async的区别

defer和async都是可选的,且只对外部脚本文件有效

<script src="main.js"></script>
复制代码

浏览器会当即加载并执行指定的脚本,“当即”指在渲染该script标签之下的文档元素以前,也就是说不等待后续载入的文档元素,读到就加载并执行。

<script async src="main.js"></script>
复制代码

浏览器会当即下载脚本,但不妨碍页面中的其余操做,好比下载其余资源或等待加载其余脚本。加载和渲染后续文档元素的过程和main.js的加载与执行并行进行(异步)。

async不保证按照脚本出现的前后顺序执行,所以,确保二者以前互不依赖很是重要,指定async属性的目的是不让页面等待两个脚本的下载和执行,从而异步加载页面其余内容,建议异步脚本不要在加载期间修改DOM。

异步脚本必定会在页面的load事件前执行,但可能会在DOMContentLoaded事件触发以前或以后执行。

<script defer="defer" src="main1.js"></script>
<script defer="defer"  src="main2.js"></script>
复制代码

表示脚本会被延迟到文档彻底被解析和显示以后再执行,加载后续文档元素的过程将和main.js的加载并行进行(异步)。HTML5规范要求脚本按照它们出现的前后顺序执行,所以第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件。在现实当中,延迟脚本并不必定会按照顺序执行,也不必定会在DOMContentLoaded事件触发前执行,所以***最好只包含一个延迟脚本。***

  • defer 和 async 在网络读取(下载)这块儿是同样的,都是异步的(相较于 HTML 解析)
  • 它俩的差异在于脚本下载完以后什么时候执行,显然defer是最接近咱们对于应用脚本加载和执行的要求的
  • 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
  • async 则是一个乱序执行的主,反正对它来讲脚本的加载和执行是牢牢挨着的,因此无论你声明的顺序如何,只要它加载完了就会马上执行 仔细想一想,async 对于应用脚本的用处不大,由于它彻底不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些能够不依赖任何脚本或不被任何脚本依赖的脚原本说倒是很是合适的,最典型的例子:Google Analytics

2七、js延迟加载的方式有哪些?

defer和async、动态建立DOM方式(建立script,插入到DOM中,加载完毕后callBack)、按需异步载入js

2八、javaScript的2种变量范围有什么不一样?

  • 全局变量:当前页面内有效
  • 局部变量:函数方法内有效

29vue双向数据绑定的原理是什么

首先传输对象的双向数据绑定 Object.defineProperty(target, key, decription),在decription中设置get和set属性(此时应注意description中get和set不能与描述属性共存) 数组的实现与对象不一样。

let obj = {}
let input = document.getElementById('input')
let span = document.getElementById('span')
Object.defineProperty(obj, 'text', {
  configurable: true,
  enumerable: true,
  get() {
    console.log('获取数据了')
  },
  set(newVal) {
    console.log('数据更新了')
    input.value = newVal
    span.innerHTML = newVal
  }
})
input.addEventListener('keyup', function(e) {
  obj.text = e.target.value
})
复制代码

同时运用观察者模式实现wather, 完成用户数据和view视图的更新

2八、如下JS函数用于获取url参数:

function getQueryVariable(variable)
{
   var query = window.location.search.substring(1);
   var vars = query.split("&");
   for (var i=0;i<vars.length;i++) {
       var pair = vars[i].split("=");
       if(pair[0] == variable){return pair[1];}
   }
   return(false);
}
复制代码

2九、react setState后会发生什么?

setState() 将老是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。若是可变对象被使用了,但又不能在 shouldComponentUpdate() 中实现这种逻辑,仅在新 state 和以前的 state 存在差别的时候调用 setState() 能够避免没必要要的从新渲染。

react setState后:

  • React会将当前传入的参数对象与组件当前的状态合并,而后触发调和过程,在调和的过程当中,React会以相对高效的方式根据新的状态构建React元素树而且从新渲染整个UI界面.
  • React获得的元素树以后,React会自动计算出新的树与老的树的节点的差别,而后根据差别对界面进行最小化的渲染,在React的差别算法中,React可以精确的知道在哪些位置发生看改变以及应该如何去改变,这样就保证了UI是按需更新的而不是从新渲染整个界面.

setState—常规状况:在同一个方法中屡次setState是会被合并的,而且对相同属性的设置只保留最后一次的设置 参考详情

3一、react 生命周期函数

初始化阶段,这是组件即将开始其生命之旅并进入 DOM 的阶段。

  • getDefaultProps:获取实例的默认属性

  • getInitialState:获取每一个实例的初始化状态

  • componentWillMount:组件即将被装载、渲染到页面上,在渲染以前执行,在客户端和服务器端都会执行

  • render:组件在这里生成虚拟的 DOM 节点

  • componentDidMount:仅在第一次渲染后在客户端执行,组件真正在被装载以后(请求数据)

  • 运行中状态;一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和从新渲染。这些只发生在这个阶段。

  • componentWillReceiveProps:经过父组件修props改时候调用,当从父类接收到 props 而且在调用另外一个渲染器以前调用。

  • shouldComponentUpdate:(nextProps及nextState)组件接受到新属性或者新状态的时候(能够返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)

  • componentWillUpdate:在 DOM 中进行渲染以前调用,组件即将更新不能修改属性和状态

  • render:组件从新描绘

  • componentDidUpdate:在渲染发生后当即调用,组件已经更新

销毁阶段,这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除

componentWillUnmount:组件被卸载的时候调用。在此方法中执行任何须要的清理,通常在componentDidMount里面注册的事件须要在这里删除,例如使计时器无效、取消网络请求或清除在组件,清理内存空间

3二、React绑定this的三种方式

  • bind()
  • 构造函数内部绑定,在构造函数constructor内绑定this,好处是仅须要绑定一次,避免每次渲染时都要从新绑定,函数在别处复用时也无需再次绑定
  • 箭头函数 ##3三、 javascript对象和数组的深拷贝与浅拷贝 juejin.im/post/5d4830…

3四、Cookie在客户机上是如何存储的

Cookies就是服务器暂存放在你的电脑里的文本文件,好让服务器用来辨认你的计算机。当你在浏览网站的时候,Web服务器会先送一小小资料放在你的计算机上,Cookies 会帮你在网站上所打的文字或是一些选择都记录下来。当下次你再访问同一个网站,Web服务器会先看看有没有它上次留下的Cookies资料,有的话,就会依据Cookie里的内容来判断使用者,送出特定的网页内容给你。

3五、编写一个方法 去掉一个数组的重复元素

方法一:Array.from()方法能够将Set结构转化为数组结构

function unique(array) {
    return Array.from(new Set(array));
}
unique([1,2,3,3]);
复制代码

方法二:扩展运算符(…)内部使用for…of循环

let arr = [1,2,3,3];
let unique = [...new Set(arr)];
复制代码

方法三

function unique(arr){
    var isRepeated, result = [];
    for(var i=0; i<arr.length; i++){
        isRepeated = false;
        for(var j=0; j<result.length; j++){
            if(arr[i] === result[j]){
                isRepeated = true;
                break;
            }
        }
        if(!isRepeated){
            result.push(arr[i]);
        }
    }
    return result;
}
var arr = [1,2,3,4,3,2,1,2,3];
console.log(unique(arr)); 
复制代码

3六、7三、你如何组织本身的代码?是使用模块模式,仍是使用经典继承的方法?

对内:模块模式

对外:继承

3七、你如何优化本身的代码?

  • 代码重用

  • 避免全局变量(命名空间,封闭空间,模块化mvc..)

  • 拆分函数避免函数过于臃肿

  • 注释

你能解释一下JavaScript中的继承是如何工做的吗?

子构造函数中执行父构造函数,并用call\apply改变this 克隆父构造函数原型上的方法

3八、dom选择器优先级是什么,以及权重值计算(一道老问题了)

  • 1.行内样式 1000
  • 2.id 100
  • 3.类选择器、伪类选择器、属性选择器[type="text"] 10
  • 4.标签选择器、伪元素选择器(::first-line) 1
  • 5.通配符*、子选择器、相邻选择器 0

3九、react和vue比较来讲有什么区别

react总体是函数式的思想,把组件设计成纯组件,状态和逻辑经过参数传入,因此在react中,是单向数据流,推崇结合immutable来实现数据不可变。react在setState以后会从新走渲染的流程,若是shouldComponentUpdate返回的是true,就继续渲染,若是返回了false,就不会从新渲染,PureComponent就是重写了shouldComponentUpdate,而后在里面做了props和state的浅层对比。

而vue的思想是响应式的,也就是基因而数据可变的,经过对每个属性创建Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。

总之,react的性能优化须要手动去作,而vue的性能优化是自动的,可是vue的响应式机制也有问题,就是当state特别多的时候,Watcher也会不少,会致使卡顿,因此大型应用(状态特别多的)通常用react,更加可控。

40、水平垂直居中

// 第一种
#container{
    position:relative;
}
#center{
    width:100px;
    height:100px;
    position:absolute;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);
}
// 第二种
#container{
    position:relative;
}
#center{
    width:100px;
    height:100px;
    position:absolute;
    top:50%;
    left:50%;
    margin:-50px 0 0 -50px;
}
// 第三种
#container{
    position:relative;
}

#center{
    position:absolute;
    margin:auto;
    top:0;
    bottom:0;
    left:0;
    right:0;
}
// 第四种 flex
#container{
    display:flex;
    justify-content:center;
    align-items: center;
}
复制代码

4一、怎么判断两个对象相等

JSON.stringify(obj)==JSON.stringify(obj);//true
复制代码

4二、Vue router怎么实现跳转?

router-link 
router.go(1)
router.push('/')
复制代码

4三、Vue router 跳转和 location.href 有什么区别?

router 是 hash 改变
location.href 是页面跳转,刷新页面
复制代码

4四、重排和重绘,什么状况会触发重排和重绘

部分渲染树(或者整个渲染树)须要从新分析而且节点尺寸须要从新计算。这被称为重排。注意这里至少会有一次重排-初始化页面布局。 因为节点的几何属性发生改变或者因为样式发生改变,例如改变元素背景色时,屏幕上的部份内容须要更新。这样的更新被称为重绘。

  • 添加、删除、更新 DOM 节点
  • 经过 display: none 隐藏一个 DOM 节点-触发重排和重绘
  • 经过 visibility: hidden 隐藏一个 DOM
  • 节点-只触发重绘,由于没有几何变化
  • 移动或者给页面中的 DOM 节点添加动画
  • 添加一个样式表,调整样式属性
  • 用户行为,例如调整窗口大小,改变字号,或者滚动。

4五、git使用过程当中,若是你在开发着业务,忽然另外一个分支有一个bug要改,你怎么办

git stash       //将本次修改存到暂存区(紧急切换分支时)
git stash list  
git stash pop   //将全部暂存区的内容取出来
复制代码

4六、Git 经常使用命令

git add # 将工做区的修改提交到暂存区
git commit # 将暂存区的修改提交到当前分支
git reset # 回退到某一个版本
git stash # 保存某次修改
git pull # 从远程更新代码
git push # 将本地代码更新到远程分支上
git reflog # 查看历史命令
git status # 查看当前仓库的状态
git diff # 查看修改
git log # 查看提交历史
git revert # 回退某个修改
复制代码

4七、js加载位置区别优缺点

html文件是自上而下的执行方式,但引入的css和javascript的顺序有所不一样,css引入执行加载时,程序仍然往下执行,而执行到script脚本是则中断线程,待该script脚本执行结束以后程序才继续往下执行。 因此,大部分网上讨论是将script脚本放在body以后,那样dom的生成就不会由于长时间执行script脚本而延迟阻塞,加快了页面的加载速度。 但又不能将全部的script放在body以后,由于有一些页面的效果的实现,是须要预先动态的加载一些js脚本。因此这些脚本应该放在body以前。 其次,不能将须要访问dom元素的js放在body以前,由于此时尚未开始生成dom,因此在body以前的访问dom元素的js会出错,或者无效 script放置位置的原则“页面效果实现类的js应该放在body以前,动做,交互,事件驱动,须要访问dom属性的js均可以放在body以后

4七、vue-cli 工程经常使用的 npm 命令有哪些?

npm install
npm run dev
npm run build
安装模块;
-save-dev 是指将包信息添加到 package.json 里的 devDependencies节点,表示开发时依赖的包。
npm install --save-dev
-save 是指将包信息添加到 package.json 里的dependencies节点,表示发布时依赖的包。
npm install --save
复制代码

4八、vue中 keep-alive 组件的做用?

keep-alive是Vue.js的一个内置组件。它可以把不活动的组件实例保存在内存中,而不是直接将其销毁,它是一个抽象组件,不会被渲染到真实DOM中,也不会出如今父组件链中。 它提供了include与exclude两个属性,容许组件有条件地进行缓存。

4九、从浏览器地址栏输入url到显示页面的步骤

(1)域名解析 在浏览器地址栏输入URL,浏览器查看缓存,判断请求资源是否新鲜,浏览器解析URL获取协议,主机,端口,path。浏览器组装一个HTTP(GET)请求报文,浏览器获取主机ip地址(从缓存、hosts、路由、DNS解析等)

(2)TCP链接HTTP协议是使用TCP协议做为其传输层协议的,在拿到服务器的IP地址后,浏览器客户端会与服务器创建TCP链接。该过程包括三次握手

第一次握手:创建链接时,客户端向服务端发送请求报文 第二次握手:服务器收到请求报文后,如赞成链接,则向客户端发送确认报文 第三次握手,客户端收到服务器的确认后,再次向服务器给出确认报文,完成链接。

三次握手主要是为了防止已经失效的请求报文字段发送给服务器,浪费资源。 **(3)浏览器发送HTTP请求 浏览器构建http请求报文,并经过TCP协议传送到服务器的指定端口。http请求报文一共包括三个部分: 请求行:指定http请求的方法、url、http协议版本等 请求头:描述浏览器的相关信息,语言、编码等,是否包含缓存验证信息若是验证缓存新鲜,返回304 请求正文:当发送POST,PUT等请求时,一般须要向服务器传递数据。这些数据就储存在请求正文中。

(4)服务器处理HTTP请求 服务器处理http请求,并返回响应报文。响应报文包括三个部分: 状态码:略 响应头:包含了响应的相关信息,如日期等 响应正文:服务器返回给浏览器的文本信息,一般的html、js、css、图片等就包含在这一部分里面。

(4)浏览器接受相应

而后根据状况选择关闭TCP链接或者保留重用; 若是资源可缓存,进行缓存; 对响应进行解码(例如gzip压缩); 根据资源类型决定如何处理(假设资源为HTML文档);

(6)浏览器页面渲染 解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操做没有严格的前后顺序,如下分别解释 构建DOM树: 根据HTML规范将字符流解析为标记 词法分析将标记转换为对象并定义属性和规则 根据HTML标记关系将对象组成DOM树 解析过程当中遇到图片、样式表、js文件,启动下载 构建CSSOM树: 字符流转换为标记流 根据标记建立节点 节点建立CSSOM树 根据DOM树和CSSOM树构建渲染树: 从DOM树的根节点遍历全部可见节点,不可见节点包括:

- script,meta这样自己不可见的标签
- 被css隐藏的节点,如display: none
复制代码

对每个可见节点,找到恰当的CSSOM规则并应用 发布可视节点的内容和计算样式

js解析以下:

浏览器建立Document对象并解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loading HTML解析器遇到没有async和defer的script时,将他们添加到文档中,而后执行行内或外部脚本。这些脚本会同步执行,而且在脚本下载和执行时解析器会暂停。这样就能够用document.write()把文本插入到输入流中。同步脚本常常简单定义函数和注册事件处理程序,他们能够遍历和操做script和他们以前的文档内容 当解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,可是解析器不会停下来等它下载。异步脚本禁止使用document.write(),它们能够访问本身script和以前的文档元素 当文档完成解析,document.readState变成interactive 全部defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用document.write() 浏览器在Document对象上触发DOMContentLoaded事件 此时文档彻底解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入而且全部异步脚本完成载入和执行,document.readState变为complete,window触发load事件 显示页面(HTML解析过程当中会逐步显示页面)

5九、H5与iOS/Android的通讯方式(原生内嵌H5页面通讯模式浅析

引入JsBridge(安卓)或WebViewJavascriptBridge(iOS)库的方案,首先安卓、iOS、web前端三方要在一块儿定义好须要使用的接口的方法名及传递的参数,三方统一,定义好各个方法及传递的方式

60、redux中间件

redux中间件中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可让咱们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。常见的中间件:

  • redux-logger:提供日志输出
  • redux-thunk:处理异步操做
  • redux-promise:处理异步操做,actionCreator的返回值是promise

61.redux有什么缺点

  • 一个组件所须要的数据,必须由父组件传过来,而不能像flux中直接从store取。
  • 当一个组件相关数据更新时,即便父组件不须要用到这个组件,父组件仍是会从新render,可能会有效率影响,或者须要写复杂的shouldComponentUpdate进行判断。

6二、react组件的划分业务组件技术组件?

根据组件的职责一般把组件分为UI组件和容器组件。UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。二者经过React-Redux 提供connect方法联系起来。、

6三、为何虚拟dom会提升性能?

虚拟dom至关于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操做,从而提升性能。

具体实现步骤以下:用 JavaScript 对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变动的时候,从新构造一棵新的对象树。而后用新的树和旧的树进行比较,记录两棵树差别把2所记录的差别应用到步骤1所构建的真正的DOM树上,视图就更新了。

6四、react diff算法?

把树形结构按照层级分解,只比较同级元素。给列表结构的每一个单元添加惟一的key属性,方便比较。React 只会匹配相同class的component (这里面的class指的是组件的名字)合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每个事件循环结束, React 检查全部标记 dirty 的component从新绘制.选择性子树渲染。开发人员能够重写shouldComponentUpdate提升diff的性能。

6五、react性能优化方案

  • 重写shouldComponentUpdate来避免没必要要的dom操做。
  • 使用 production 版本的react.js。
  • 使用key来帮助React识别列表中全部子组件的最小变化。

6五、Vue的生命周期

相关文章
相关标签/搜索