前端面试题整理(2021)

1、canvas和svg的区别

canvas

  • 基于像素
  • 单个html,类似画笔在画布上画画

svg

  • 基于对象模型
  • 多个图形元素
  • 高保真(不失真,不变形)

2、vdom

  • 用 js 来模拟 DOM 结构
  • dom 变化的对比,放在js层来执行
  • 提高重绘性能
  • DOM操作比较占内存,将dom操作放在js层,可以提高效率性能

3、数组的方法

  • push(),末尾添加元素,会返回改变后数组的长度
  • pop 删除最后一个,返回被删除的值
  • concat 连接两个或多个数组,返回一个新数组
  • shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
  • unshift:将参数添加到原数组开头,并返回数组的长度
  • splice 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。

3.1 es6数组方法

  • map // 循环,必须有return 不设就返回undefined

  • forEach // 循环

  • find // 找到第一个符合的,找到之后就会直接返回

  • filter // 根据条件过滤
    在这里插入图片描述

  • every // 要所有的满足才可以

  • some // 只要有一个满足就行
    在这里插入图片描述

  • reduce // reduce(function(sum,number){…},0)要有两个参数,第一个参数一定要初始化
    // 结果值是1+2+3+4+5 = 15
    在这里插入图片描述

4、jsonp

  • jsonp是一个简单高效的跨域方式,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。
  • 特点:不受同源策略的限制,兼容性更好,易于实现,只支持get。

5、IE盒子模型和谷歌的区别

  • W3C的盒模型方式被称为“content-box
  • IE的被称为“border-box
  • box-sizing: border-box;就是为了在设置有padding值和border值的时候不把宽度撑开。
    在这里插入图片描述
    在这里插入图片描述

6、js原型、原型链

  • 万物皆对象,万物皆空(js中大部分都是对象, 对象的源头为null)
  • 原型:保存所有子对象的共有属性值和方法的父对象,分为隐式原型__proto__和显示原型prototype,隐式原型指向他构造函数的显示原型
  • 原型链:由各级子对象的__proto__属性连续引用形成的结构
  • 主要三个属性: __proto__constructorprototype

总结:

  • .prototype只是一个指针,指向的是原型对象
  • 对象的prototype.constructor就是对象本身
    Object.prototype.constructor==Object
  • 隐式原型等于构造函数的原型
    __proto__ = constructor.prototype
  • 原型链的尽头一般都是Object.prototype
    Object.prototype.__proto__为null
  • 原型链指原型与原型层层相连接的过程即为原型链,访问一个对象的属性,这对象内部不存在这个属性就会去它的原型对象中找,一直找下去,就是原型链的概念。

在这里插入图片描述
图解:
在这里插入图片描述
funtion对象和Object对象之间的关系:

  • Function是顶层的构造器 Object是顶层的对象
  • 顶层现有null,Object.prototype,Function.prototype Function
  • 原型上说:Function继承了Object toString
  • 构造器上说:Function构造了Object new Object()
    在这里插入图片描述

