Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

注意事项(基础)

1.js的基础数据类型:

基本数据类型:undefined,null,number,string,boolean

引用类型(都算作对象Object):Object,Array,Function

ES6新增了一种Symbol,这种类型的对象用不相等,即使创建的时候传入相同的值,可以解决属性名冲突的问题,作为标记

2.浏览器的内核

  • IE浏览器内核:Trident内核(Trident:三叉戟),俗称IE内核
  • Chrome浏览器内核:统称Chromium或chrome内核,以前是Webkit内核,现在是Blink内核
  • Firefox浏览器内核:Gecko(gecko:壁虎)内核,俗称Firefox内核
  • Safari浏览器内核:Webkit内核
  • Opera浏览器:最初是自己的Presto内核,后来是Webkit,现在是Blink内核

浏览器的内核分两部分:渲染引擎和JS引擎。

webkit内核是苹果公司的,blink内核是webkit的分支内核

3.BOM对象有哪些?

1.window对象:是JS最顶层对象,其他的BOM对象都是Window对象的属性

2.document对象:文档对象

3.location对象:浏览器当前的url信息

4.navigator对象:浏览器本身信息

5.screen对象:客户端屏幕信息

6.history对象:浏览器访问历史信息

4.em和rem的区别,

em相对于父元素,rem相对于根元素

5.在使用foreach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数

6.for in 和 for of的区别,

for in遍历的是数组的索引(即键名),而for of遍历的是数组的元素值

for of 遍历的是数组内的元素,不包括数组的原型属性method和索引name

for (var index in arr){

}

for in遍历数组的缺点:

1.index索引为字符串型数字,不能直接进行几何运算

2.遍历顺序有可能不是按照实际数组的内部顺序

3.使用for in会遍历数组所有的可枚举属性,包括原型。例如以下遍历数组的原型方法method和name属性

  var arr = [1,2,3,4,5,6,7,8,9];
        arr.name = "数组";

        Array.prototype.method = function(){
            console.log(this.length);
        } 
        for (var index in arr){
            console.log(arr[index]);
        }

4.for in适合遍历一个对象,for of遍历对象时会报错

        var obj = {name:'安妮',age:100,sex:'女'};

        Object.prototype.sayHello = function(){
            console.log('Hello');
        };

        Object.prototype.str = '原型中的属性';
        for(let index in obj){
            console.log(index);
        }

5.只要数据结构部署了Symbol.iteratoer属性,就可以使用for of循环

  • 数组
  • Map
  • Set
  • String
  • arguments对象
  • Nodelist对象,就是获取的dom列表集合

凡是部署了iterator接口的数据结构,也都可以使用扩展运算符和解构赋值等操作

  1. call,apply ,bind

call ,apply,bind都是改变this指向的方法,

call

fn.call(thisArg,arg1,arg2,…)

thisArg:在fn函数运行时指定的this值,需要注意的是,指定的this值并不一定是该函数执行时

真正的this值,

非严格模式:不传参数,或者第一个参数是null或undefined,this都指向window。

严格模式,第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined

apply

fn.apply(thisArg,[argsArray]),和call用法一样,第二个参数传递的是一个数组或者类数组对象

bind

bind语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE 6,7 8

fn.call(obj,1,2);  //改变fn中的this,并且把fn立即执行
fn.bind(obj,1,2); //改变fn中的this,fn并不执行

this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined

document.onclick = fn.call(obj,1,2);

bind 会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行

document.onclick = fn.bind(obj,1,2);

8.cookie sessionStorage localStorage区别

考察点:本地存储

cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递

cookie数据还有路径(path)的概念,可以限制,cookie只属于某个路径下

存储大小限制也不同,cookie数据不超过4K,同时因为每次http都会携带cookie,所以cookie只适合保存很小的数据,如会话标识

webStorage虽然也有存储大小的限制,但是比cookie大得多,可以达到5M或更大

数据的有效期不同:sessionStorage,仅在当前的浏览器窗口关闭有效,localStorage始终有效,

窗口或浏览器关闭也一直保存,因此用作持久数据,cookie,只在设置的cookie过期时间之前一直有效

,即使窗口和浏览器关闭,

作用域不同: sessionStorage:不在不同的浏览器窗口中共享,即使同一个页面;localStorage:在所有的同源窗口都是共享的,cookie:也是在所有的同源窗口中共享的

