前端面试题

1.浏览器输入URL后发生了什么?

1:读取DNS缓存,如果DNS缓存中找到IP且在有效期内,就跳过查找IP步骤,直接访问该IP地址。

2:未找到IP,通过DNS将域名解析成IP。
3:TCP的3次握手
    第一次握手:客户端发送syn包到服务器
    第二次握手:服务器收到SYN包必须确认客户的SYN包,然后再发送给客户端SYN+ACK包
    第三次握手:客户端收到SYN+ACK包,然后发送给服务器ACK包
    完成三次握手,客户端与服务器开始连接数据。
4.发送http请求
5.服务器处理http请求,并返回http报文
6.浏览器解析渲染页面
7.断开连接,tcp的四次挥手
    第一次挥手:客户端发送给服务器,请求报文发送完毕,准备关闭
    第二次挥手:服务器发送给客户端,我接收完请求报文,准备关闭
    第三次挥手:服务器发送给客户端,我响应报文发送完毕,准备关闭
    第四次挥手:客户端发送给服务器,我响应报文接收完毕,准备关闭

2.重绘,重排,回流(同35)

⚠️ 网上的回流跟重排两种说法,其实都是一个意思。
⚠️ 回流/重排必定会引起重绘,但重绘不一定会引起回流/重排。回流/重绘会导致渲染树重新计算,开销比重绘大,所以尽量避免回流/重绘的产生。

1: 回流/重排的产生
    1> 页面进行首次渲染时,所有组件都要进行首次布局,这是开销最大的一次回流/重排。
    2> 浏览器窗口尺寸的改变
    3> 元素位置和尺寸发生改变
    4> 元素字体大小发生改变
    5> 激活css伪类(比如: hover )
    6> 设置style
2:  重绘的产生
    不影响布局,只影响外观的属性,比如visibility、outline、背景色等属性的改变

常见的避免方法:
    1> 样式集中改变,比如需要在js中改变某元素的宽高,可以用js给元素添加特定的clssName。

3.http

http1.0 请求方式: GET,POST,HEAD
http1.1 请求方式:OPTIONS,PUT,DELETE,TRACE,CONNECT

GET跟POST的区别:
    1.数据传输方式不同:GET通过URL传输数据,POST通过请求体传输。
    2.安全性不同:POST数据在请求体内,有一定的安全性,GET数据在URL中,通过历史记录缓存很容易就找到数据信息。
    3.数据类型不同:GET传输是ASCII字符串,POST没有限制。
    4.GET无害:刷新,后退等浏览器操作,GET请求是无害的,POST可能就要重复提交表单。
PUT与POST都是给服务器发送新增资源,有什么区别:
    1.PUT方法是幂等的,就是一次跟多次执行的结果是一样的,无副作用,而POST是非幂等的。
    2.通常情况下PUT指向一个具体的资源,而POST是指向的一个资源级。
    ⚠️ 「POST表示创建资源,PUT表示更新资源」这种说法是错误的,两个都能新增资源,区别在于幂等性

4.深拷贝和浅拷贝

1.关于js数据类型
    基本类型:number, boolean, string, undefined, null, symbol
    引用类型:object 如 array, function, object
2.深拷贝与浅拷贝的区别
    假设b复制了a,如果修改b导致a的值也被修改,则为浅拷贝;如果修改b的值,a保持原有值不变,则是深拷      贝。
    当a为引用类型时,b=a;其实b复制的是a的引用地址,而并非堆里面的值。
    深拷贝是拷贝对象各个层级的属性。

3.怎样实现深拷贝
    1.function objCopy = (obj) => {
        const newObj = Object.Array(obj) ? [] : {};
        if (obj && typeOf obj === 'object') {
            for (let key from obj) {
                if (Object.Array(obj[key])) {
                    newObj[key] = objCopy(obj[key])
                } else {
                    newObj[key] = obj[key]
                }
            }
        }
        return newObj;
    } 
    2.function objCopy = (obj) => {
        const _obj = JSON.Stringify(obj);
        return JSON.parse(_obj);
    }
    ⚠️只能拷贝数组或对象,不能处理函数
    3.lodash中的cloneDeep 

  4.浅拷贝实现方式              
    object.assign(), 扩展运算符
和原始数据是否指向同一对象第一层数据为基本数据类型原始数据中包含子对象
赋值改变会使原数据改变改变会使原数据改变
浅拷贝改变不会使原数据改变改变会使原数据改变
深拷贝改变不会使原数据改变改变不会使原数据改变

5.原型与原型链

原型:原型分为隐式跟显示,每个对象都有一个隐式原型,它指向自己的构造函数的显示原型。
原型链: 多个_proto_组成的集合成为原型链
    .所有实例的_proto_都指向他们构造函数的prototype
    .所有的prototype都是对象,自然它的_proto_指向Object的prototype
    .所有的构造函数的隐式原型指向的都是Function()的显示原型
    .object的隐式原型是null

6.js中什么是数据类型,什么是引用类型,具体是怎么储存的。

基本数据类型: 
    number,string,boolean, undefined, null, symbol
引用数据类型:
    object,array,date,function,regExp

存储方式:
    基本数据类型是存储在栈中,引用数据类型存储在堆中,栈中存储的是引用链接,注意堆内存不会自动释放,使用完对象需要手动将对象设置为null

7.闭包

闭包:
    有权访问另一个函数作用域中的变量,常见方式:函数内部嵌套另一个函数,内部函数可以访问外部函数的变量。
原理:
    外部函数调用时,会创建自己的作用域链,当执行完毕时,作用域链会被销毁,但内部函数还在引用这个活动对象,内部函数会将外部函数的活动对象添加到自己的作用域链中,直到内部函数执行完毕时,活动对象才会被销毁。
优点:
    防止变量污染,内部函数可以调用外部函数
缺点:
    占内存,使用不当容易引起内存泄漏

8.react与vue的区别