7、prototype和__proto__的区别

  • prototype函数才有的属性,比如你创建一个对象,它是没有prototype属性的
    在这里插入图片描述

  • __proto__每个对象都有的属性,是js内部属性(不推荐使用

  • __proto__ = constructor.prototype 也就是说它等于构造函数的原型

  • 接上一条:但是通过 Object.create()创建的对象有可能不是, Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

8、js防抖、节流

  • 防抖节流的作用都是用于防止函数被多次调用,
  • 区别在于,如果一个用户一直触发这个函数,每次触发的间隔都小于wait,防抖的情况下只会调用一次,而节流的情况会每隔一段一段时间调用函数
  • 防抖在间隔时间内被触发会重新计时,执行最后一次
  • 节流在间隔时间内只执行一次,第一次

9、跨域问题

  • jsonp跨域
    JSONP(JSON with Padding:填充式JSON),应用JSON的一种新方法,

  • JSON、JSONP的区别:
     1、JSON返回的是一串数据、JSONP返回的是脚本代码(包含一个函数调用)
     2、JSONP 只支持get请求、不支持post请求
     (类似往页面添加一个script标签,通过src属性去触发对指定地址的请求,故只能是Get请求)

  • nginx反向代理:

  • 服务端端修改header
      header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
      header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

10、es6新数据类型symbol

  • symbol是es6新推出的一种基本数据类型,表示独一无二的值。最大用途就是用来定义对象唯一的属性名

11、ajax实现

创建XMLHttpRequest对象。
设置请求方式。
调用回调函数。
发送请求。

//第一步:创建XMLHttpRequest对象
var xmlHttp;
if (window.XMLHttpRequest) {            //非IE
    xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {       //IE
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
}

//第二步:设置和服务器端交互的相应参数,向路径http://localhost:8080/getAjax准备发送数据
var url = "http://localhost:8080/getAjax";
xmlHttp.open("POST", url, true);
// open(method,url,async) post/get
// .send(string) 仅用于post

//第三步:注册回调函数
xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4) {
        if (xmlHttp.status == 200) {
            var obj = document.getElementById(id);
            obj.innerHTML = xmlHttp.responseText;
        } else {
            alert("AJAX服务器返回错误!");
        }
    }
}

//第四步:设置发送请求的内容和发送报送。然后发送请求
var params = "userName=" + document.getElementsByName("userName")[0].value + "&userPass=" + document.getElementsByName("userPass")[0].value + "&time=" + Math.random();         // 增加time随机参数,防止读取缓存 				
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");                     // 向请求添加 HTTP 头,POST如果有数据一定加加!!!!
xmlHttp.send(params);

12、call、apply、bind

  • 作用:改变this的指向
  • 第一个参数都是this的指向
  • call/apply直接返回结果,立即执行的,bind返回的是一个函数,需要再次调用
  • call/bind,第一个参数是this,后面跟参数列表。apply两个参数,第二个参数接收一个数组
  • 都是Function对象上的方法

13、react render之后发生了什么

  • 1、React创建元素,解析组件标签,找到MyComponent 组件
  • 2、发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
  • 3、将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

14、react高阶组件

  • 定义:高阶组件(Higher Order Component,HOC)并不是React提供的某种API,而是使用React的一种模式,一个高阶组件就是一个函数,这个函数接受一个组件作为输入,然后返回一个新的组件作为结果,例如:Redux 的 connect
  • 意义:1、重用代码。2、修改现有react组件的行为
  • 实现方式:
    1、代理方式的高阶组件
    2、继承方式的高阶组件

15、this.setState可以放在constructor中吗

  • 直接放在constructor中不会报错,但是也不会生效
  • 原因:this.setState( )本身是异步的,类似于是一种请求而不是立即更新组件的命令,为了更好的性能,React会延迟调用它,不会保证state的变更会立即生效,而是会批量推迟更新
constructor(props){
    super(props)
    this.state = {
        name:'qss'
    }
    this.setState({
        name:'qss3'
    })
}
  • 配合settimeout会生效,官方建议放在componentDidUpdate中执行或利用回调函数(setState(updater, callback))
constructor(props){
    super(props)
    this.state = {
        name:'qss'
    }
    setTimeout(()=>{
        this.setState({
            name:'qss3'
        })
    },1000)
}

16、redux

  • 如果UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。
  • redux取值,在需要使用store中的状态值得组件导出的时候,使用connect
    例如:export default connect(组件名),组件中可直接使用,this.props.状态名来使用
  • 链接https://blog.csdn.net/sinat_41904410/article/details/102961499

17、vue和react的区别

  • vue 提供了一系列的api, 而react的api 很少

  • vue的思想是响应式的,也就是基于是数据可变的,实现了数据的双向绑定,react整体是函数式的思想,是单向数据流,推崇结合immutable来实现数据不可变

  • vue 采用了template, react采用了jsx (本质上都是模版)

  • React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果做脏检查。

  • Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。

18、vuex的相关属性、vuex的模块化

state, getters, mutations, actions, modules。