9.适配移动端

  • 流式布局:百分比布局实现在移动端的宽高自适应
  • 响应式布局:CSS3媒体查询
  • REM(弹性)布局:实现盒子的宽高自适应

最标准的viewport设置:

  • 视口宽度和设备保持一致

  • 视口的默认缩放比例1.0

  • 不允许用户自行缩放

  • 最大允许的缩放比例1.0

  • 最小允许的缩放比例1.0

流式布局:在css2时代就有,主要靠百分比进行排版,网页中主要的划分区域的尺寸使用百分数(搭配min,和max使用)

缺点:宽度使用百分比定义,但是高度和文字大小大多都是用px来固定,所以在大屏幕手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度,文字大小还是和原来一样

响应式布局:响应式布局的关键技术是CSS3中的媒体查询,监测设备屏幕大小,通过媒体查询有针对性的更改页面的布局

布局特点:每个屏幕的分辨率下面会有一个布局样式,即元素位置和大小都会变

优点:适应pc和移动端,如果足够耐心,效果完美

缺点:媒体查询是有限的,也可以枚举出来,只能适应主流的宽高。工作量大,设计需要多个版本

REM布局

rem的定义:rem相对于根元素设置字体大小,这就意味着,我们只需要根据自己的需求在根元素确定一个参考值

rem 与 em, px 的区别:

    px:像素,比较精确的单位,但是不好做响应式布局

    em:以父节点font-size大小为参考点,标准不统一,容易造成混乱

@media screen and (min-width: 640px) {

         html {
             font-size: 100px;
         }
    }

    @media screen and (max-width: 639px) and (min-width: 480px){
        html {
            font-size: 75px;
        }
    }

    @media screen and (max-width: 479px) and (min-width: 414px){
        html {
            font-size: 64.6875px;
        }
    }

    @media screen and (max-width: 413px) and (min-width: 375px){
        html {
            font-size: 58.59px;
        }
    }

    @media screen and (max-width: 374px) and (min-width: 360px){
        html {
            font-size: 56.25px;
        }
    }

    @media screen and (max-width: 359px){
        html {
            font-size: 50px;
        }
    }

10.数组去重

  1. set方法去重
    let arr = [1,0,0,2,9,8,3,1];
    function unique(arr) {
    return Array.from(new Set(arr))
    }
    console.log(unique(arr));
  2. 双重for循环在利用数组splice方法去重(ES5常用)
    var arr = [1, 5, 6, 0, 7, 3, 0, 5, 9,5,5];
    function unique(arr) {
    for (var i = 0, len = arr.length; i < len; i++) {
    for (var j = i + 1, len = arr.length; j < len; j++) {
    if (arr[i] === arr[j]) {
    arr.splice(j, 1);
    j–; // 每删除一个数j的值就减1
    len–; // j值减小时len也要相应减1(减少循环次数,节省性能)
    // console.log(j,len)

    }
    }
    }
    return arr;
    }
    console.log(unique(arr));
  3. 利用indexOf
    var arr =[1,-5,-4,0,-4,7,7,3];
    function unique(arr){
    var arr1 = []; // 新建一个数组来存放arr中的值
    for(var i=0,len=arr.length;i<len;i++){
    if(arr1.indexOf(arr[i]) === -1){
    arr1.push(arr[i]);
    }
    }
    return arr1;
    }
    console.log(unique(arr)); // 1, -5, -4, 0, 7, 3

4.使用数组sort()方法(相邻元素对比法)

  var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
            function Sort(arr){
                let newArr = arr.sort((a,b)=>a-b);
                let arr1 = [];
                console.log(newArr);

              for(let i=1;i<newArr.length;i++){
                if(newArr[i-1] !== newArr[i]){
                    arr1.push(newArr[i]);
                }
              }
              return arr1;
            }
         console.log(Sort(arr));

5.使用filter

    var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
            function arrfilter(arr){

                return arr.filter((item,index)=>{
                    return arr.indexOf(item) == index;
                })
            }
         console.log(arrfilter(arr));

6.使用includes()方法 (includes方法用来判断一个数组是否包含一个指定的值,如果是返回true,否则返回false)

[1, 2, 3].includes(2);     // true
[1, 2, 3].includes(4);     // false
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true

  var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
            function arrIncludes(arr){
                let newArr = [];

                for(let i=0;i<arr.length;i++){
                    if(!newArr.includes(arr[i])){
                        newArr.push(arr[i]);
                    }
                }
                return newArr;
            }
         console.log(arrIncludes(arr));