9.浏览器缓存机制

10.数组去重

1. 利用forEach循环数组,通过includes或indexOf判断是否在新数组,不在则插入新数组
function unique (arr) {
    const result = [arr[0]];
    arr.forEach(item => {
        if (!result.includes(item)) {
            result.push(item)
        }
    });
    return result;
}

2.利用Set结构不会有重复元素的原理,以及...运算符
function unique (arr) {
    return [...new Set(arr)];
}

3.利用Set结构不会有重复元素的原理,以及Array.from方法
function unique (arr) {
    return [Array.from(new Set(arr))];
}

4.利用sort排序,将重复的放在一起,然后使用splice删除重复元素
function unique (arr) {
    arr.sort((a,b) => a-b);
    for (let i = 0; i< arr.length; i++) {
        if (arr[i] == arr[i+1]) {
            arr.splice(i, 1);
            i--;
        }
    }
    return arr;
}
   

11.react刷新的几种方式

1.setState

2.外界props发生改变(redux数据改变)

3.强制更新  this.forceUpdete()
⚠️正确用法:<button onClick={() => this.forceUpdate()}
  错误写法: <button onClick={this.forceUpdate}>错误写法</button>

12.非递归优化

13.promise

promise是异步编程的一种解决方案,比传统的回调函数更加合理和更加强大。promise是使用链式操作,降低了编码难度,代码可读性明显增强。
promise有三种状态pending(进行中), rejected(已失败), fulfilled(已成功);
特点:
1.对象的状态不受外界的干扰,只有异步操作结果可以决定当前是哪个状态。
2.状态只会从pending--fulfilled或者pending--rejected;
3.状态一旦改变就不会再变

promise对象是一个构造函数,用来生成promise实例;promise构造函数接收一个函数作为参数,函数有两个参数(参数作用改变promise对象的状态),分别是resolve(进行中-成功),reject(进行中-失败);

promise 构造出来的实例有以下方法

1. then (实例状态发生改变时的回调函数,第一个参数是resolved状态的回调,第二个参数是rejected状态的回调函数。then方法返回的是一个新的promise实例)
2. catch (捕获错误,发生错误时的回调函数)
3. finally(不管promise最后状态如何,都会执行)
4. all(用于将多个promise实例包装成一个新的promise实例)
    如: const p = Promise.all([p1,p2,p3]);(p1,p2,p3应为promise实例) 
    p的状态分为两种:
    1⃣️:p1,p2,p3状态都为fulfilled,则p的状态为fulfilled,此时p1,p2,p3返回值组成一个数组,传递给p的回调函数;
    2⃣️:若p1,p2,p3中有一个的状态为rejected,则p的状态为rejected,此时第一个被rejected的实例的返回值会传递给p的回调函数;
5. race(将多个promise实例包装成一个新的promise实例。率先改变promise实例状态的返回值则传递给p的回调函数)


promise与async await的区别
1.promise通过catch来捕获错误, async await 是通过try catch 或者then方法来捕获错误
2.await关键字只能在async定义的函数内,await后面跟promise对象。
3.promise后面跟多个then方法,假如第一个then报错,后面的then不会执行,直接返回,直到catch方法

⚠️async await使用then方法捕获错误
window.onload=async () => {
    let res = await getData(3).then((res) => [null, res]).catch(err => [err,null])
}

14.map ,forEach, for, for in , for of ,filter, reduce的区别

1.for...in  遍历数组索引,对象的属性。使用fo...in遍历时,原型链上所有属性都会被访问。
  解决方法: 可以使用hasOwnProperty()来判断一个属性是否存在于实例中。
  如:const arr = ['a', 'b','c']
    arr.prototype.test = ['e', 'f'];
    for (let i in arr) {
     if (arr.haOwnProperty(i)){
       console.log(arr[i]); 
     }
    }
    // a,b,c
2.forEach 遍历数组,但是不能使用break,continue,return 语句
3.for 遍历数组
4.for of 遍历数组(数组中的value),也可以遍历字符串,支持Map和Set对象的遍历,可以正确响应break,continue,return。不能遍历一个普通对象,会报错。
5.map 遍历数组,有返回值,可以返回一个结果数组,遍历对象的话会报错,map只能循环数组或者对象数组。
6.filter: 过滤,当返回值为true时,才会返回当前处理的元素
7.reduce:接收一个函数作为累加器,数组中的每个值(从左到右开始缩减,最终计算为一个值)
  注:reduce对空数组不会执行回调函数,可用于数组去重,降维

15.如何优化首屏加载

16.判断数据类型的方法

1.typeof   
    eg: typeof ‘a’ === 'string' //true
    ⚠️ typeof null === 'object' //true  无法分辨是null还是object
2.instanceof 
    eg: new Number(1) instanceof Number //true
    ⚠️ : 123 instanceof Number // false  只能判断对象是否存在与目标对象的原型链中
3.contructor
    eg: console.log([123].contructor.name) //Array 
    ⚠️: null,undefined 没有contractor属性
4.object.prototype.toString.call()

延伸题:
1.instanceof原理
    function myInstanceof (L,R) {
        var RP = R.prototype;
        var LP = L._proto_;
        while(true) {
            if (LP === null) {
                return false
            }
            if (RP === LP) {
                return true;
            }
            LP = LP._proto_;
        }
      
    }
2.为什么typeof null 为object?
   因为在js中,对象的储存都是使用二进制,如果二进制前三位都是0 ,系统会判定为object类型,而null的二进制的前三位都是0.

17.手写call,apply, bind

实现思路:
call跟apply:
.判断是否是函数调用,若非函数调用抛异常
.通过新对象(context)来调用函数
.给context创建一个fn设置为需要调用的函数
.结束调用完之后删除fn
bind实现思路:
.判断是否是函数调用,若非函数调用抛异常
.返回函数
.判断函数的调用方式,是否是被new出来的
.new出来的话返回空对象,但是实例的__proto__指向_this的prototype
.完成函数柯里化 Array.prototype.slice.call()