1. state:vuex的基本数据,用来存储数据

2. getters:获取数据的,this.$store.getters.xxx

3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。
   每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
   回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
   同步操作数据:this.$store.commit(“方法名”,数据)

4. action:和mutation的功能大致相同,异步更新数据,this.$store.dispatch(“方法名”,数据)
   不同点:
   1. Action 提交的是 mutation,而不是直接变更状态。
   2. Action 可以包含任意异步操作。

5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

19、vue父子组件传值,兄弟组件之间的传值

  • 父传子,属性形式传递,props接收
  • 子传父,函数形式,使用$emit() 调用父级函数传递
  • 兄弟组件之间传值,也是通过$emit;
    原理是:vue一个新的实例,类似于一个站,连接着两个组件,也就是一个中央事件总线;eventBus

19.1、父子组件生命周期执行顺序

  • 加载渲染过程(父beforeMount之后开始执行子组件的生命周期)
    在这里插入图片描述

  • 更新过程
    在这里插入图片描述

  • 销毁过程
    只销毁子组件
    在这里插入图片描述
    销毁父组件同时销毁子组件
    在这里插入图片描述

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
  • 常用钩子简易版
父create->子created->子mounted->父mounted

20、webpack/gulp

  • webpack核心代码
  • Webpack有人也称之为 模块打包机
  • Webpack更侧重于模块打包,当然我们可以把开发中的所有资源(图片、js文件、css文件等)都可以看成模块,最初Webpack本身就是为前端JS代码打包而设计的,后来被扩展到其他资源的打包处理。Webpack是通过loader(加载器)和plugins(插件)对资源进行处理的。

const path = require('path'); 
var webpack = require("webpack");
const config = {
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: '[name]-[hash:8].js',
        path: path.join(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.html/, use: ['html-loader']
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: __dirname + '/index.html'
        })
    ]
}
module.exports = config;
  • gulp核心代码
  • Gulp侧重于前端开发的 整个过程 的控制管理(像是流水线)
  • 通过给gulp配置不通的task(通过Gulp中的gulp.task()方法配置,比如启动server、sass/less预编译、文件的合并压缩等等)来让gulp实现不同的功能,从而构建整个前端开发流程。
var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('hello', function() {
// 将你的默认的任务代码放在这
  console.log('hello world!');
});
gulp.task('sass',function(){
  return gulp.src('src/main/webapp/static/styles/scss/apply.scss')
    .pipe(sass())
    .pipe(gulp.dest('src/main/webapp/static/styles/css'))
});

21、webpack loader和plugins

1、loader:

  • loader从字面的意思理解,是 加载 的意思。
  • loader是运行在NodeJS中。
  • 由于webpack 本身只能打包commonjs规范的js文件,所以,针对css,图片等格式的文件没法打包,就需要引入第三方的模块进行打包。css-loader和style-loader模块等等
  • loader运行在打包文件之前(loader为在模块加载时的预处理文件)

2、plugin

  • 也是为了扩展webpack的功能
  • plugin 是作用于webpack本身上的。
  • 针对html文件打包和拷贝(还有很多设置)的插件:html-webpack-plugin。
  • plugins在整个编译周期都起作用。

22、闭包

  • 闭包就是可以访问函数内部参数的函数,闭包的本质是作用域,用于保护和保存局部变量,保护局部变量不受污染,保存循环中的i值

  • 优点是:避免全局变量污染,变量一直存在在内存中

  • 缺点是:变量一直存在在内存中,如果使用不当会导致内存泄漏,需要在退出函数时将不用的参数删除

应用: 给对象循环添加点击事件的时候,由于函数内部是单独作用域,
如下第一种写法,返回值是当循环结束之后的 i 值,是333
第二种写法应用闭包,实现数据的驻留,打印结果为 012