11.ES6新增

const(声明常量), let(声明变量)关键字;

map 和 set 数据类型;

模板字符串

; 对象数组解构赋值;

函数剩余参数;(…arg)

延展运算符;(…)

函数默认参数;fn(name=’zs’)

对象字面量的增强(属性名和属性值相同, 可缺省);

Promise 异步对象;

class 类的支持

1.当我们要对多个对象操作合并两个或者多个object的时候,我们可以使用Object.assign( );

Object.assign(target, ...sources)

  var obj = {};
            var obj1 = { a: 1, b: 2 }; 
            var obj2 = { c: 3, d: 4 }; 
            var obj3 = { e: 5, f: 6 };
            // for(let k in obj2){
            //     obj1[k] = obj2[k];
            // }

            // for(let k in obj3){
            //     obj1[k] = obj3[k];
            // }
            // console.log(obj1);

            Object.assign(obj,obj1,obj2,obj3);
            console.log(obj);

2.解构赋值

3.模板字符串

4.字符串新增方法

String.repeat()方法返回一个新字符串,表示原字符串重复n次

  var str = 'char';
      var repeat = str.repeat(5);
      console.log(repeat);

5.扩展运算符

ES5数组方法:

  • forEach( );
  • map()
  • filter
  • find
  • every
  • some
  • reduce

6.reduce方法

array.reduce(function(total,currentValue,currentIndex,arr),initialValue)

1.代替map做一些简单的运算

   var a = [10,20,30];
       var res = a.reduce(function(sum,item,index){
           console.log(sum);
           console.log('index',index);
           return sum + item;
       },1);
       console.log(res);

2.将一个对象数组中的某些属性的值抽出来,组成一个新的数组

    var colors = [
           {color:'pink'},
           {color:'red'},
           {color:'gray'}
       ]

       var Arr = colors.reduce(function(colorArr,item,index){
        colorArr.push(item.color);
        return colorArr;
       },[])

       console.log(Arr);

React面试题:

高阶组件:高阶组件接收React组件作为参数,并且返回一个新的React组件,高阶组件本身是一个函数,并不是一个组件

7.Promise.race() 和 Promise.all()

Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例

const p = Promise.all([p1, p2, p3]);

p的状态由p1、p2、p3决定,分成两种情况

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数

Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例

const p = Promise.race([p1, p2, p3]);

只要p1,p2, p3之中有一个实例率先改变状态,p的状态就跟着改变,那个率先改变的Promise实例的返回值,就传递给p的回调函数

promise.race 不是只执行一个promise,而是只返回最快的promise的结果。

12.防抖或是节流

限制函数的执行次数

1.防抖:通过setTimeout的方式,在一定的时间间隔内,将多次触发变成一次触发

2.节流; 减少一段时间的触发频率

    // 防抖是通过setTimeout的方式,在一段时间间隔内,将多次触发转为一次触发
    var btn = document.getElementById('btn');
    // btn.addEventListener('click',submit);
    btn.addEventListener('click', debounce(submit, 1000));

    function submit() {
        console.log('submit');
    }

    function debounce(fn, timout) {
        var t = null;
        return function () {
            if (t) {
                clearInterval(t);
            }
            t = setTimeout(() => {
                fn();
            }, timout)
        }
    }

   //节流是减少一段时间内的触发频率
var btn = document.getElementById('btn');

       btn.addEventListener('click',throttle(submit,2000))

       function submit(){
           console.log('submit');
       }


       function throttle(fn,timout){
        var begin = 0;
        return function(){
            var cur = new Date().getTime();
            if(cur -begin > timout){
                fn();
                begin = cur;
            }
        }
       }

13.闭包

1.javascript语言特殊之处,函数内部可以直接读取全局变量1.

 var n=999;
 function f1(){
   alert(n);
 }

 f1(); // 999

2.函数外部无法读取函数内的局部变量

 function f1(){
    var n=999;
  }

  alert(n); // error

3.函数内部声明变量的时候,一定要使用var命令,如果不用的话,你实际上就声明了一个全局变量

function f1(){
    n=999;
  }

  f1();

  alert(n); // 999

函数f2就被包含在函数f1内部,这时f1内部所有局部变量,对f2都是可见的,但是反过来不行