1.手写call
Function.prototype.MyCall = (context){
    if (typeof this !== 'function') {
        throw new typeError('not a function');
    }
    context = context || window;
    context.fn = this;
    let args = Array.from(arguments),slice(1);
    let resule = context.fn(...args);
    delete context.fn;
    return result;
}
2.手写apply
Function.prototype.MyApply = (context) {
    if (typeof this !== 'function) {
        throw new TypeError('not a function');
    }
    context = context || window;
    context.fn = this;
    let result;
    if (arguments[1]) {
        result = context.fn(...arguments[1]);
    } else {
        resule = context.fn();
    }
    delete context.fn;
    return result;
}
3.手写bind
Function.prototype.MyBind = (context) {
    if (typeof this !== 'function') {
        throw new TypeError('not a function');
    }
    const _this = this;
    const args = Array.prototype.slice.call(arguments, 1);
    return function F () {
        //判断是不是new出来的
        if (this instanceof F) {
            return new _this(...args, ...argyments);
        } else {
            return _this.apply(context, args.concat(...arguments));
        }
    }
}

18.手写数组降维

1. function flatten (arr) {
    return [].concat(...arr.map(item => Array.isArray(item) ? flatten(item) : item))
}

2.function arrFn (arr) {
    const newArr = [];
    const loopFn = (arr) {
        arr.forEach(item => {
            if (Array.isArray(item)) {
                loopFn(item);
            } else {
                newArr.push(item)
            }
        })
    }
    looFn(arr);
    return newArr;
}

3.
    var arr1 = [1, 2, [3, 4]];
    arr1.flat(); 
    // [1, 2, 3, 4]
  
    var arr2 = [1, 2, [3, 4, [5, 6]]];
    arr2.flat();
    // [1, 2, 3, 4, [5, 6]]
  
    var arr3 = [1, 2, [3, 4, [5, 6]]];
    arr3.flat(2);
    // [1, 2, 3, 4, 5, 6]
  
    //使用 Infinity 作为深度,展开任意深度的嵌套数组
    arr3.flat(Infinity); 
    // [1, 2, 3, 4, 5, 6]

19.虚拟dom?

虚拟dom是一个js对象,通过对象的形式展示dom结构。
虚拟dom保存了真实dom的层次关系和一些基本属性,与真实的dom一一对应。
如果只更新虚拟dom,页面是不会重绘的。

优点: 保证性能下限
      无需手动操作dom
      跨平台
缺点:无法进行极致优化

虽然虚拟dom+合理的优化,足以应对绝大部分的性能需求,但是有一些性能要求极高的应用中,虚拟dom无法进行针对性的极致优化。
首次渲染大量dom时,由于多了一层虚拟dom的计算会比innerhtml插入慢

20.什么是MVVM?

MVVM是前端的架构模式,作用是为了让前端业务逻辑与html代码更加分离。它把每个页面分成了M(model数据模型),V(view 视图),VM(viewModel 视图模型);其中VM是M和V的调度者,M和V不直接关联,通过中间的VM,VM提供了双向绑定功能,V和M中其中一方改变,另一方也会随之改变。

21.flex布局

1.flex-direction 主轴方向  row columns row-reverse columns-reverse
2.flex-wrap  是否换行 nowarp wrap wrap-reverse
3.flex-flow 1,2属性的简写
4.justify-context 主轴上的对齐方式 flex-start flex-end space-between center
5.align-items 交叉轴上的对齐方式。flex-start flex-end stretch center
6.align-content 多根轴线的对齐方式

22.原型怎么实现继承


原型实现继承?
1.构造函数继承
写法:构造函数名字.call(当前对象, 属性, 属性, 属性。。。)
   function Person(name, age, sex, weight) {
      this.name = name;
      this.age = age;
    }
    Person.prototype.sayHi = function () {
      console.log("您好");
    };
    function Student(name,age) {
      //借用构造函数
      Person.call(this, name, age, sex, weight);
      this.score = score;
    }
    var stu1 = new Student("小明",10);
    console.log(stu1.name, stu1.age);//输出 小明 10
 
    var stu2 = new Student("小红",20,"女","20kg","120");
    console.log(stu2.name, stu2.age);//输出 小红 20
2.原型方法实现
写法:通过改变子类的原型(prototype)指向,指向父类即可。
3.组合继承
组合继承是 原型方法实现继承和借用构造函数实现继承的结合
4.拷贝继承
拷贝继承是把一个对象中的属性或者方法直接复制到另一个对象中。

23.react-ssr

1.什么是ssr?
在服务端渲染框架中所创建的虚拟dom

2.为什么要实现服务端渲染?
增加首屏加载速度,解决白屏问题,可以直接渲染页面,利于seo(搜索引擎)优化

24.js本地缓存方式

1.cookie
cookie中存储的数据,如果没有设置有效期的话,浏览器关闭就会被清空。
一般同源是4kb。
浏览器与服务器之间来回传递。
所有同源窗口都是共享的。

2.localStorage
需要手动清除,否则会一直存在。
只能存储字符串。
大小5MB。
尽在本地
所有同源窗口都有共享

3.sessionStorage
窗口关闭,信息就会丢失。
大小5MB。
仅在本地。
不在不同的浏览器窗口共享,即使是同一页面。

25.react-router的路由有几种模式?

1.browseRouter: 浏览器的路由方式,也就是开发中的最常用的方式。
2.hashRouter: 在路径前加入#号成为一个Hash值,Hash模式好处是,再也不会因为我们刷新页面而找不到我们对应的路径。
3.memoryRouter: 不存储history,所有路由过程保存内存里,不能进行前进后退,因为地址栏没有发生变化
4.nativeRouter: 经常配合ReactNative 使用,多用于移动端。
5.staticRouter: 设置静态页面路由,需要在后台服务器配合设置,比如设置服务端渲染时使用。