var btns = [{name:'b1'},{name:'b2'},{name:'b3'}]
// 未应用闭包
function bind(){
    for(var i = 0;i<btns.length;i++){
        btns[i].onclick=function(){
            console.log(i)
        }
    }
}
// 应用闭包,增加立即执行函数
function bind(){
    for(var i = 0;i<btns.length;i++){
        (function (num){
            btns[i].onclick=function(){
                console.log(num)
            }
        })(i)
    }
}
// 第三种作为扩展介绍,es6的let,let会形成单独作用域
function bind(){
    for(let i = 0;i<btns.length;i++){
        btns[i].onclick=function(){
            console.log(i)
        }
    }
}
bind();
btns[0].onclick();
btns[1].onclick();
btns[2].onclick();

22.1、执行环境(执行上下文)

执行环境(EC execution context)和作用域概念类似,分为全局执行环境、局部执行环境

  • 全局执行环境,也就是window
  • 局部执行环境指的是函数内部执行环境

浏览器环境栈:

  • 默认有一个全局执行环境 ,也就是window
    [ window ]
  • 当我们创建的函数被调用的时候,形成了一个新的局部执行环境,栈是先进后出的理念,这个时候window执行环境会被挤入栈底
    [ fun, window ]
  • 多个环境调用的时候依次,执行的时候如果在第一层没有找到对应属性,就往上查找,栈中方法调用之后内存会被自动释放,保留变量,就比如闭包上面的那个例子,为什么不用闭包的时候,调用方法返回的值是3,因为当找到那一层执行环境的时候 i 已经结束了循环,值为3
    [ fun, fun, window ]

图解:

23、vue中template里面的和render里面的区别是啥

  • 相同之处:
    render 函数 跟 template 一样都是创建 html 模板

  • 不同之处:
    1、Template适合逻辑简单,render适合复杂逻辑。
    2、使用者template理解起来相对容易,但灵活性不足;自定义render函数灵活性高,但对使用者要求较高。
    3、render的性能较高,template性能较低。这一点我们可以看一下,下图中vue组件渲染的流程图可知。
    4、基于上一点,我们通过vue组件渲染流程图知道,使用render函数渲染没有编译过程,相当于使用者直接将代码给程序。所以,使用它对使用者要求高,且易出现错误
    5、Render 函数的优先级要比template的级别要高,但是要注意的是Mustache(双花括号)语法就不能再次使用

24、vue双向绑定的原理

  • 通过object.defineProperty()来劫持各个属性的setter/getter,在数据变动时,发布消息给订阅者,触发相应的监听回调
Object.defineProperty(obj,prop,descriptor){}
// 参数描述
// obj:需要定义属性的对象
// prop:需要定义的属性
// descriptor: 属性的描述描述符
// 返回值: 返回此对象

var obj = {};
let descriptor = {
	// 数据描述符
	configurable:false,// 表示该属性能否通过delete删除,能否修改属性的特性或者能否修改访问器属性,默认为false.当且仅当该属性的configurable 为true的时候,才能实现上述行为
	writable:false,// 表示该属性的值是否可写,默认为false.当且仅当属性的writable为true时,其值才能被赋值运算符改变
	enumerable:false, // 表示该属性是否可以枚举,即是否可以通过for..in访问属性,默认为false
	value:'hello world' // 表示该属性的值,可以是任何有效的js值,默认为undefined

	// 访问器描述符:数据描述符和访问器描述符不能同时使用
	// get:在读取属性时调用的函数,默认为undefined
	// set:在写入属性时调用的函数,默认值为undefined
}

Object.defineProperty(obj,'qwe',descriptor)
console.log(obj.qwe) // hello world

数据响应式 vue

function definReactive(obj, key, val){
	// 在此作用域内存在一个val变量,由于闭包的存在他不会被销毁,会一直保存在内存中
	Object.defineProperty(obj,key,{
		get (){ //获取key上的值
			console.log('get',key)
			return val
		},
		set(newval){
			if(newval !== val){
				console.log('set',key)
				val = newval
			}
		}
	})
}
const obj = {}
definReactive(obj,'foo','123') // 操作对象obj

obj.foo // 触发get函数
obj.foo = '456' //触发set函数,此时newval = 456,而val由于闭包还是123
console.log(obj)