f2内部的局部变量,对f1是不可见的,这就是js语言的特点,被称为”链式作用域结构”。子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

  function f1(){

    var n=999;

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

既既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗! f2还函数,就是闭包

闭包:就是能够读取其他函数内部变量的函数

只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解为,定义在函数内部的函数

闭包的用途

闭包最大用处有两个:1.可以读取函数内部的变量

                                   2.另一个就是让这些变量始终保存在内存中

                    

 function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

result 实际就是闭包函数f2 :

  function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

在这段代码中,result实际上就是闭包f2函数,它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是”nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作

闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

14.箭头函数与普通函数的五个不同之处

    1. this不同,普通函数内部,this值(即执行上下文)是动态的,可以是window也可以是对象本身
      箭头函数没有定义自己的执行上下文,一般是父级的对象
  • 2.普通函数可以做构造函数,轻松构建对象,箭头函数不能用作构造函数
  • 3.普通函数的主体内部有arguments,箭头函数没有arguments .arguments是类数组对象,包换已调用函数的参数列表
  • 4.隐式return,箭头函数一条语句时可以省略return
  • 5.再类中使用箭头函数定义方法,箭头函数绑定this到类的实例

15.简单介绍下 react 中的 diff 算法?

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

16.什么是 Redux?

Redux 是一个状态管理工具, 不仅可以在 react 中使用, 也可在其他框 架中使用, 甚至可以脱离框架本身使用. redux 中有几个核心的组成部 分:

store 存储数据的对象,必须通过 createStore 方法来创建;

action 更新数据的规则, 必须有一个属性 state, 值必须是字符串;

reducer 更新数据的函数, 需要传入 state 状态数据和 action 更新规则. 在 react 中使用 redux 的时候, 一般会使用 react-redux 来简化使用步 骤

17.React 中如何操作 DOM?

在需要进行 dom 操作的标签上设置一个 ref 属性, 保证值不要重复, 后期在js 部分可以通过”this.refs.属性名”来获取标签的虚拟dom 对象

18.什么是高阶组件(HOC)?

函数的返回值是一个函数, 我们称之为高阶函数. 同理一个组件返回 值如果还是一个组件, 那么就称之为高阶组件. redux 中提供的 connect 就是一个高阶组件

19.react 性能优化可以使用哪个生命周期函数?

shouldComponentUpdate 这个方法用来判断是否需要调用 render 方 法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法, 可以极大的提高性能。

20.git 中有哪些常用的命令?

初始化仓库: git init

添加暂存区: git add 文件名

提交到本地仓库: git commit -m ‘注释‘

推送到远程仓库: git push 仓库地址 分支名称

拉取远程仓库代码: git pull

克隆仓库: git clone 仓库地址

创 建分支: git branch 分支名称

切 换分支: git checkout 分支名称

查 看分支: git branch

合并分支: git merge 分支名称

查 看日志: git log (git log –oneline)

查看所有日志: git reflog

版 本 回 退 : git reset –hard 版 本 号 (commit-id 可 以 通 过 git log –oneline 获取

21.git 和 svn 有什么不同?

git 是一个分布式仓库管理系统, 每个人本地都有一个本地仓库,svn 是 一个集中式仓库管理系统, 仓库只有一个. svn 一般需要服务端给每个 人分配账号和密码, git 是使用 ssh 公钥/秘钥对来区分不同程序员的

22.前端构建工具?

webpack , gulp , grunt

23.webpack 和 gulp 在进行代码合并的时候还有什么不同?

webpack 是基于 commonjs 模块化规范进行代码合并, 而 gulp 只是简 单的代码合并

const path=require('path'); 
const HtmlWebapckPlugin=require('html-webpack-plugin'); 
 const htmlPlugin=new HtmlWebapckPlugin({ 
     template:path.join( dirname,'src/index.html'),  
     filename:'index.html' 
 }); 

module.exports={ 
// 打包模式, 可值:development(开发模式),production(生产模式)  
mode:'development', 

// 插件配置节点

 plugins:[ 
     // html-webpack-plugin 作用:根据模板,在内存中创建一个 html 页面
     htmlPlugin
 ],

 resolve:{ 
     // 配置省略的文件后缀 
     extensions: ['.js', '.jsx', '.json'],
    // 配置根路径
    alias:{'@':path.join( dirname,'./src')}
 }

module:{
// 配置 loader  

rules:[ 
{
    test:/\.js|jsx$/, 
    use:'babel-loader',  
    exclude:/node_modules/ 
}, 

{ 
    test: /\.scss$/,  
    use: [ 'style-loader', 
          { 
              loader: 'css-loader', 
              options: { 
                  modules: {
                      localIdentName: '[name]-[local]-[hash:5]' 
                  } 
              } 
          }, 'sass-loader' ] }, 

{ 
    test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,  

    loader: 'url-loader', // 需 要 依 赖 file-loader

  options: { limit: 10000 }

 } 
] 
} 
}
}

24.在 jsx 中如果非要创建多个平行标签, 该如何处理?

  • 在 jsx 的最外层使用<> </>进行包裹;
  • 或者使用<React.Fragment> </React.Fragment>标签进行包裹; 两种方式本质是一样的,
    底层都是通过 document.createDocumentFragment()创建了一个虚拟 dom 标签

25.setState 什么时候是同步,什么时候是异步?

这里的“异步”不是说异步代码实现. 而是说 react 会先收集变更,然后 再进行统一的更新. setState 在原生事件和 setTimeout 中都是同步的. 在合成事件和钩子函数中是异步的. 在 setState 中, 会根据一个 isBatchingUpdates 判断是直接更新还是稍后更新, 它的默认值是 false. 但 是 React 在 调 用 事 件 处 理 函 数 之 前 会 先 调 用 batchedUpdates 这 个 函 数 , batchedUpdates 函 数 会 将 80 isBatchingUpdates 设置为 true. 因此, 由 react 控制的事件处理过程, 就变成了异步(批量更新).

26.什么是 ssr? 如何实现 ssr?

ssr 是全拼(server side rendering) ,中文意思, 服务端渲染, 让页面的渲 染在服务端完成, 生产环境必须部署nodeJS 的环境, 因为服务端渲染 必须借助 nodeJS 来完成. vue 中可以使用 nuxt 框架实现服务端渲染.

27.谈谈 async/await 的使用方式和场景

async 是用来修饰函数的声明, 使用async 修饰的函数会变成一个异步 函数. await 用来修饰函数的调用, 被 await 修饰的函数必须返回一个 promise 异步对象, 使用 await 修饰后, 就会将 promise 异步对象转换 成一个同步操作

28.你了解到的网站攻击方式有哪些?

常见的网站攻击方式有 xss(跨站脚本攻击), csrf(跨站请求伪造)

29.什么是页面的回流和重绘?

回流是指当页面的结构或者标签的尺寸发生变化的时候, 浏览器需 要对页面进行重排, 并重新渲染;

重绘是指当页面上的标签的外观(比如字体颜色,或背景颜色)发生改 变的时候, 浏览器需要重新对页面进行渲染. 所以回流一定会引起页面的重绘, 重绘不一定会引起回流.

要提高页面性能, 就要尽可能的减少页面的回流和重绘.

30.GET 和POST 的区别,何时使用 POST?

get 是将要传递的参数拼在 url 中进行传递,传递数据量少, 不安全 43 post 是将传递的参数放在请求体里传递, 携带数据量大, 相对安全. 要提交一些敏感数据(比如登录密码),上传文件时, 必须使用 post 请求

31.cookie, session,sessionStorage,localStorage

cookie和session都是用来跟踪浏览器用户身份的会话方式。

保持状态:cookie保存在浏览器端,session保存在服务器端

存储的大小:cookie:单个cookie保存的数据不能超过4kb;session大小没有限制。

存储内容:cookie只能保存字符串类型,以文本的方式;session通过类似与Hashtable的数据结构来保存,能支持任何类型的对象(session中可含有多个对象)

session的安全性大于cookie。

cookie断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。

    (2)保存上次登录的时间等信息。

    (3)保存上次查看的页面

    (4)浏览次数

32.for循环和forEach区别

  • 1.在固定长度或者长度不需要计算的时候for循环效率高于foreach,在不确定长度或者计算长度有损性能

的时候用foreach比较方便

  • 2.foreach适用于只是进行集合或数组遍历,for则是在较复杂的循环中效率更高
  • 3.如果对集合中的值进行修改,就要用for循环,foreach内部原理是iterator,但它不能像iterator一样可以人为控制,
  • 4.forEach相比普通的for循环的优势在于对稀疏数组的处理,会跳过数组中的空位
  • 5.foreach不能中断循环,for循环可以中断循环

33.Viewport(视口)的概念

pc端: viewport实际上等于浏览器窗口,拥有浏览器窗口的宽度和高度,document.documentElement.clientWidth获取。

移动端:

     布局视口:pc端布局视口等于浏览器窗口的宽度,移动端上,要让pc端浏览器设计的网站能够完全显示在移动端的小屏幕里,此时布局视口会远大于移动设备的屏幕,就会出现滚动条

        document.documentElement.clientWidth | document.body.clientWidth

     视觉视口(visual viewport):visual viewport的宽度指的是浏览器可视区域的宽度

     理想视口:布局视口的一个理想尺寸,只有当布局视口的尺寸等于设备屏幕的尺寸时,才是理想视口,

    js获取理想视口:window.screen.width

34.visibility:hidden和display:none 的区别

1.作用不同

    visibility:hidden ----将元素隐藏,但是在网页上的位置还是占着

    display:none ------将元素的显示设置为无,即再网页中不占任何的位置

2.使用后html元素有所不同

    visibility:hidden,使用后html元素仅仅再视觉上看不见(完全透明),而它所占据的空间位置,仍然存在,

也即是说它扔具有高度,宽度等属性值

display:none使用该属性后,html元素的宽度,高度等各种属性值都会"丢失"。

35.v-if和v-show的区别

v-if的原理是根据判断条件来动态的进行增删DOM元素,v-show是根据判断条件来动态显示和隐藏元素,

频繁的进行增删DOM操作会影响页面加载速度和性能。

36.浏览器的多线程

  • GUI渲染线程

  • JavaScript引擎线程

  • 事件触发线程

  • 定时触发器线程

  • 异步http请求线程
    GUI渲染线程:负责渲染浏览器页面html元素,解析html,css,构建DOM树和RenderObject树,布局和绘制等,当页面重绘重排时,该线程就会执行
    JavaScript引擎线程: 也可以成js内核,只要负责处理JavaScript脚本程序
    例如:V8引擎
    GUI渲染线程与引擎线程是互斥的。
    事件触发线程: 事件被触发时该线程会把事件添加到EventLoop(事件循环队列)的队尾,等待js引擎的处理
    定时触发器线程: setInterval与setTimeout所在线程, 通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待js引擎空闲后执行)
    异步http请求线程
    在XMLHttpRequest在连接后是通过浏览器新开一个线程请求。
    将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件
    ,将这个回调再放入事件队列中,再由JavaScript引擎执行

    37.宏任务(macrotask)和微任务(microtask)
    先运行微任务,后运行宏任务
    微任务的发起者是js引擎,事件有:Promise,process.nextTick(node.js),MutainObserver
    宏任务的发起者是(Node,浏览器), 事件有setTimeout, setInterval, script(整体代码),setImmediate(Node.js环境)
    console.log(‘script start’)

    async function async1() {
    await async2()
    console.log(‘async1 end’)
    }
    async function async2() {
    console.log(‘async2 end’)
    }
    async1()

    setTimeout(function() {
    console.log(‘setTimeout’)
    }, 0)

    new Promise(resolve => {
    console.log(‘Promise’)
    resolve()
    })
    .then(function() {
    console.log(‘promise1’)
    })
    .then(function() {
    console.log(‘promise2’)
    })

    console.log(‘script end’)
    打印顺序为:
    script start
    async2 end
    Promise
    script end
    async1 end
    promise1
    promise2
    setTimeout
    JS 运行机制为从上而下,首先打印script start,async/await 是Promise包装执行会立即执行async2()打印async2 end,把setTimeout加入宏任务队列但是不会立马执行,往下走,Promise创建属于同步任务此时打印Promise,并放入微任务队列中,再往下走直接打印script end,此时如果有微任务会优先执行微任务队列,微任务队列执行完毕再执行宏任务,async1 end 的打印是因为执行了Promise.then的方法,继续微任务输出promise1、promise2,当微任务队列为空,执行宏任务setTimeout,此时打印setTimeout。

  • js分同步任务和异步任务

  • 同步任务都在主线程上执行,行成一个执行栈

  • 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件

  • 一旦执行栈中的所有同步任务执行完毕(js引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中。开始执行

38.前端性能优化

1.减少http请求

2.使用服务端渲染

3.静态资源使用CDN

4.将css放在文件头部,JavaScript文件放在底部

5.使用字体图标代替图片图标

6.善用缓存	

7.图片使用懒加载





> 客户端渲染: 获取html文件,根据需要下载JavaScript文件,运行文件,生成DOM,再渲染
>
> 服务端渲染:服务端返回HTML文件,客户端只需解析HTML
>
> css执行会阻塞渲染,阻止js执行
>
> js加载和执行会阻塞HTML解析,阻止CSSOM构建

39浏览器渲染过程

    1.解析HTML生成DOM树

    2.解析CSS生成CSSOM规则树

    3.将DOM树与CSSOM规则树合并在一起生成渲染树

    4.遍历渲染树开始布局,计算每个节点的位置大小信息

    5.将渲染树每个节点绘制到屏幕

40.fetch请求和ajax请求的区别

1.ajax是XMLHttpRequest的一个实例,容易出现回调地狱

ajax请求:

//1.创建异步对象
var xhr = new XMLHttpRequest()
//2.设置请求行open(请求方式,请求url)
xhr.open("post","http://www.yangaoyuan.cn")
//3.设置请求头,get不需要设置,post需要设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//4.设置请求体,发送send()
xhr.send()   //get请求
xhr.send("username="+name)  //post请求

//5.让异步对象接收服务器的响应数据(数据成功返回并且响应状态为4)
xhr.onreadystatechange = function(){
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
}

2.fetch请求

    1.fetch是基于promise实现的,也可以结合async/await

    2.fetch请求默认不带cookie,需要设置需要设置fetch(URL,{credentials:’include’})。Credentials有三种参数:same-origin,include,*

    3.所有版本的IE均不支持原生Fetch

    4.fetch是window的一个方法



fetch(url,{
  method:'get'
}).then(function (response) {
    return response.json()   //执行成功第一步
}).then(function (returnedValue) {
    //执行成功的第二步
}).catch(function (err) {
    //中途的任何地方出错  都会在这里被捕获到
})

41.HTML几种定位方式

  1. static(默认定位方式)

  2. relative(相对定位方式)

  3. absolute(绝对定位)

  4. fixed(固定定位)

  5. sticky(粘性定位)
    父元素不能overflow:hidden或者overflow:auto属性。
    必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
    父元素的高度不能低于sticky元素的高度
    sticky元素仅在其父元素内生效

    以浏览器的可视窗口为参照点移动元素(固定定位特点)粘性定位占有原先的位置(相对定位特点)必须添加top.right.bottom,left其中一个才有效一般可跟页面滚动搭配使用

42.css隐藏元素的五种方法

1.opaticy:0;

2.visibility:hidden

3.display:none;

43清除浮动的几种方法

1.父级div overflow:hidden

2.父级div overflow:auto

3.6363结尾处添加div clear:both

44.async,await和Promise

1.执行async函数,返回的都是Promise

async函数如果返回一个普通值,将会包装成promise类型返回,

asynch函数如果返回的是一个promise类型,将直接返回

        async function test1(){
            return 1;
        }

        async function test2(){
            return Promise.resolve(2);
        }

        const result1 = test1();
        const result2 = test2();
        console.log('result1',result1)
        console.log('result2',result2);

2.promise.then成功的情况对应await

 async function test3(){
            const p3 = Promise.resolve(3);
            p3.then(data=>{
                console.log('data',data);
            })

            const data = await p3;
            console.log('data',data);
        }
        test3();

   async function test4(){
           const data4 = await 4;  //等价于 await Promise.resolve(4);
            console.log('data4',data4);
        }
        test4();

        async function test5(){
           const data5 = await test1();  //等价于 await Promise.resolve(4);
            console.log('data5',data5);
        }
        test5();
  1. //Promise.catch异常情况对应try…catch
    async function test6(){
    const p6 = Promise.reject(6);

    try{
    const data6 = await p6;
    console.log(‘data6’,data6);
    }catch(e){
    console.error(‘e’,e);
    }
    }
    test6();

路由中传参:

1..methods传参 /dest/${id}

2.params传参 :/id

3.query传参 ?/id

45new运算符做了什么?

  • 1.创建一个新对象(空对象)
  • 2.将新对象的_proto指向构造函数的原型
  • 3.将构造函数的this指向新对象
  • 4.根据返回值判断,是否返回新对象

评论