26.js中常用的设计模式

1.工厂模式✳️
2.单例模式✳️
3. 原型模式
4.适配器模式
5.代理模式
6.策略模式
7.迭代器模式
8.发布-订阅模式 ✳️
9.命令模式
10.状态模式

27.css权重如何计算?

1:  !import 不推荐使用;
2:  内联样式。权重值为1000;
3:  ID选择器。 权重为100;
3:  类名,属性选择器,伪类。  权重为10;
4:  标签, 伪元素。权重值为1;
其它: 通配符, 子选择器 , 相邻选择器 如: *, >, +  权值为0

28: DOCTYPE的作用?

作用是告诉浏览器以哪种模式去解析html文档。
有两种模式:标准模式(<!DOCTYPE html>)与怪异模式
标准模式:以浏览器最高标准呈现
怪异模式: 页面以比较宽松向后兼容来显示

29.一些常用的meta标签有哪些?

<!-- 关键字,搜所引擎 SEO -->
<meta http-equiv="keywords" content="关键字1,关键字2,...">

<meta name='author' content='开源技术团队' />//网页作者

<meta name='viewport' content='width=device-width,initical-scale=1.0,maxnum-scale=1.0,use-scale=no' /> //移动端常用视口

<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1' /> //使用浏览器版本

<!-- 页面描述 -->
<meta http-equiv="description" content="网页描述">

<!-- 清除缓存(再访问这个网站要重新下载!) -->
<meta http-equiv="cache-control" content="no-cache, must-revalidate">

<!-- 不缓存 -->
<meta http-equiv="cache-control" content="no-cache" />

30.display: none与visibility:hidden 的区别?

display: none: 
  1.非继承属性, 子节点会随着父节点消失,改变子节点属性也不会显示
  2. 隐藏后的元素无法点击,占据的空间消失
visibility: hidden: 
  1.继承属性,子节点通过设置visibility: visible 可以显示
  2.隐藏元素所占据的空间还保留

31.null与undefined的区别?

null:表示控对象,转为数值为0
undefined:表示缺少值 ,转为数值为NaN
1:变量声明,没有赋值,默认为undefined
2:调用函数,应该提供的参数没有提供,默认为undefined
3:对象没有赋值的属性,默认值为undefined
4:函数没有返回值

32.什么叫栅格化?

将网页一行等比例划分,比如一行划分为12等份,然后在每个格子中开发,这就是栅格化

33.React.child.map 与map的区别?

React.child.map: 可以处理未知数据类型,即使是undefined与null,此方法将返回null或undefined
map: 只能处理数组,不是数组会报错

34.作用域与作用域链?

1⃣️:作用域分为: 全局作用域,函数作用域,块级作用域
1: 全局作用域
     全局作用域是指在最外层函数内外定义的变量拥有全局作用域,或者直接赋值的变量会自定声明为全局作用域,所有window对象的属性都拥有全局作用域

2:函数作用域
    在函数内部声明的变量
3:块级作用域
    使用es6新增的let或const声明可以声明块级作用域,可以在函数中创建也可以在代码块中创建(由{}包裹的代码片段)。
    let跟const声明的变量不会进行变量提升,也不可以重复声明。
2⃣️:作用域链?
    在当前作用域中查找所需变量,但是当前作用域没有该变量,就会去父级作用域查找,依次向上级作用域查找,直到访问到window对象就被终止,这一层层关系就是作用域链。

35:回流与重绘(同2)

回流: 当render tree中的一部分(或全部),因为元素的尺寸,布局,隐藏等改变,而需要重新构建。
重绘: 当render tree中一些元素需要更新属性,而这些属性只影响外观,不影响布局,则称为重绘。

回流: 
    添加或删除可见的dom元素
    元素位置改变
    元素尺寸改变(margin, padding, width, height, border)
    内容的改变(文本改变,或者图片大小改变)
    页面渲染初始化
    浏览器窗口尺寸改变(resize事件发生)
重绘: 
    元素的属性或样式发生变化
    (color, background-color, border-radius, border-shadow)

如何减少回流跟重绘?
    css:
        使用transform来代替top
        避免使用table布局
        尽量避免多层嵌套,结构尽量扁平化。
        使用visibility,opacity 代替display:none
    js:
        给dom设置css避免一行一行的设置(如:el.style.width = '40px', el.style.color = 'red')
        涉及到批量修改dom时,使用先将dom元素的display设置为none,然后修改,最后将其重新展示

36.类数组与数组的区别

类数组是一个对象,有length属性,但是不能使用数组的方法。
常见的类数组有: 函数的arguments, DOM方法的返回结果
类数组转化为数组的方法:
    [...arguments] (扩展运算符)
    Array.from(arguments)
    [].slice.call(arguments)

37.React.component 与React.pureComponent的区别?

pureComponent时一个纯组件,可以用来优化React程序,减少render执行次数。
pureComponent会自动执行shouldComponentUpdate。
pureComponent的shouldComponentUpdate进行的是浅比较,也就是说引用类型只会比较是否为同一地址。

38.受控组件与非受控组件

受控组件:是指在使用表单收集用户输入时,绑定onChange事件,状态发生改变就会触发onChange事件,更新组件的state。
非受控组件:表单的数据交由DOM节点来控制。

39.js获取url参数

1.返回需要的参数值
function getUrlvalue (type) {
    var query = window.location.search.subString(1);
    var params = query.split('&');
    for (let i = 0; i< params.length; i++) {
        const values = params[i].split('=');
        if (values[0] == type) {
            return values[1];
        }    
    }
    return false; 
}
2.参数以对象的形式返回
function getUrlParams (url) {
    let params = url.split('?');
    let keyValue = params.split('&');
    let obj = {};
    for (let i = 0; i< keyValue.length; i++) {
        let item = kayValue('=');
        let key = item[0];
        let value = item[1];
        obj[key] = value;
    }
    return obj;
}