25、keep-alive 触发的生命周期

  • 当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated

  • 事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中;

26、computed/watch、computed可以监听单个属性吗?

  • computed 是计算属性,监听多个属性,影响一个值,例如购物车结算
  • watch 监听单个属性,一条数据影响多条数据,例如数据搜索
  • computed 可以监听单个属性,使用get () {}, 来获取单个值
computed: {
    // 多个值,影响一个值
	evidenceHeight () {
       let height = this.$store.state.common.documentClientHeight - 350
       return {minHeight: height + 'px'}
   },
  // 单个值
   defaultTheme: {
       get () {
         return this.$store.state.config.defaultTheme
       },
       set (val) {
         return this.$store.commit('config/updateDefaultTheme', val)
       }
   }
},
watch: {
    // 普通监听
    value () {
        if (this.value === '') {
            this.clearHandle()
        }
    },
    // 深度监听
    files: {
        handler (files) {
            if (files && files.length > 0) {
                this.accessories = files
                this.selectedAccessoriesCount = files.length
            }
        },
        immediate: true, // 立即执行 :当刷新页面时会立即执行一次
        deep: false // 复杂类型深度监听
    },
}

27、require 和 import 区别

  • 模块加载时间:require运行时动态加载、import在编译时静态加载(效率更高,需要放在顶部)
  • 使用位置:require可以在函数、判断语句等代码块中加载,import必须在顶部加载
  • 等等

28、new 一个函数相关

1.新创建一个空对象

var fn = new Object();

2.把fn的proto指向构造函数的prototype对象,实现继承

Fn.prototype = fn.__proto__

3.通过调用call、apply方法执行构造函数并改变this对象(绑定到实例对象上,将 fn 作为 this 的上下文)

Fn.call(f)

4.如果没有手动返回其他任何对象或返回值是基本类型(Number、String、Boolean)的值,会返回 this 指向的新对象,也就是实例,若返回值是引用类型(Object、Array、Function)的值,则实际返回值为这个引用类型。
示例:

function myNew (fun) {
        return function () {
            // 创建一个新对象且将其隐式原型指向构造函数原型
            let obj = {
                __proto__ : fun.prototype
            }
            // 执行构造函数
            fun.call(obj, ...arguments)
            // 返回该对象
            return obj
        }
    }

    function person(name, age) {
        this.name = name
        this.age = age
    }
    let obj = myNew(person)('li', 18)   

29、深拷贝,浅拷贝区别,

  • 浅拷贝是复制原对象,共享一个内存,修改的话会影响原对象的值,常见的浅拷贝方式:遍历,Object.assign
  • 深拷贝会创建一个一模一样的对象,不共享内存,修改互不影响
  • 深拷贝函数的思路(遍历):
    1、判断目标是对象还是数组,初始赋值{} || []
    2、for in 遍历目标
    3、hasOwnProperty() 判断当前值是否存在
    4、判断是否是对象,否,直接赋值,是,判断当前对象是对象还是数组,再次调用拷贝函数

26、JSON.parse(JSON.stringfy)进行深拷贝有啥弊端

  • obj里的时间对象new Date()会被改为字符串形式,而不再是时间对象
  • obj里有RegExp、Error对象,会得到空对象
  • obj里有函数,undefined、symbol 会丢失
  • obj里有NaN、Infinity和-Infinity,会变为null
  • JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;

30、判断数据类型的几种方式:instanstof、typeof、Object.prototype.toString.call()

  • instanceof 用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上。通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。判断一个对象是否是另一个对象的实例
[] instanceof Object // true
[] instanceof Array // true
  • typeof 判断类型 但不能判断null,
    在这里插入图片描述

  • 最有效的判断类型方法:Object.prototype.toString.call(null)
    在这里插入图片描述

  • indexof 查找给定元素在数组中的索引,没有的话返回-1,[1,2].indexOf(2)

31、react生命周期

  • 组件的生命周期可分成三个状态:
    Mounting:已插入真实 DOM
    Updating:正在被重新渲染
    Unmounting:已移出真实 DOM
  • react16,生命周期
    componentWillMount 在渲染前调用
    componentDidMount 在第一次渲染后调用(适合调用接口发起请求)
    componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
    shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
    componentWillUpdate 数据变化尚未更新前
    componentDidUpdate 更新后
    componentWillUnmount 卸载后

forceUpdate就是重新render。有些变量不在state上,但是你又想达到这个变量更新的时候,刷新render;或者state里的某个变量层次太深,更新的时候没有自动触发render。这些时候都可以手动调用forceUpdate自动触发render。

  • react16.4中新的生命周期
    1、getDerivedStateFromProps(nextProps, prevState)代替了旧的componentWillReceivePropscomponentWillMount
    代替原因:

    • getDerivedStateFromProps 中禁止了组件去访问 this.props,比较 nextProps 与 prevState 中的值,根据当前的 props 来更新组件的 state,而不是去访问this.props。
    • 当state需要从props初始化时,使用
    • 每次render都会调用

    2、 getSnapshotBeforeUpdate(prevProps, prevState)代替了旧的componentWillUpdate

    • getSnapshotBeforeUpdate会在最终的 render 之前被调用,读取到的 DOM 元素状态是可以保证与componentDidUpdate 中一致的。
    • 在 React 开启异步渲染模式后,在执行函数时读到的 DOM 元素状态并不总是渲染时相同,这就导致在 componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。

32、vue生命周期

  • created 、beforeMount 、mounted 这三个生命周期中可以请求数据
  • beforeCreate 实例创建前(无data、无methods、无$el)
  • created 实例创建后 (有data/methods,无$el)
  • beforeMount 模板加载前
  • mounted 模板加载后 (有$el,可以操作DOM了)
  • beforeUpdate 数据更新后,对应的组件重新渲染之前
  • updated 数据更新后,对应的组件重新渲染之后
  • beforeDestory 组件销毁前,实例尚未销毁
  • destoryed 组件销毁后,实例销毁
  • activated 组件激活(keep-alive)组件触发
  • deactivated 组件停用

在这里插入图片描述

33、web常见安全问题及解决方法

1、xss 跨站脚本攻击

  • 使用encode方法将<等转换为代码
  • 设置HTTP Header中的Content-Security-Policy

2、crsf 跨站请求伪造

  • 加上token用于验证
  • 设置cookie不随请求发送

3、sql注入

  • 不要相信用户输入的信息,对其进行校验,加密敏感信息

更多安全问题可以看这个博文:https://blog.csdn.net/sinat_41904410/article/details/118254355?spm=1001.2014.3001.5502

34、前端性能提升

  • 使用缓存
  • 减少http请求
  • 减少dom操作
  • 图片懒加载
  • css/js放置位置,css前,js后

35、Restful标准

  • REST 指的是一组架构约束条件和原则。
  • RESTful,满足rest原则的应用程序或设计就是 RESTful。
  • RESTful架构是对MVC架构改进后所形成的一种架构,通过使用事先定义好的接口与不同的服务联系起来。在RESTful架构中,浏览器使用POST,DELETE,PUT和GET四种请求方式分别对指定的URL资源进行增删改查操作。因此,RESTful是通过URI实现对资源的管理及访问,具有扩展性强、结构清晰的特点。
  • 为什么需要restful?
    url具有很强可读性,具有自描述性
    规范化请求过程和返回结果
    资源描述与视图的松耦合
    可提供openAPI,便于第三方系统集成,提高互操作性
    提供无状态的服务接口,降低复杂度,可提高应用的水平扩展性

36、webpack性能优化

  • 时间指的是打包时间尽可能快;空间指的是打包体积尽可能小
  • 使用一些插件、配置来实现

时间:

  • 缓存 babel-loader
  • 缓存不常变动模块(代码分割,将不常改动的缓存起来)
  • JS 与 CSS 并行加载
  • 使用 HappyPack 插件对 Loader 进行多线程打包
  • 使用 DNS 加载静态数据

空间:

  • css压缩
  • js压缩