40.redux的工作流程

redux包含三要素: store, action , reducer
store: 就是数据保存的地方,可以把它看成一个容器,整个应用只有一个store。同时store还具有将action与reducer联系在一起的作用。
action: 就是一普通对象,其中type属性是必须的,用来表示action的名称,type一般定义为普通的字符串常量。
reducer: 本质上是一个函数,它接受当前的state和收到的action作为参数并返回一个新的state。

用户发出action,发出方式用到了dispatch。
然后store自动调用reducer,并传入两个参数,当前state与收到的action,reducer 会返回新的state。
state一旦变化,store就会自动调用监听函数,触发重渲染。

41.css超出隐藏

单行:

width: 300px;
overflow: hidden;//溢出隐藏
text-overflow: ellipsis;//溢出用省略号
white-space: noWrap; //段落中的文字不换行


多行:

width: 300px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;//弹性伸缩盒子模型
-webkit-box-orient: vertical;//伸缩盒子子元素从上到下垂直排列
-webkit-line-clamp: 3; //显示的行数

42.webpack中loader与plugin的区别

1.loader只专注于转化文件这一领域,完成压缩,打包,语言翻译
而plugin不仅只是局限在打包,资源的加载上,还可以打包优化和压缩重新定义环境变量。
2.loader运行在打包文件之前,plugin在整个编译周期都起作用。

43.css-loader与style-loader区别

css-loader: 找出css中的依赖,压缩资源。
style-loader: 通过一个js脚本创建一个style标签,然后将css-loader解析后的内容挂载到html

44.setState注意事项

1.不能直接设置this.state的值,需要使用setState;this.state不会触发render
2.调用setState后,可能不会立即生效。
3.在一些原生事件如:addEventListener,setTimeout,setInterval 事件中是可以取到最新值,
在react的生命周期与合成时间中是异步,不能取到最新的值

45. 函数声明与函数表达式的区别

函数声明的例子:
function name () {}可以在声明之前调用

函数表达式的例子: //不可以在表达式赋值完成前调用
var name = function () {}

var name = function test() {}

46.宏任务与微任务

微任务: 1.发起者 JS引擎 2.事件:promise等 3,运行:先运行

宏任务: 
1.发起者:宿主(node, 浏览器)
2.事件:script(整体代码,setTimeout, setInterval)
3.后运行


先script整体代码执行,遇到宏任务放置宏任务队列,微任务放置微任务队列,
执行结束后,执行全部的微任务,当执行微任务时遇到微任务就放置微任务队列末尾,
依次执行,直至微任务队列清空。再执行下一个宏任务,这就是eventLoop

例子:

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
//1,7,6,8,2,4,3,5,9,11,10,12

47.隐式类型转换,显示类型转换

显示类型转换: Number, parseInt, parseFloat, Boolean(), String

隐式类型转换: 主要发生在+,-,*,/以及==,>,<这些运算符之间。
而这些运算符只能操作基本类型,在运算前,先将两边的值转换为基本数据类型。
1>: +运算符
    1.两边有一个string,两边都被隐式转换为字符串
    2.其它情况,两边都被转换为number
    var a = '5';
    console.log(+a+5) //10
    console.log(a+5) // 55
    console.log(+'5'+5) //10
2>: < 和 >比较符
    如果两边都是字符,则比较顺序,其他情况,转化为数字再比较
3>: ==操作符
    1.类型相同,直接比较两者是否相等
    2.类型不同,看是否比较的是undefined与null,是直接返回true
    3.两者类型是否为string与number,是的话将字符串转为number
    4.一方为boolean,把boolean转换为number
    5.一方为object,且另一方为string,number,symbol,则把object转换为原始类型

48.数组有哪些原始方法?

1.数组转化为字符串
    toString, join
2.数组尾部操作方法
    push: 尾部插入
    pop: 尾部删除
3.数组首部操作方法
    shift: 首部删除
    unshift: 首部插入
4.数组连接
    concat //返回拼接好的数组,不影响原数组
5.数组插入/删除方法
    splice: splice(开始位置,删除个数,向数组添加的新值)
6.数组截取方法
    slice: slice(start,end)
7.数组排序
    sort:可以传入一个函数,传入前后两个值,如果返回为正数,则交换两个参数的位置,影响原数组
    数字排序(数字和升序):
        var points = [40,100,1,5,25,10];
        points.sort(function(a,b){return a-b});
    数字排序(数字和降序):
        var points = [40,100,1,5,25,10];
        points.sort(function(a,b){return b-a});
8.反转数组
    reverse: 将改变原数组

49.前端浏览器的兼容问题

1.浏览器种类及内核
    IE浏览器: Trident内核,也称为IE内核
    Chrome浏览器: webkit内核,现在是Blink内核
    Firefox浏览器:Firefox内核
    safari浏览器: webkit内核
    OperaL浏览器:最初Presto内核, 从webkit到Blink内核
    360浏览器:IE+Chrome双内核
    猎豹浏览器:IE+Chrome双内核
    百度浏览器: IE+Chrome双内核
    qq浏览器: Trident(兼容模式)+webkit(高速模式)
2.常见的兼容模式
    不同浏览器的标签默认的margin和padding不同
    图片默认有边距
    边距重叠问题:两个或多个块级盒子的垂直相邻边距会重叠 (都为正值则取最大,一正一负则取两值相加,都是负值则取绝对值最大的那个值)
    cursor: hand 显示手型,在Safari上不支持。统一使用cursor:pointer
    事件绑定方式:
        IE:dom.attachEvent
        其他浏览器:dom.addEventListener
            addEventListener的语法:
                document.addEventListener(event, function, useCapture);
                    event: 事件名称的字符串
                    function: 事件发生后的需执行的操作
                    useCapture: 可选(布尔值)指定事件在捕获阶段执行还是冒泡阶段执行
                        true:捕获阶段  false: 冒泡阶段 (默认值)

                    阻止事件冒泡和事件捕获: event.stopPropagation();