37、css设置黑白条背景

  • 使用css渐变属性,配合宽高呈现横向黑白条或者竖向黑白条
// 横向
height:25%;
background-image: linear-gradient(to bottom, #000 50%, #FFF 0);
// 竖向
width:25%;
background-image: linear-gradient(to bottom, #000 50%, #FFF 0);

38、div盒子里小盒子宽高固定从左到右排列,两边靠边,中间间隔相等,怎么布局

  • float 计算对应的宽高
  • 待解决
<div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
	 <div style="width:9%;height: 10vw;background-color: aqua;float: left;margin:0.5%;"></div>
</div>

39、v-for和v-if为什么不能同时使用

因为v-for优先级比v-if高,每次判断都要先循环一遍,消耗性能较大,不建议同时使用

40、面向对象

面向对象概念: 就是把任何的数据和行为抽象成一个形象的对象,类似于人生活中思考的方式

类:对象(object)的模板,定义了同一组对象(又称实例)共有的属性和方法

就比如,车类:共有的属性:轮胎,发动机… 方法:发动
对象:属性:轮胎, 方法就是发动
就类似于java中的class概念

js中是没有类的概念的,我们可以通过构造函数形式实现面向对象

创建一个构造函数:  function Person(){}      
实例化 : new Person

js面向对象主要有三特点:

  1. 继承:子继承父
  2. 封装:就是将一些共有方法封装起来,方法: run:function(){}
  3. 多态:同一个东西在不同情况下的表现不同状态,有两个概念
    • 重载:也就是说根据传入参数不同进行不同的处理计算
    • 重写:也就是继承,比如子觉得父的run方法达不到自己预期,可以重写一个run1方法,也可以写run方法将父的run覆盖

41、继承

js继承的方式6种

  1. 简单原型链:类式继承
  2. 借用构造函数:缺点=》父类的原型方法自然不会被子类继承
  3. 组合继承(常用):类式继承+构造函数式继承
  4. 寄生组合继承(最佳):寄生式继承+构造函数式继承
  5. 原型式:跟类式继承一样,父类对象中的值类型的属性被复制,引用类型的属性被共有
  6. 寄生式:通过在一个函数内的过渡对象实现继承并返回新对象的方式

42、vue-router有哪几种钩子函数

beforEach

  • 参数有
  • to(Route路由对象)
  • from(Route路由对象)
  • next(function函数) 一定要调用才能进行下一步

afterEach
beforeRouterLeave

43、vue 中key的作用

key主要用在虚拟Dom算法中,每个虚拟节点VNode有一个唯一标识Key,通过对比新旧节点的key来判断节点是否改变,用key就可以大大提高渲染效率

44、diff算法

diff算法是指对新旧虚拟节点进行对比,并返回一个patch对象,用来存储两个节点不同的地方,最后利用patch记录的消息局部更新DOM

45、虚拟DOM的优缺点

缺点:首次渲染大量DOM的时候因为多了一层虚拟DOM计算,所以插入速度会比innerHTML慢
优点:使用js来模拟DOM,减少了DOM操作,减少了回流与重绘。提升性能。局部更新。

重绘指的是颜色等改变不影响布局,回流指的是布局改变,消耗性能较大
重绘不一定引起回流,回流一定会引起重绘

46、vue中的nextTick

在下次DOM更新循环结束之后执行延迟回调。在修改数据后,立即使用这个方法可以拿到更新后的DOM
应用:

  • 想要在Vue生命周期函数中的created()操作DOM可以使用Vue.nextTick()回调函数
  • 在数据改变后要执行的操作,而这个操作需要等数据改变后而改变DOM结构的时候才进行操作,需要用到nextTick

47、>>>、/deep/、::v-deep区别

  • 都是深度选择器,可以对组件内部样式修改
  • 原生css可用 >>>表示深度选择
  • 使用scss less等预处理器的话,>>>可能无法编译,需要使用 ::v-deep/deep/
  • 在scss中使用/deep/会报loader错误,这时可以使用::v-deep来代替
  • 11
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值