3.浏览器css兼容前缀
    -o-transform: rote(7deg)  //opera
    -moz-transform: rote(7deg) //Firefox
    -ms-transform: rote(7deg) //IE
    -webkit-transform: rote(7deg) //chrome
4.判断是否为IE浏览器
    function isIE() {
        if (!!window.ActiveXObject || 'ActiveXObject' in window) {
            return true;
        } else {
            return false;
        }
    }

50.css3新特性

1.新增选择器: nth-child(n), first-child, last-child
2.弹性盒模型: display: flex;
3.媒体查询: @media
4.颜色透明度:rgba
5.圆角:border-radius
6.阴影:box-shadow
7.背景效果:background-size
8.转换: transform transition

51.html5语义化标签

1.语义化标签
    <header>, <nav>, <footer>, <artical>, <main>, <aside>, <section>
2.音频视频标签
    视频:<video>
    音频: <audio>
3.canvas绘图
    初始:宽300px  高150px
4.SVG绘图

5.webSocket
    websocket创建和常用的属性方法
    var websocket = new websocket(url);
    websocket.onopen=function() {//在链接建立时触发}
    websocket.onclose=function() {//链接关闭时触发}
    websocket.onmessage=function(){//客户端接受服务器数据时}
    websocket.send('发送数据')

6.增强型表单
    类型             描述
    color            主要用于选取颜色
    date             一个日期选择器选择一个日期
    email            包含e-mail地址的输入域
    month            选择一个月份
    number            数值的输入框
    tel                定义输入电话号码
7.新增表单属性
    placehoder    输入前显示在输入框内,用户输入消失
    required      要求输入框不能空
    min和max      设置元素最小值与最大值
    autofocus     自动获取焦点
    multiple      input可选择多个值

canvas与上svg的区别
1.svg绘制出来的每一个图形的元素都是独立的dom节点,能够方便的绑定事件或用来修改,canvas输出的是一整张画布。
2.svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小。不会失真和锯齿。而canvas输出标量画布,像一张图片一样,放大会失真或者锯齿。

52.响应式开发适配的机型

响应式:基于一套代码,开发一个app能够兼容多尺寸,多终端设备的显示,能够动态调整页面的布局及容器的布局。

设备划分            尺寸区间                宽度设置
超小屏(手机)        <768px                100%
小屏幕(平板)        >=768~992px            750px
中等屏幕(桌面显示器) >=992px~1200px         970px
宽屏设备(大桌面显示器)  >=1200px            1170px

53.微前端

微前端就是将不同的功能按照不同的维度拆分成多个应用,通过主应用加载这些子应用。
微前端的核心在于拆,拆完后再合。

54.原声事件与React合成事件的区别

1.react合成事件是绑定在document上的,原生事件是绑定在dom上。
相对绑定的地方,dom事件要优先于document上的事件执行

2.原生事件阻止事件冒泡:event.stopPropagation
react事件阻止事件冒泡:event.preventDefault

3.阻止原生事件的冒泡后,会阻止合成事件之行
   

55.等式是否成立

0.1+0.2 == 0.3 // false 
    怎么使等式成立 0.1跟0.2分别乘以100再相加,然后再除以100

{} == {} //false 
    虽然值一样,但栈中保存的实际上是指向堆中对象的一个指针,值一样,但是是独立的两个对象占两份内存空间

1==true //true 
    在==的隐式转换中,把两边都进行了number转换

undefined === undefined //true   

null === null // true

null == undefined //true

NaN == NaN //false


56.['1', '2', '3'].map(parseInt)结果

结果为[1, NaN, NaN]

parseInt函数接收两个参数parseInt(string,radix)
string: 需要被解析的字符串
radix: 要解析的数字的基数 该值介于2~36

['1', '2', '3'].map(parseInt) 即
parseInt('1', 0)  parseInt会根据十进制解析,结果为1
parseInt('2', 1)  parseInt超出区间范围 NaN
parseInt('3', 2)  parseInt用2进行解析,应以0和1开头 NaN

57.HTTP状态码

菜鸟教程

58.

Math.ceil() 执行向上舍入    ceil英文意思天花板,所以向上取
Math.floor() 执行向下舍入    floor英文意思地板,所以向下取
Math.round() 执行标准舍入,四舍五入
    如果小数为0.5,则四舍五入到相邻的正无穷方向上的整数
    比如: Math.round(4.5) //5    Math.round(-4.5) // -4

59.构造函数与class的区别

1.类的形式
    可以在class内部同时定义普通对象的属性与方法,定义构造函数对象上的方法,定义原型上的方法属性。
值得注意的是通过静态关键字只能在构造函数对象上添加方法,也就是说只能定义静态的方法,不能定义静态的属性
2.构造函数的形式
    在构造函数内部只能定义普通对象上的方法和属性
    静态方法也就是构造函数对象上的方法,只能通过显示的追加
    原型对象上面的方法和属性也需要显示追加

60.创建对象的方式

1.工厂模式
    例:function createPerson (name, age, job) {
            let obj = new Object();
            o.name = name;
            o.age = age;
            o.job = job;
            o.sayNam = function() {
                console.log(this.name)
            }
        
        }
        let person = createPerson('lhh', '14', 'IT');
2.构造函数模式
    例:function Person (name, age, job) {
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayNam = function() {
                console.log(this.name)
            }
        }
        let person1 = new Person('lhh', '14', 'IT');
        let person2 = new Person('lhh', '15', 'IT');

 61.原型实现继承的方式

1.原型链继承
    例:function Dog() {
            this.dog = 'dog';
        }
        function Cat() {
            this.cat = 'cat';
        }
        cat.prototype = new Dog();
        let newCat = new Cat();
2.借用构造函数 (缺点:继承不到父类原型上的方法和属性)
    例:function Super (name) {this.name = name}
        function Suber () {
            Super.call(this, 'kies');
            this.age = '27';
        }
        let oo = new Suber();
        console.log(oo.name); //kirs
3.组合继承
    使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。这样使得定义在原型上的方法实现函数复用,又能够保证每个实例都有自己的属性

62.JS回收机制

JS垃圾回收机制是为了防止内存泄漏的,(已经不需要的某一块内存还一直存在着),垃圾回收机制就是不停歇的寻找这些不再使用的变量,并释放掉它所指向的内存

垃圾回收方法?
 标记清除法:当声明变量的时候,垃圾回收器将该变量进行标记,当该变量离开环境时,将其再度标记,随之进行删除

63.E charts开发中遇到的问题

1.Echarts解决双Y轴,左右刻度不一致
解决办法:
    1:求出一组数据的最大值,这里设置最大值为10的倍数
    2.根据最大值,设置interval
    function calMax (arr) {
        var max = arr[0];
        for(let i = 0; i< arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
        }
        var maxInt = Math.ceil(max/10); //向上取整
        var maxVal = maxInt*10; // 最终设置的最大值
        return maxVal;
    }
    var appRegum = [10,20,30,40,50,....,130];
    var activeNum = [1.1,2.2,3.3,4.4,5.5,...,30.5];
    var maxAppRegum = calMax(appRegum); //注册Y轴值
    var maxActive = calMax(activeNum); //活跃Y轴值
    var interval_left = maxAppRegum / 5; //左轴间隔
    var interval_right = maxActive / 5; //右轴间隔
    option = {
        ...,
        yAxis: [
            {
                type: 'value',
                name: '注册',
                min: 0,
                max: maxAppRegum,
                invertal: interval_left,
                splitNumber: 5,
            },
            {
                type: 'value',
                name: '活跃',
                min: 0,
                max: maxActive,
                invertal: interval_right,
                splitNumber: 5,
            }
        ]
    }
2.echarts的父级要有宽高,否则就显示不出来

64.盒模型分为什么

标准盒模型: width = content

怪异盒模型: width = content + padding + border

box-sizing: border-box; //转换为怪异盒模型

65. 清除浮动的方式

1.overflow: hidden;
2.给父级添加伪元素
    .clear::after {
        display: block; // clear 属性只有块级元素才有效,而::after等伪元素默认是内联
        content: '';
        clear: both;
    }

66.css布局的几种方式

1>flex布局
2>float 布局
3>响应式布局
4>文档流布局

67.this指向

非严格模式下this指向默认的window,严格模式下,this指向undefined

普通函数调用:this指向全局对象window
对象函数调用:谁调用this就指向谁
对象函数调用:this指向实例对象
箭头函数: 
1.箭头函数的this是在定义函数的时候绑定的,继承父级执行上下文中的this(注意:简单对象是没有执行上下文的)。
2.可以解决匿名函数和定时器的this指向问题,不用用变量that存储this

70.懒加载

懒加载:优先加载可视区域的内容,其他部分等进入了可视区域在加载。

原理:先把img的src指向空或者一个小图片,图片的真实地址存在img的一个自定义属性里,<img src=''  data-src='http://.......red.jpg' />,等到此图片出现在可视区域内,获取img元素,把data-src赋值给src.这样防止页面一次性向服务器响应大量请求,导致服务器响应慢,页面卡顿或崩溃等问题。

判断图片是否出现在可视区域:
img的offsetTop < document.documentElement.clientHeight + document.documentElement.scrollTop

71.sass使用的哪些功能

1.$声明变量
2.&引用父元素 如: a { &:hover {color: red;} }
3.可嵌套
4.计算功能 +,-,*, /
5.继承
    如: .a1 {color: red;}  .a2 {@extend .a; font-size: 12px}
6.混合 用来分担那些需要在页面中复用的css声明,开发人员可以通过MIXIN传递变量参数,让代码更加灵活。
如: 
    @mixin boreder-radius ($value) {
        border-radius: $value;
        -webkit-border-radius: $value;
        -o-border-radius: $value;
        -ms-border-radius: $value;
        -moz-border-radius: $value;
    }
    .box {@include border-radius(5px); }
如: @mimin banner {
        width: 100%;
        position: relative;
    }
    .lead-banner {
        @include banner;
    }

72.ref的3种用法

1.字符串 (dom节点上使用通过this.refs[refname]来引用真实的dom节点)
    <input ref='inputRef' /> //this.refs.inputRef
2.回调函数
    <input ref={(input) => {this.textInput = input}} />
3.React.createRef()
    在react 16.3版本后,使用此方法创建ref。将其赋值给一个变量,通过ref挂载到dom节点或者组件上,该ref的current属性能拿到dom节点或组件实例。
    class Child extends React.component {
        constructor(props) {
            super(props);
            this.myRef = React.createRef();
        }
        componentDidMount() {
            console.log(this.myRef.current)
        } 
        render(){
            return <input ref={this.myRef} />
        }
    }


    

74.var a=b=5;

1.解析: var a=b; b=5;
2.然后,b=5前面没有var,相当于声明为全局变量
3.相当于:
    var b;
    (function...{var a=b; b=5;})();
    console.log(b) //5
    console.log(a) //a is not defined

75.link与@import的区别

1.link是标签 @import 是css提供的一种方式
2.加载顺序差别,页面加载link会同时加载,@import 会等页面全部被下载再加载
3.兼容性。@import会有兼容性问题,link没有

76.为什么用transform中的translate,不用定位实现移动

性能问题,定位在手机上会出现卡顿。
使用绝对定位会触发回流和重绘,造成页面卡顿,translate不会触发回流或重绘

77.扩展运算符使用场景

1.数组和对象的浅拷贝
2.字符串转为数组
3.伪数组转换为数组
4.合并数组
5.函数形参

78.什么情况会造成内存泄漏

1.意外的全局变量引起内存泄漏。(直接赋值的变量)
2.闭包引起的内存泄漏
3.没有清理的dom元素引用
4.被遗忘的定时器

79.React性能优化方案

1.给按钮绑定事件的时候,最好在constructor内进行绑定如:
    class App extends React.Component {
        constructor (props) {
            super(props)
            this.onClick=this.onClick.bind(this);
        }
        render(){
            return(<button onClick={this.onClick}>按钮</button>)
        }
    }
2.当父组件变化时,而且子组件并没有变化,此时组件也会同时render
    可以使用shouldComponentUpdate进行优化
    React.component创建组件换成React.pureComponent
3.对于数组形式的数据,遍历时需要给同级的每个值添加独一无二的key

80.BFC的理解

BFC是块级格式化上下文,一个元素形成BFC之后,它的内部元素布局不会影响到外部元素,外部元素不会影响到内部元素。
形成BFC的方式:
    1.浮动元素与绝对定位元素
    2.display属性值为inline-block,flex,table,flex
    3.元素的overflow值不为默认属性(visible)
使用场景:
    1.清浮动
    2.解决margin重叠问题(外边距为两者中的最大值,重叠只会出现在垂直方向)
    3.自适应两栏布局
        .left {float: left; width: 100px; height: 300px;}
        .right {overflow: hidden; height: 300px;}

81.从哪些点做性能优化?

1.加载
    减少http请求(精灵图-雪碧图,文件的合并)
    减少文件大小(资源压缩,图片压缩,代码压缩)
    CDN(第三方库,存放大文件大图片,代码中引入地址)
    SSR服务端渲染,预渲染
    懒加载
    分包
2.减少dom操作,避免回流,文档碎片
3.css性能的优化
    css压缩
    使用margin-top,margin-bottom来设置而不是用margin:top 0 bottom 0;
    尽量使用link标签,而不要使用@import

82.jsx是什么

jsx是js的一种扩展语法,它不能被浏览器读取,需要通过babel将其解析为传统js.
为什么要使用jsx?
jsx允许前端开发者使用我们最熟悉的html标签语法来创建虚拟dom,在降低学习成本的同时,也提高了研发效率和体验

83.React的生命周期

1.挂载时
    constructor--getDerivedStateFromProps--render--componentDidMount
2.更新时
    getDerivedStateFromProps--shouldComponentUpdate--render--getSnapShotBeforeUpdate--componentDidUpdate
3.卸载时
    componentWillUnmount

84.高阶组件使用场景以及优缺点

1.权限控制
    function withAdminAuth (wrapComponent) {
        return class extends React.component {
            state={isAdmin: false}
            componentWillUnmount() {
                this.setState({isAdmin: 'Admin'})
            }
            render() {
                if(this.state.isAdmin){
                    return <wrapComponent {...this.props} />
                } else {
                    return (<div>您没有权限,请联系管理员</div>)
                }
            }
        }
    }
优点:通过传递props去影响内层组件状态,不影响参数组件的内部逻辑,降低了耦合度
缺点:组件多层嵌套,增加复杂度与理解成本
    高阶组件多层嵌套,相同属性名的props会覆盖老属性,不清楚props来源于哪个高阶组件

85.柯里化函数?

题目:实现函数fn,让其具有如下功能;let res = fn(2,1)(3); console.log(res) //6
    function fn (...others) {
        return function(...innerOther) {
            let args = innerOther.concat(others);
            return args.reduce((result, item) => result+item);
        }
    }
题目:编写一个求知函数sum,使输入sun(2)(3)或输入sum(2,3),输出结果为5;
    function sum(other) {
       var num = other[0];
        if (other.length == 1) {
            return function(sec) {
                return num+sec;
            }
        } else {
            return other.reduce((result, item) => result+item)    
        }
    }

86.类组件与函数组件哪个性能好,为什么?  

函数组件性能好,函数组件不回有组件实例化的过程,不需要分配多余的内存,函数组件没有生命周期。

87.jsonp的实现原理

1.首先利用script标签的src属性来实现跨域
2.通过将前端方法作为参数传递到服务器,然而由服务器注入参数之后返回,实现服务器端向客户端通信
3.由于使用script标签的src属性,因此只支持get方法。

实现:
1.设定script标签
    <script src='http://jsonp.js?callback=xxx'></script>
2.callback定义一个函数,而远程服务端通过调用指定函数来实现传递参数,将fn(response)传递回客户端
3.客户端接收到返回的js脚本,开始解析和执行fn(response)

88.在antd的基础上写自定义筛选菜单

使用columns的filterDropdown属性,自定义筛选菜单。为了可复用性高将其封装为一个函数
该函数只需要传入筛选操作时发生时要执行的函数其他参数从antd给的props里取。由此依然可以用antd的filter等api.返回一个完整的菜单组件

export const getColumnFilter = onSearch => void => props => {
    const { setSelectedKeys, selectedKeys, filters, confirm, clearFilters } = props;
    const onChange = (checkedValues) => {setSelectedKeys(checkedValues)}
    const clear = () => {
        setSelectedKeys([]); 
        onSearch([]);
        clearFilters([]);
    }
    const onOk = () => {
        onSearch(selectedKeys);
        confirm();
    }
    return (
        <div>
            <Checkbox.Group onChange={onChange} value={selectedKeys}>
                {
                    filters.map(
                        item => (
                            <Checkbox value={item.value} key={item.value}>
                                {item.text}
                            </Checkbox>
                        )
                    )
                }
            </Checkbox.Group>
            <div>
                <Button onClick={clear}>reset</Button>
                <Button onClick={onOk} type='primary'>ok</Button>
            </div>
        </div>
    )
})

在定义的table columns时使用
    {
        dataIndex: 'sth',
        title: 'sth',
        filters: [
            {text: 'filter1', value: 'filter1'},
            {text: 'filter2', value: 'filter2'}
        ],
        filterDropdown: getColumnFilter(//onSearch func like setData)
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值