前端八股文

这篇具有很好参考价值的文章主要介绍了前端八股文。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Vue

Vue3的一些基本配置

  • 去掉ESLint校验:package.json中的extends去掉eslint:commends

  • 引入icon图标

    // main.js中
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    import * as ElementPlusIconsVue from '@element-plus/icons-vue'
    const app = createApp(App)
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        app.component(key, component)
    }
    
    // vue页面使用
    <el-icon><edit /></el-icon>
    

Vuex

  • state: 存放数据
  • mutations: 同步操作,写方法用于改变state里面的数据,vue可以监听数据的改变进行更新(相当于methods)
  • actions:所有异步操作都放在这里,改变的数据不能够被vue监听
  • getters: 进行逻辑处理(相当于computed属性)
  • module:单一状态树,存放所有模块
  1. 新建store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
        state:{
            count: 0
        },
        mutations:{
            // state是必要参数
            addCount(state, number){
                state.count+=number
            }
        },
        actions:{
        	setCount(content, payload){
        	    //增加setCount方法,默认第一个参数是content,其值是复制一份store,第二个是自定义参数
        	    return new Promise(resolve => {
        	        setTimeout(()=>{
        	            content.commit('addCount', payload);
        	            resolve();
        	        }, 1000);
        	    })
        	}
        },
        getters:{
            // 不能改变state里面的值
            alertCount(state){
                return `当前值${state.count}`
            }
        }
    })
    
    export default store;
    
  2. 页面使用

    <template>
      <div><b>count: {{this.$store.state.count}}</b></div>
      <button @click="addCount">count++</button>
    </template>
    <script>
    export default {
      name: 'HelloWorld',
      mounted() {
        console.log(this.$store.state.count)		// 获取state值
        console.log(this.$store.getters.alertCount)	// 执行getters里的方法
      },
      methods:{
        addCount() {
          this.$store.commit('addCount', 1)		// 执行mutation里的方法
        }
      }
    }
    </script>
    

    简写vuex

    • 采用解构方法import {mapState, mapMutations, mapGetters} from "vuex";
    <script>
    import {mapState, mapMutations, mapGetters} from "vuex";
    
    export default {
      name: 'HelloWorld',
      mounted() {
        console.log(this.count)		// 解构后,采用this.xx调用vuex的内容
        console.log(this.name)
      },
      methods:{
        ...mapMutations(['addCount']), //mutations和actions要在methods里面解构
        ...mapActions(['setCount']),
        
        btnAdd() {
          this.addCount(1)
        }
      },
      computed:{
        ...mapState(['count', 'name']),	//state和getters要在computed里面解构
        ...mapGetters(['alertCount']),
      }
    }
    </script>
    
  3. 异步action在页面的使用

    async mounted() {
      console.log(`旧值: ${this.count}`)
      await this.$store.dispatch('setCount', 3);	// 默认写法
      await this.setCount(3);	// 解构写法
      console.log(`新值:${this.count}`)
    },
    

v-model低层原理

<h2>v-model低层原理</h2>
<input placeholder="请输入数值" id="username" />
<p id="uName"></p>
<script>
    let obj={}
    Object.defineProperty(obj, 'username', {
        // 取值
        get:function (){
            console.log("取值")
        },
        // 设置值
        set(val) {
          console.log(val)
          document.getElementById('uName').innerText = val
        }
    document.getElementById('username').addEventListener('keyup', function (){
        // 监听事件
        obj.username = event.target.value;
        // console.log(event)
    })
 </script>

vue理解

  • 渐进式框架,声明式渲染,借鉴MVVM思想
  • 采用虚拟dom(不会重新渲染所有页面,先进行对比,有更新的部分会进行重新渲染(render函数))
  • 高内聚,低耦合,使用组件化开发
  • computed属性:如果多次调用某个方法,computed里面只会计算一次,减少了资源消

vue2.0生命周期

  1. 创建前后:组件实例被创建
  2. 挂载前后 :组件挂载到实例
  3. 更新前后 :组件数据更新
  4. 销毁前后:组件实例销毁

vue性能优化

  • 数据层级不能过深,合理设置响应数据
  • v-if 和 v-show合理选择
  • 使用数据缓存,不频繁取值、组件缓存(keep-alive)
  • 分页、虚拟滚动

vue组件通信

  • props通信:子组件通过props接受来自父级组件的参数

  • $emit: 子组件传递数据给父组件

  • ref:父组件使用子组件的时候设置ref(ref = ‘foo’),通过 this.$refs.foo 获取子组件实例

  • EventBus: 兄弟组件传值

  • $parent 或 $root: 通过共同祖辈搭建通信桥梁

  • provide 与 inject
    父级组件:

    provide(){  
        return {  
            foo:'foo'  
        }  
    }  
    

    子组件:

    inject:['foo'] // 获取到祖先组件传递过来的值
    

    父组件向子组件动态传参

    需求

    • 父组件是文章管理列表,带有一个编辑按钮
    • 子组件(editor)是一个内嵌的富文本编辑器:点击编辑按钮,弹出Dialog框,富文本编辑器的内容显示为当前文章内容(暂且设为content属性)
    • 我们需要传递content属性到子组件(editor),但是子组件中v-model无法绑定props中的content,因此子组件中的文本内容绑定的是data中的html属性,我们需要将content传递并且赋值给html。

    当前问题

    • 按照props传参(子组件第一次可以接收content并且更新页面内容,当时当我们点击编辑其他文章,这时候content虽然有变化,但是无法更新到子组件html属性上面(相当于没有监听变化),导致页面无法更新到当前文章的content,仍然显示的是之前的content)

      父组件

      <el-form-item label="内容">
        <WangEditor ref="editor" :content="formLabelAlign.content" />
      </el-form-item>
      

      子组件

      <template>
          <Editor
              style="height: 500px; overflow-y: hidden;"
              v-model="html"
              :defaultConfig="editorConfig"
              :mode="mode"
              @onCreated="onCreated"
          />
      </template>
      <script>
      import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
      export default{
        name: 'WangEditor',
        data() {
          return {
            html: this.content,
          }
        },
        props:['content'],
      }
      </script>
      

    解决办法

    在子组件加上content的监听,当content变化,再给文本编辑器内容绑定的html属性赋值.

    watch:{
      content(newVal, oldVal){
        console.log('content change')
        console.log(newVal)
        this.html = this.content
      }
    },
    

vue-router

1.路由守卫

A.全局路由

全局使用

  • router.beforeEach((to, from, next)=>{}):路由跳转前执行的操作
    to:需要跳转的路径
    from:当前页面路径
    next:执行当前操作

    // 登录拦截器
    router.beforeEach((to, from, next) =>{
      if(to.path == '/login' || to.path == '/front/home'){
        next();
      }else{
        // 不是登录页面
        localStorage.getItem("user")?next():next("/login")
      }
    })
    
  • router.beforeResolve

  • router.afterEach((to, from) =>{}):路由跳转后
    一般用于跳转后更改页面标题声明页面等辅助功能

B.路由独享守卫

某个单页面渲染使用

  • boforeEnter(路由独享的守卫)

    const routes = [
      {
        path: '/users/:id',
        component: UserDetails,
        beforeEnter: (to, from) => {
          // reject the navigation
          return false
        },
      },
    ]
    
    

C.组件路由

组件渲染的时候使用

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave

2.hash和history的区别

hash模式
  • 带#号,改变URL时,页面不会重新加载

  • 利用window.onhashchange事件实现,每次改变hash值,浏览器访问历史会新增一个记录

  • hash值是URL中#后面的值,不会传递给服务器

  • 使用"后退"按钮,返回上一个页面

    history模式

  • 通过window.history实现页面无刷新跳转

  • 路径会随http请求发送给服务器,因此前端URL必须和请求的后端URL一致,否则404

  • 404举例
    当我们把 history 项目部署到服务器中后,此时我们在浏览器输入一个网址(比如是 www.test.com ), 此时会经过 dns 解析,拿到 ip 地址后根据 ip 地址向该服务器发起请求,服务器接受到请求后,然后返回相应的结果(html,css,js)。如果我们在前端设置了重定向,此时页面会进行跳转到 www.test.com/home ,在前端会进行匹配对应的组件然后将其渲染到页面上。此时如果我们刷新页面的话,浏览器会发送新的请求 www.test.com/home, 如果后端服务器没有 /home 对应的接口,那么就会返回404。

computed和watch的区别

  • computed是计算属性,函数内的变量可以缓存,除非变量发生变化,才会重新进行计算
  • watch主要是监听,每次值变化就会立即进行回调。

v-show和v-if的区别

  • v-show是控制display来让元素隐藏(会渲染到页面,不会触发生命周期)
  • v-if显示隐藏时是把整个元素删除(为true才会渲染组件,会触发生命周期)

created和mounted请求数据,有什么区别

  • created:渲染前调用,先初始化属性,再做渲染

  • mounted:渲染完成之后,先初始化页面,再对元素节点进行操作 (这里请求数据,可能会出现闪屏问题)

vue中的修饰符

  • 事件修饰符
    • .stop 阻止冒泡
    • .prevent 阻止默认行为
    • .self 只有在event.target是当前元素触发
    • .capture
    • .once 事件只触发一次
    • .passive 立即触发默认行为
  • 按键修饰符
    • .keyup .keydown
  • 系统修饰符
  • 鼠标修饰符
  • 表单修饰符

keep-alive组件

用来缓存组件 ==》减少页面刷新、网络请求次数,提升性能

Vue el-upload上传图片 + express

思路:

  • 以formData的数据格式上传图片
  • 后端存储图片到文件夹(/images/)下,并且返回给前端图片名称(imgUrl)
  • 前端通过’http://localhost:3000/images/imgUrl’的形式访问图片地址,用于展示

前端代码

<el-upload
    class="avatar-uploader"
    action="string"
    method="post"
    :http-request="uploadImage"		// 自定义上传图片函数
>
  <img v-if="formLabelAlign.imageUrl" :src="resource+formLabelAlign.imageUrl" class="avatar">
  <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<script>
export default {
  name: "Attractions",
  data() {
    return {
      formLabelAlign: { title: '', date: '', content: '', imageUrl: '', filename: '', label: ''},
      resource: 'http://localhost:3000/images/',
    }
  },
  methods: {
    uploadImage(params){
    // 图片以formData格式上传,并且请求头需要设置'Content-Type': 'multipart/form-data'
      let formData = new FormData()   
      formData = { file: params.file,}
      const config = {
        headers:{
          'Content-Type': 'multipart/form-data'
        }
      };
      this.request.post('/attractions/uploadImage', formData, config).then(res=>{
        // console.log("upload: ", res)
        this.formLabelAlign.imageUrl = res.data.data
      })
    }
  },
}
</script>

后端代码(express)

const MsgCode = require("../config/MsgCode");
const multer = require('multer')	// 引入multer:图片处理的工具包
const path = require('path')
const storage = multer.diskStorage({
  // 配置文件上传后存储的路径
  destination: function (req, file, cb) {
    // NodeJS的两个全局变量
    // console.log("__dirname: ", __dirname);  //获取当前文件在服务器上的完整目录
    // console.log("__filename: ", __filename); //获取当前文件在服务器上的完整路径
    cb(null, path.join(__dirname, '../public/images'))
  },
  // 配置文件上传后存储的路径和文件名
  filename: function (req, file, cb) {
    let defineFilename = new Date().getTime() + file.originalname     // 防止图片名重复
    cb(null, defineFilename)
  }
})
const upload = multer({
  fileFilter(req, file, callback) {
    // 解决中文名乱码的问题
    file.originalname = Buffer.from(file.originalname, "latin1").toString("utf8");
    callback(null, true);
  },
  storage: storage
})

// 上传首页图
router.post('/uploadImage',upload.single('file'), function (req, res, next){
  // console.log(req.file)
  MsgCode(res, req.file.filename, "")	// 返回前端的自定义函数,读者可以自己使用res.end()进行数据传输
})

this.$nexttick

当数据被修改后,获取dom更新之后的数据,用于异步获取更新后的数据,性能优化

Object.defineProperty有什么缺点

  • 无法监听到数组变化
  • 无法检测对象属性的添加和删除

vue2和vue3区别

  • 选项式API(vue2)和组合式API(vue3)
  • vue3:多根节点
  • 响应式原理:vue2(Obejct.defineProperty)vue3(proxy)
  • Diff算法优化
  • 虚拟dom增加patchFlag字段

MVC

view(视图层)-controller(控制器)-model(数据模型)

view主要用于UI界面展示和响应用户交互,controller用于监听数据改变和处理用户交互,model用于存放数据

MVVM

model-viewmodel-viewcontroller

在MVC的基础上,把contrler的数据和逻辑处理部分抽离出来,放到viewmodel中,是model与controller沟通的桥梁。

JS

JS组成三部分

  • ECMAScript: JS的核心内容,描述了JS的基础语法(var for 数据类型…)
  • 文档对象模型(DOM)
  • 浏览器对象模型(BOM): 对浏览器窗口访问和操作

location对象

包含了当前url的属性,主要有

  • protocol(‘http:’)协议
  • host(‘www.xx.com’) 网址
  • hostname(带了端口号)
  • path (/home/list) 访问路径
  • search (‘?id=123456&sort=discount’) 参数
  • hash (‘#title’)

innerText 和 innerHTML的区别

  • innerText不识别html标签,不保留空格和换行
  • innerHTML识别html标签,保留空格和换行

和=区别

  • ==: 比较的是值(如string类型和number类型比较,会进行隐士转化)
  • ===:除了比较值,也比较数据类型(object类型比较的是地址)

构造函数

  • 函数名首字母大写
  • 不需要return就可以返回结果
  • 调用函数必须使用关键字new
// 构造函数
function Star(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}
var dz = new Star('DZ', 18, 'male');
console.log(dz.age)

cookie sessionStorage localStorage的区别

  • 三者均保存在本地浏览器
  • cookie:存储量小,由服务器写入,若设置了固定的时间,时间过后失效
  • session:页面关闭自动清除(主要用于检测用户刷新页面)
  • localStorage:一直保存在本地(存储不易变动的数据),不会自动清除

token的登录流程

  • 客户端用账号密码请求登录
  • 服务器验证请求,成功之后,给客户端签发一个token,
  • 客户端将token保存在本地(localstorage或者cookie中)
  • 每次客户端发送请求,都要携带token
  • 服务端收到请求,需要先验证token,验证成功,给客户端返回请求数据

Token存localStorage还是session里面?

  • 存localStorage里面,每次请求接口都需要把它当做字段传到服务器(容易被XSS攻击)
  • 存cookie中,会自动发送,不能跨域(CSRF攻击)

基本&引用数据类型(JS内置对象)

  • 基本数据类型:string,number,undefined,null,boolean,symbol,bigint
    保存在栈内存中,保存的是一个值

  • 引用类型:object(普通对象)Array Function Date
    保存在堆内存中,保存的是引用数据类型的地址(多个引用会同时改变)。例如下:

    let obj = {
        name: 'xm',
        age: 18
    }
    let obj1 = obj
    obj1.name = 'change'
    console.log(obj)
    console.log(obj1)
    

常用的对象

  • Math(abs, ceil, sqrt, max, min…)
  • Date(getYear, getMonth…)
  • Array(push, foreach)
  • String(concat, length, slice, split)

操作数组的方法

  • push() pop() sort()

  • splice():数组删除,返回删除的元素,会改变原数组

  • slice:数组截取

  • unshift() shift() reverse() concat() join() map() filter() reduce() isArray() findIndex()

  • find 和 filter
    find 返回第一个满足条件的内容
    filter 返回一个新的数组

      let arr = [1, 2, 3, 4, 5, 5]
      let a = arr.find(item=>item>2)
      let b = arr.filter(item=>item>2)
      console.log(a)	// 3
      console.log(b)	// [3, 4, 5, 5]
    
  • 改变原数组的方法:push() pop() sort() reverse() unshift() shift() splice()

JS判断数组的方法

  • Array.isArray() 、instanceof Array() 、 constructor、prototype

      let arr = [1, 2,3]
      let str = 'hello'
      console.log(Array.isArray(arr))
      console.log(arr instanceof Array)
      console.log(Object.prototype.toString.call(arr).indexOf('Array') > -1)
      console.log(arr.constructor.toString().indexOf('Array') > -1)
    

数组去重

  • Set

  • indexOf

  • filter

      let arr = [1, 2, 2, 3, 1, 4]
      // set去重
      console.log(Array.from(new Set(arr)))
      // indexof去重
      function unique(arr){
        let brr = []
        arr.forEach(item=>{
          if(brr.indexOf(item) == -1){
            brr.push(item)
          }
        })
        return brr;
      }
      unique(arr)
      // 方式三:filter
      var arr2 = arr.filter((item, index,self)=>{
        console.log(item, index, self)
        return self.indexOf(item)===index
      })
      console.log(arr2)
    

多维数组最大值

  let arr = [
          [1, 2,3],
          [1,3,5],
          [95, 25, 36]
  ]
  let brr = []
  arr.forEach(item=>{
    console.log(Math.max(...item))
    brr.push(Math.max(...item))
  })

数据类的检测方法

  • typeof() 判断基本数据类型

  • instanceof() 判断引用数据类型

  • constructor 基本可以判断基本数据类型和引用数据类型

    console.log(('abc').constructor === String)
    
  • Object.prototype.toString.call() 可以判断所有数据类型

    var opt = Object.prototype.toString
    console.log(opt.call(2))     // [object Number]
    console.log(opt.call('abc')) // [object String]
    console.log(opt.call([]))   // [object Array]
    console.log(opt.call({}))   // [object Object]
    console.log(opt.call(true)) // [object Boolean]
    

闭包

  • 优点:可以重复利用内部变量,不会污染全局变量,一直保存在内存中,不会被垃圾机制回收

  • 缺点:闭包较多的时候,会消耗内存,导致页面性能下降,在IE浏览器会导致内存泄漏

  • 应用:防抖(防止重复点击,n秒后执行事件,在n秒内重复点击,从最后一次点击开始计时 — 点击事件)节流(n秒内重复点击,只有一次生效 – 滚动条)

  • function fn(){
        let name = 'xiaoxie'
        function getName(){
            alert(name)
        }
        getName()
    }
    fn()
    

防抖和节流的实现

  // 防抖:n次内重复点击,执行最后一次
  function FD_debounce(func, wait){
    let timeout;
    return function (){
      let context = this;	// 保存this指向,context指向当前对象
      let args = arguments
      clearTimeout(timeout)
      timeout = setTimeout(function (){
        func.apply(context, args);
        console.log(context)
      }, wait);
    }
  }
  let func = function (){
    console.log('我是func')
  }
  res = {
    a: debounce(func, 2000)
  }
  res.a()

  // 节流: n秒多次点击,只执行一次
  function JL_debounce(func, wait){
    let timeout;
    return function (){
      let context = this
      if(!timeout){
        timeout = setTimeout(function (){
          func.apply(context)
          timeout = null
        }, wait);
      }
    }
  }

内存泄漏

JS里已经分配内存地址对象,但由于长期没办法回收和清除释放,造成长期占有资源的情况,导师运行速度缓慢甚至崩溃。

因素

  • 未清空的定时器
  • 过度的闭包
  • 一些元素没被清除

事件委托(事件代理)

原理:利用事件冒泡的机制实现,把子元素的事件绑定到父元素身上

父元素添加addEventListener('click', 函数名, true/false) 默认true, false代表阻止(子元素)冒泡

原型链

原型链:一个实例对象在调用属性和方法的时候,会以此从实例本身=》构造函数原型 =》原型的原型 去查找

以下例子的原型链:p1 -> Person -> Object -> null

原型就是一个普通的对象,它是为构造函数的实例共享属性和方法,所有实例中引用的原型都是同一个对象

<!--原型-->
function Person(){
    this.say = function (){
        console.log('sing')
    }
}
let p1 = new Person()
let p2 = new Person()
p1.say()
p2.say()

例:say调用了两次,在内存中占用了两个(如果多次使用,会造成资源浪费),为了解决这个问题,原型:将方法挂载到prototype上,所有实例共享这个方法,减少了内存消耗。

__proto__: 可以理解为指针,实例对象中的属性,指向了构造函数的原型(prototype)

p1.__proto__ === Person.prototype // 返回true

例如下:

<!--原型-->
function Person(){
    this.say = function (){
        console.log('sing')
    }
}
Person.prototype.run = function (){
    console.log('跑步')
}
let p1 = new Person()
let p2 = new Person()
//p1.say()
//p2.say()
p1.run();
p2.run();

new关键字

实现new关键字

    function newFun(Fun, ...args){
        // 1.创建空对象
        let obj = {}    // 引用类型
        // 2.把空对象和构造函数通过原型链进行连接
        obj.__proto__ = Fun.prototype
        // 3.把构造函数的this绑定到新的空对象身上
        const res = Fun.apply(obj, args)    // 值类型
        // 4.根据构造函数返回的类型判断,如果是值类型,返回对象;是引用类型,返回这个引用类型
        return res instanceof Object ? res:obj;
    }
    // 测试newFun
    function Person(name){
        this.name = name
    }
    Person.prototype.printName = function (){
        console.log(this.name)
    }
    let p1 = newFun(Person, 'xym')
    p1.printName()

JS的继承

  • 原型链继承(子类继承父类,new出来的实例拥有父类相同的属性和方法)
    缺点:无法向父类传参

        function Person(){
            this.info={
                name: '张三',
                age: 12
            }
        }
        function Child(){}
        Child.prototype = new Person();
    
  • 构造函数继承(使用call / apply 方法实现继承,在子类里面调用父类)
    缺点:无法实现函数的复用

    function Person(){
        this.info={
            name: '张三',
            age: 12
        }
    }
    function Child(){
        Person.call(this)
    }
    let c1 = new Child();
    c1.info.nick = 'nick name'
    console.log(c1.info)
    
  • 组合继承(调用了两次父类构造函数)

    function Person(gender){
        this.info={
            name: '张三',
            gender: gender,
            age: 19
        }
    }
    Person.prototype.getInfo = function (){
        console.log(this.info)
    }
    function Child(gender){
        Person.call(this, gender)   // 构造函数继承
    }
    Child.prototype = new Person()  // 原型链继承
    let c1 = new Child('男')
    c1.info.nickname = '小张'
    c1.getInfo()
    
    let c2 = new Child('女')
    c2.info.nickname = '小红'
    // c1 和 c2 互不影响
    c1.getInfo()
    c2.getInfo()
    
  • ES6使用class关键字继承父类
    某些浏览器可能不支持

    class Animal{
        constructor(kind) {
            this.kind = kind
        }
        getKind(){
            return this.kind
        }
    }
    
    // 继承animal类
    class Cat extends Animal{
        constructor(name) {
            // 子类构造方法必须调用super方法
            super('cat');
            this.name = name
        }
        getCatInfo(){
            console.log(this.name+' : '+this.getKind())
        }
    }
    let cat = new Cat('buding')
    cat.getCatInfo()
    
  

## JS设计原理

- JS引擎
- 运行上下文
- 调用栈
- 事件循环
- 回调

## JS中的this指向

- 全局对象的this指向window
- 全局作用域/普通函数中this指向window
- this永远指向最后调用他的对象
- apply call bind可以改变this指向
- 箭头函数this指向箭头函数外的一层

## setTimeout和setInterval最小时间

- setTimeout   4ms
- setInterval   10ms

## promise

- 解决回调问题

​```js
const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('foo');
    }, 300);
});

myPromise.then(value => {
    console.log(value)
})

跨域?如何解决跨域?

跨域:当前页面接口访问的 协议/域名/接口 不同,(浏览器的同源策略)。(浏览器能发出请求,服务器能响应数据,返回的时候被浏览器拦截了)

解决办法

  • script调用js文件
  • 服务器实现cors接口,前端正常访问就行。服务器收到前端请求,设置Access-Control-Allow-Origin

异步操作实现

  • 回调函数callback

    function f(x){
        console.log(x)
    }
    function printTime(){
        setInterval(function (){
            console.log('print fn exe')
            c = 1
        }, 3000)
    }
    var c = 0
    printTime()
    f(c)
    

    js内部执行不是按照顺序的,因此这里先打印0,再输出"print fn exe"。采用回调函数实现异步

    <script type="text/javascript">
        <!--回调函数,实现异步操作-->
        function f(x){
            console.log(x)
        }
    
        function printTime(callback){
            setInterval(function (){
                console.log('print fn exe')
                c = 1
                callback(c)
            }, 3000)
        }
        var c=0
        //方法一
        printTime(f)
        // 方法二
        printTime(function (x){
            console.log(x)
        })
    </script>
    
  • async / await

    function print(time){
        setTimeout(function(){
            console.log(time);
            return 1;
        },time)
    }
    async function fun(){
        let a = await print(1000);
        // let b = await print(3000);
        // let c = print(2000);
        console.log(a);
        // console.log(1)
    
        setTimeout(()=>{
            alert(a)
        }, 3000)
    }
    fun();
    
  • setTimeout(利用定时器实现异步操作)

ES6新特性有哪些?

  1. 新增了箭头函数
    不能作为构造函数使用,不能new
    没有arguments
    不能用call,apply,bind改变this指向
    箭头函数的this是在函数定义时就决定了,不可以修改:this指向定义时外层第一个普通函数的this
  2. 新增块级作用域(let 和 const)
    不存在变量提升(在变量声明之后才能使用)
    存在暂时性死区问题
    块级作用域的内容
    不能在同一个作用域内重复声明
  3. Promise
    解决回调地狱问题
    自身有all,reject,resolve,race等方法
    原型上有then,catch
    把异步操作队列化
    三种状态:pending-初始状态,fulfilled-操作成功,rejected-操作失败
    async/await
    同步代码做异步操作
  4. 解构赋值
    从对象或者数组中取值,然后给变量赋值
  5. set和map
    set:数组去重
    map的key类型不受影响
  6. 定义类语法糖(class)
  7. 数据结构(symbol)
  8. 模块化(export,import)

call、aply、bind区别

  • 都能改变this的指向
  • call和aply功能类似,传参方法不同
  • call传的是一个参数列表
  • aply传的数组

实现深拷贝

深拷贝就是完全拷贝一个新的对象,会在堆内存开辟新空间,拷贝的对象被修改后,原对象不受影响

主要针对引用数据类型

  • 扩展运算符

  • JSON.parse(JSON.stringify())

  • 递归实现

    // 深拷贝
    let obj = {
        name: '张三',
        age: 18,
        say(){console.log('say name')},
        arr:[[1, 2], 3, 4, 5]
    }
    // let obj1 = {...obj}     // 方法一:扩展运算符
    // obj1.name = 'xxx'
    // console.log(obj)        // name : "张三"
    // console.log(obj1)       // name : 'xxx'
    
    // 方法二:json.parse   =>  不能拷贝函数,即say没有拷贝进来
    // let obj2 = JSON.parse(JSON.stringify(obj))
    // obj2.name = 'aaa'
    // console.log(obj)
    // console.log(obj2)
    
    // 方法三 递归实现深拷贝
    function exten(origin, deep){
        let res = {}
        if(origin instanceof Array) res = []    // 判断数组, 更改返回类型
        for(let key in origin){
            let value = origin[key]
            res[key] = (deep && typeof value == 'object' && value != null) ? exten(value, deep):value
        }
        return res
    }
    let obj3 = exten(obj, true)
    obj3.name = 'bbb'
    obj3.arr[0].push('ccc')
    console.log(obj)
    console.log(obj3)
    

ajax

ajax:交互式网页开发技术,在不重新加载整个页面的情况下,与服务器交换数据并更新部分内容

通过XmlHttpRequest对象向服务器发送异步请求,然后从服务器拿到数据,最后通过js操作dom更新页面

  1. 创建XmlHttpRequest对象 xml
  2. xml.open()和服务器建立连接
  3. xml.send()发送数据
  4. xml.onreadystate() , xml.change()事件监听服务器和通信状态
  5. 接收并处理服务器响应的数据
  6. 更新数据到html页面

ajax/fetch/axios区别

  • fetch是es6的一个用于网络请求的api
  • axios是一个网络请求库
  • ajax是异步js和xmlhttprequest

axios封装

vue2.0

npm install axios  // 安装
  1. 创建service.js配置文件

    import axios from 'axios'
    import { Message, Loading } from 'element-ui'
    const ConfigBaseURL = 'http://localhost:8080/' //默认路径,这里也可以使用env来判断环境
    let loadingInstance = null //这里是loading
    //使用create方法创建axios实例
    export const Service = axios.create({
        timeout: 7000, // 请求超时时间
        baseURL: ConfigBaseURL,
        method: 'post',
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
        }
    })
    // 添加请求拦截器(请求前执行)
    Service.interceptors.request.use(config => {
        loadingInstance = Loading.service({
            lock: true,
            text: 'loading...'
        })
        return config
    })
    // 添加响应拦截器(服务器响应后执行)
    Service.interceptors.response.use(response => {
        loadingInstance.close()
        return response.data
    }, error => {
        console.log('TCL: error', error)
        const msg = error.Message !== undefined ? error.Message : ''
        Message({
            message: '网络错误' + msg,
            type: 'error',
            duration: 3 * 1000
        })
        loadingInstance.close()
        return Promise.reject(error)
    })
    
  2. main.js使用

    import {Service} from '@/utils/service'
    
    Vue.prototype.request = Service	//将axios放在vue的this上(vue2)
    app.config.globalProperties.request = Service //(vue3)
    
  3. 使用

    // post方法
    this.request.post(`/menu/delete?id=${val}`).then(res=>{
      	// 请求成功
      }else{
        // 请求失败
      }
    });
    // get方法
    this.request.get("/echarts/getList").then(res =>{
         console.log(res)
    })
    

vue3.0

  1. 创建http.js

    import axios from "axios";//创建一个axios的对象
    //生成一个axios的实例
    const http=axios.create({
        baseURL:"http://localhost:8080/",// baseURL会在发送请求的时候拼接在url参数前面
        timeout:3000,//请求超时
    });
    export default http;//导出
    
  2. main.js使用

    import axios from "axios";
    const app = createApp(App)
    app.config.globalProperties.axios = axios
    
  3. 单页面使用

    getWeather:function (){
          this.axios.get(url).then(res =>{
            // console.log(res)
          })
        }
    
  4. 封装API的js文件使用(异步调用)
    封装函数js文件

    import http from "./http";
    export const getWeather = ()=>{
        return new Promise((resolve, reject)=>{
            http.get(url).then(res =>{
                resolve(res)
            })
        })
    }
    
      页面调用
    
    // 1.引入
    import  {getWeather} from '../request/HomeHeader.js'
    // 2.获取返回值
    let res = getWeather()
    // 方法一 采用promise实现异步
    res.then((res)=>{
      console.log(res)
    })
    // 方法二 采用async/await实现异步
      async created() {
        let res = await getWeather()
        console.log(res)
      }
    

get和post请求

  • get是请求数据,post是提交数据
  • get的请求参数放在url中,不安全,post请求参数放在body中
  • get请求会缓存,post不会缓存
  • 刷新或回退页面get不会重新请求,post会重新请求
  • get请求只能进行url编码,post支持多种编码方式

promise和async/await的区别是什么

  • 都是处理异步请求的方式
  • async/await是基于promise实现的
  • promise是返回对象,使用then,catch方法处理和捕获异步请求,链式书写,造成代码重叠,维护差
  • async/await使用try,catch捕获异常

SVG格式

基于XML语法的图像格式,可缩放矢量图,本质是文本文件,无论缩放都不会失真

JWT

JSON Web Token 通过JSON形式作为在web应用中的令牌

JWT认证流程

  1. 前端发送登录请求给接口
  2. 服务器核对账号密码成功,把用户id等信息作为jwt负载,和他和头部进行base64编码,形成jwt
  3. 前端每次请求都会把jwt放在http请求头的Authorization字段内
  4. 服务器验证jwt的有效性,返回对应结果

JSON

JSON是一种纯字符串形式的数据,适合网络传输

  • JSON.parse()
  • JSON.stringfy()

数据没有请求过来时,该怎么做?

给数据设默认值,最后进行判断

无感登录

用户不需要重新登录,优化用户体验

方案如下

  • 在响应器中拦截,判断token过期后,调用刷新token的接口
  • 后端返回过期时间,前端判断token过期时间,去调用刷新token的接口
  • 设置定时器,定时刷新token

大文件上传

采用分片上传思想

  1. 把文件按照一定规则分块,分割成相同大小的数据
  2. 初始化一个分块上传,返回本次上传唯一标识
  3. 按照一定规则把各个数据上传
  4. 服务器判断文件完整性,完整就把文件块合并

断点续传

JS为什么是单线程

为什么是单线程:比如当一个用户执行添加节点和删除节点的任务,如果不是单线程,则会出问题

JS微任务和宏任务

  • js是单线程的

  • js代码执行流程:同步执行完 ==》事件循环[微任务、宏任务] ==》微任务 ==》宏任务 ==》微任务 …

    for(let i=0; i<3; i++){
        setTimeout(function (){
          console.log(i)
        }, 1000*i)
      }
    // 输入三个3
    
  • 微任务:promise.then

  • 宏任务:setTimeOut

JS作用域

  • 除了函数外,js无块级作用域

  • 作用域链:内部可以访问外部变量,但外部不能访问内部
    注:如果内部有相同的变量,则优先访问内部的变量

      let a = 10;
      function fun(){
        let a = 20;
        console.log(a)
      }
      fun();
    
  • js变量提升机制

    function c(){
        var b = 1;
        function a(){
          console.log(b)	//undifined
          var b = 2;
          console.log(b)	// 2
        }
        a()
        console.log(b)	// 1
      }
      c()
    
  • 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升

JS对象

  • 对象都是new构建的,所以对象之间不相等

    console.log([1,2,3] === [1,2,3]) // false
    
  • 对象的key都是string类型

  • 原型链:对象本身obj ==》构造函数Fun =》对象的原型(obj._proto_) =》构造函数的原型(Fun.prototype) => Object => null

var let const的区别

  • let const 不存在变量提升,var有

  • var可以声明同一个变量多次,let const 只能声明一次同一个变量

  • const声明常量,一旦赋值不可以修改(const为object/数组,里面的值是可以修改的)

  • let const有块级作用域

      if(true){
        let a  = 1;
        const b = 2;
        var c = 3;
      }
      console.log(c)	// c能打印,a,b会报错
      console.log(a)
      console.log(b)
    

object对象的合并

  const a = {a:1, b:4}
  const b = {b:2, c:3}
  //方式1
  let obj = Object.assign(a, b)	// {1,2,3}
  // 方式二
  let obj2 = {...a, ...b} // {1,2,3}

websocket(vue2.0实现)

  • 前端
    登录页:输入用户信息,进入聊天室
    聊天页:输入消息,点击按钮发送

    <template>
      <div>
        <ul>
          <!--   消息展示   -->
          <li v-for="item in msgList" :key="item.id">
            <div>用户:{{item.username}}</div>
            <div>时间:{{new Date(item.dateTime)}}</div>
            <p>消息:{{item.msg}}</p>
          </li>
        </ul>
    
        <input type="text" placeholder="请输入消息" v-model="msg">
        <button @click="sendMsg">发送</button>
      </div>
    </template>
    
    <script>
    // npm install ws
    const ws = new WebSocket('ws://localhost:8080')
    
    export default {
      name: "Two",
      data(){
        return{
          msg: '',
          username: '',
          msgList: []
        }
      },
      methods:{
        sendMsg(){
          const msg = this.msg
          ws.send(JSON.stringify({
            id: new Date().getTime(),
            username: this.username,
            dateTime: new Date().getTime(),
            msg: this.msg
          }))
        },
        handleWsOpen(e){
          console.log('websocket open', e)
        },
        handleWsClose(e){
          console.log('websocket close', e)
        },
        handleWsError(e){
          console.log('websocket error', e)
        },
        // 接收消息
        handleWsMessage(e){
          // console.log('websocket message', e)
          let msg = JSON.parse(e.data)
          this.msgList.push(msg)
          console.log(msg)
        },
      },
      mounted() {
        this.username = localStorage.getItem('username')
        if(!this.username){
          this.$router.push('/login')
        }
        // 事件绑定
        ws.addEventListener('open', this.handleWsOpen.bind(this), false);
        ws.addEventListener('close', this.handleWsClose.bind(this), false);
        ws.addEventListener('error', this.handleWsError.bind(this), false);
        ws.addEventListener('message', this.handleWsMessage.bind(this), false);
      }
    }
    </script>
    <style scoped></style>
    
  • 后端
    新建index.js文件

    const Ws = require('ws')
    
    // 立即执行函数
    ;((Ws)=>{
        const server = new Ws.Server({port: 8080});	// 要和前端监听同一个端口
    	
        // 初始化函数
        const init = ()=>{
            bindEvent();
        }
    
        function bindEvent(){
            server.on('open', handleOpen);
            server.on('close', handleClose);
            server.on('error', handleError);
            server.on('connection', handleConnection);
        }
    
        function handleOpen(){
            console.log('wb open')
        }
        function handleClose(){
            console.log('wb close')
        }
        function handleError(){
            console.log('wb error')
        }
        // 消息接收
        function handleConnection(ws){
            console.log('wb connection')
            ws.on('message', handelMsg)
        }
        // 消息处理
        function handelMsg(msg){
            // c : 表示每个客户端
            let oMsg = msg.toString()
            server.clients.forEach((c)=>{
                c.send(oMsg)
            })
        }
        init()
    })(Ws);
    

HTTP协议以及浏览器原理

http协议

web端发送请求报文(请求头、URL、请求方法、请求数据、协议版本) ==》 服务器端返回数据(响应头、协议版本、响应数据、响应代码(success/error)、服务器信息)

http协议是无状态协议 导致了 cookies的产生(用于验证服务器的合法性)

http协议版本

  • 1.0 只能
  • 1.1
  • 2.0

浏览器原理

  1. 输入网址
  2. DNS域名解析(有该网页则返回,没有返回错误信息)
  3. TCP三次握手(建立连接)
  4. HTTP请求(获取资源) =》 HTTP响应
  5. 浏览器渲染页面。HTML解析 =》 DOM树,css =》css规则树,两者结合渲染成render树,浏览器通过render对页面进行渲染布局

http缓存

  • 强缓存(本地缓存)和协商缓存(弱缓存)
  • 网页请求资源
    • 没有缓存 =》 使用服务器资源 =》返回请求资源。
    • 有缓存 =》强缓存命中 =》使用缓存内容 =》返回资源。
    • 强缓存未命中 =》协商缓存命中,使用缓存内容;未命中 =》服务器资源 =》返回资源

浏览器如何渲染页面

  • html解析成DOM树,CSS解析成CSS规则树
  • 浏览器将CSS规则树附着在DOM树上,结合生成Render渲染树
  • 生成布局:浏览器解析渲染树节点的位置和大小,在屏幕上渲染出所有节点(重排)
  • 将布局绘制在屏幕上,生成整个页面(重绘)

Http请求头和响应头

  • 请求头
    • Accept(浏览器可接受服务器返回数据类型, text/html, ‘/’ 代表所有)
    • Accept-Encoding(gzip, deflate 申明浏览器接受的编码方法)
    • Connection(keep-alive / close , 当浏览器与服务器建立了TCP连接,keep-alive表示不断开,下次请求服务器使用相同的TCP连接)
    • Host(服务器ip和端口)
    • Referer(浏览器的地址)
    • User-Agent(浏览器的操作系统和名称、版本)
    • Cookie(存储用户信息)
  • 响应头
    • Content-Type(Content-Type:text/html;charset=UTF-8):资源文件的类型以及编码方式
    • Content-Encoding: 编码格式
    • Date:服务器时间
    • Server:服务器信息
    • Connection(keep-alive/ close)
    • Access-Control-Allow-Origin:指定可以访问服务器的网址(Access-Control-Allow-Origin: *代表所有网站可以跨域资源共享)
    • Access-Control-Allow-Methods(GET, POST, DELETE, PUT)
    • Access-Control-Allow-Credentials(是否允许发送cookie)

同源策略

协议(http)+域名(www.a.com)+端口号(8080)三者一致,其中一个不同就不是同源,需要跨域

跨域的方法

  • JSONP(利用script标签不存在跨域的方式)
  • CORS(服务器配置响应头Access-Control-Allow-Origin)
  • websocket
  • 反向代理(中间件)

CSS

BFC(块级格式化上下文)

  • bfc就是一个隔离容器,日期里面的子元素不会影响到外面的元素
  • bfc的原则:如果一个元素具有bfc,那么内部元素任何操作都不会影响到外部元素
  • 如何触发bfc(一般给内部元素加overflow:hidden):
    float:none
    overflow: visible
    display:inline-block、table-cell
    position: absolute、fixed

清除浮动有哪些方式

// li标签会自己浮动,没有包裹在ul标签里面
<style>
    *{margin: 0; padding: 0}
    ul{
      list-style: none;
      border: 10px solid red;
    }
    li{
      width: 100px;
      height: 100px;
      background: yellow;
      float: left;
    }
  </style>
  <body>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </body>
// 方法1:触发bfc清楚浮动
    ul{
      overflow: hidden;
    }
// 方法2:after方式
	ul:after{
      content: '';
      display: block;
      clear: both;
    }

position有哪些值,分别根据什么定位

  • static:默认值,代表没有定位
  • fixed:固定定位,相对于浏览器窗口进行定位,(使用left,right, top,bottom)
  • absolute:相对于第一个有relative父元素定位
  • relative:相对定位,相对于自身定位,不脱离文档流(位置改变了,其原有位置不会被其他元素占据)

flex布局

flex 表示 flex-grow(设置扩展比例), flex-shrink(设置收缩比例), flex-basis(不伸缩的情况下子容器的原始尺寸)

flex:1: (1, 1, 0%) 不管内容多少,都是平分空间

flex:auto: (1, 1, auto) 根据内容的大小来分,不是均分的(除非内容都是一样,才均分)

flex:0: (0, 1, 0%)可缩小,不可扩大

flex:none:(0, 0, auto) 不可扩大 不可缩小

CSS样式优先级(权重)

  • !import > 行内样式 > id选择器 > class选择器 > 标签选择器 > 通配符

盒子模型

在html页面中所以元素都可以看成是一个盒子

盒子组成

  • 内容content
  • 内边距padding
  • 边框border
  • 外边距margin

盒模型类型

  • 标准盒模型 margin+border+padding+content
  • IE盒模型 margin+content(padding + border)

控制盒模型的模式:box-sizing:content-box(默认值), border-box(IE盒模型)

隐藏元素的方法

  • display: none(元素消失,不占空间)
  • opacity: 0 (透明度,占空间)
  • visibility: hidden(元素消失,占空间)
  • position: absolute(将元素移除页面)
  • clip-path(将元素剪掉)

px和rem区别

  • px: 像素,绝对单位长度,每个显示器像素大小一样
  • rem:相对单位,相对html根节点font-size的值改变,html的根节点默认16px :font-size = 62.5% => 1rem = 10px (16px * 62.5% = 10px)
  • em: 相对父元素的font-size改变

重绘和重排(回流)

  • 重排(回流):布局引擎根据所有样式计算出盒模型在页面的位置和大小
  • 重绘:计算好盒模型在页面的位置和大小以及其他属性,然后根据每个盒模型的特性进行绘制
  • 对DOM的大小、位置修改,重排
  • 对DOM的样式修改,重绘

元素水平居中方式

  • 定位+margin
  • flex布局
  • grid布局
  • table布局

例:

<div id="app">
    <div id="sub"></div>
</div>
	 <!--   定位+margin     -->
        #app{
            width: 400px;
            height: 400px;
            position: relative;
            border: 3px solid royalblue;
        }
        #sub{
            position: absolute;
            width: 100px;
            height: 100px;
            background-color: red;
            top: 0;
            right: 0;
            left: 0;
            bottom: 0;
            margin: auto;
        }

H5C3新特性

H5新特性

  1. 语义化标签
  2. 新增音频视频
  3. 画布canvas
  4. localStorage和sessionStorage
  5. 表单控件email url search
  6. 拖拽释放api

css3的新特性

  1. 选择器:属性选择器、伪类选择器、伪元素选择器
  2. 增加了媒体查询
  3. 文字阴影
  4. 边框
  5. 盒子模型box-sizing
  6. 渐变
  7. 过度
  8. 自定义动画
  9. 2D和3D

CSS属性继承

css三大特性 继承(子元素继承父元素属性)、层叠、优先级

CSS可以继承的属性

  • 文字:font
  • 文本:line-height
  • 元素可见性:visibility: hidden
  • 列表属性: list-style

预处理器

css的预处理器增加了函数、变量等,便于维护

  • SASS
  • LESS

例:

<div id="app">
    <span></span>
</div>

#app{
    span{
        // 这里写span的样式
    }
}

@global: #eee;	// 定义全局变量,利于维护使用	
#app{
    color: @global;
}

Node.js

入门

数据库连接,登录小案例

<form action="http://localhost:8080" method="post">
    <input type="text" class="username" name="username" />
    <input type="password" class="password" name="password"/>
    <input type="submit" value="提交" />
</form>
const mysql = require('mysql')
const http = require('http')
const queryString = require('querystring')

const server = http.createServer((req, res)=>{
    let postVal = "";
    req.on("data", (chunk)=>{
        postVal+=chunk;
    })
    req.on('end', ()=>{
        let formVal = queryString.parse(postVal)
        let username = formVal.username;
        let pwd = formVal.password;
        console.log(username, pwd)

        // 连接数据库
        const conn = mysql.createConnection({
            host: 'localhost',
            port: 3306,
            user: 'root',
            password: '116054',
            database: 'test'
        })
        conn.connect();
        conn.query('select * from user where username=? and password=?', [username, pwd], (err, result, fields)=>{
            if(err) throw err;
            console.log(result);
            if(result.length>0){
                res.writeHead(200, {'Content-Type': 'text/html;charset=utf8'});
                res.write('登录成功')
                res.end();      // 关闭http连接
            }
        });
        conn.end();     // 关闭数据库连接
    })
})

server.listen(8080)     // 端口监听

express

处理404

// catch 404 and forward to error handler
// 方法一
var createError = require('http-errors');
app.use(function(req, res, next) {
  next(createError(404));
});
// 方法二
// 所有路由之后配置处理404
app.use((req, res, next)=>{
  console.log('错误', err)
  res.status(404).send('404 Not Found')
})

Java

面向对象和面向过程

面向过程:更注重任务顺序(简单高效)

面向对象:更注重参与者(易于维护、拓展)

封装、继承、多态

  • 封装:内部细节对外部调用透明,外部调用无需修改或关心内部实现
    1.javabean的属性私有,提供getset对外访问数据
    2.orm框架:不需要关心链接如何建立,只需要调用mybatis,调方法即可

  • 继承:继承基类方法,进行拓展

  • 多态:基于对象所属类的不同,外部对同一个方法调用,实际执行的逻辑不同

    父类类型 变量名 = new 子类对象
    变量名.方法名();
    

JDK、JRE、JVM

  • jdk(java开发工具)
  • jre(java运行环境)
  • jvm(虚拟机)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VuzCPhs5-1690204973231)(C:\Users\11605\AppData\Roaming\Typora\typora-user-images\image-20230711192250851.png)]

==和equals

  • ==对比的是栈中的值:基本数据类型的变量值,引用类型是堆内存对象的地址
  • equals: 直接对比的值:value

final的作用

  • 修饰类:类不可被继承
  • 修饰方法:不可被子类覆盖,但可以重载
  • 修饰变量:一旦被赋值不可被修改

String StringBuffer StringBuilder

  • String是final修饰的,每次操作都会产生新对象(赋值变量会创建一个新的内存地址)
  • string buffer和string builder都是在原对象操作
  • buffer是线程安全的,builder是线程不安全的
  • stringbuffer方法都是synchronized修饰的
  • 性能:string builder > stringbuffer > string
  • 场景:经常改变字符串就使用后两者,优先使用stringbuilder,多线程使用共享变量时使用string buffer

重载和重写的区别

  • 重载:发生在同一个类中,方法名必须相同,参数类型、个数、顺序不同,方法返回值和访问修饰符可以不同

  • 重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于父类,抛出的异常范围小于父类;父类方法修饰符是private,子类就不能重写该方法

    public int add(int a, String b)
    public String add(int a, String b)
    // 编译报错
    

List和Set的区别

  • list: 有序,按对象进入顺序保存,可重复,允许多个null对象,可遍历,可使用get(int index)获取元素

  • set: 无序,元素不可重复, 最多一个null对象,只能使用iterator获取元素文章来源地址https://www.toymoban.com/news/detail-601934.html

    List<Object> list = new ArrayList<>();
    

hashCode与equals

ArrayList和LinkedList区别

  • Arraylsi:基于动态数组,连续内存,下标(随机)访问,扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组
  • LinkedList: 基于链表,存储分散在内存中,适合做数据插入和删除,不适合查询(一般不用)

到了这里,关于前端八股文的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【面试】前端面试八股文

    前端思维导图 优点 大可爱html+css+js+node 全面可下载 千峰html+css 简洁漂亮 千峰js 简洁漂亮 (1)标签引用 (2)文件引用 解释型语言:JS不需要被编译为机器码而是直接执行,开发轻松 动态型语言:JS变量与任何值类型都不关联,都可以重新分配类型值 弱类型语言:变量数据

    2024年02月02日
    浏览(56)
  • 前端常见面试八股文

    1、H5新增标签有哪些? 一、语义化标签 header、footer、nav、aside、section、article 语义化的意义? 1、更适合搜索引擎的爬虫爬取有效的信息,利于SEO。 2、对开发团队很友好,增加了标签的可读性,结构更加的清晰,便于团队的开发和维护。 二、多媒体标签 视频标签:video 属性

    2023年04月08日
    浏览(85)
  • 前端八股文

    去掉ESLint校验: package.json 中的extends去掉eslint:commends 引入icon图标 state: 存放数据 mutations: 同步操作,写方法用于改变state里面的数据,vue可以监听数据的改变进行更新(相当于methods) actions:所有异步操作都放在这里,改变的数据不能够被vue监听 getters: 进行逻辑处理(相当于

    2024年02月16日
    浏览(42)
  • 前端基础面试题八股文

    代码结构: 使页面在没有css的情况下,也能够呈现出好的内容结构 有利于SEO: 爬虫根据标签来分配的权重,因此可以和搜索引擎建立良好的沟通,帮助爬虫抓取更多的有效信息 方便其他设备解析: 如屏幕阅读器、盲人阅读器、移动设备等,以有意义的方式来渲染页面 便于

    2024年02月07日
    浏览(48)
  • 前端八股文(性能优化篇)

    目录 1.CDN的概念 2.CDN的作用 3.CDN的原理   4.CDN的使用场景 5.懒加载的概念 6.懒加载的特点 7.懒加载的实现原理 8.懒加载与预加载的区别 9.回流与重绘的概念及触发条件 (1)回流 (2)重绘 10. 如何避免回流与重绘? CDN(内容分发网络)是指一种通过互联网互相连接的电脑网

    2024年01月20日
    浏览(35)
  • 前端面试题八股文汇总(最新)

    前言:小伙伴们,本篇文章是博主自己在面试过程中的一些面试题的记录,自己在总结回顾记录的同时希望也能帮助到你们,可以结合对应的知识点去理解和查看!有什么不对的地方欢迎伙伴们指正!大家一起学习!一共有五大回合,如果在后续面试过程中还会持续更新!

    2023年04月08日
    浏览(50)
  • 前端八股文(三)—— 性能优化部分

    1、懒加载的概念 懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能。 如果使

    2024年02月22日
    浏览(55)
  • 面试 JavaScript 框架八股文十问十答第七期

    作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新! ⭐点赞⭐收藏⭐不迷路!⭐ 1)原型修改、重写 在 JavaScript 中,可以通过修改或重写对象的原型来改变对象的行为。原型修改指的是直接修改对象的原型,而原型

    2024年02月20日
    浏览(51)
  • 史上最全前端八股文来了

    由于最近比较忙活没时间学习新东西,现在得空想着能不能好好整理出一些有用的东西,让记忆深刻一点,免得到时候实习找工作面试的时候一问三不知,也希望大家能指正出错误和对大家有点帮助,一起进步,加油奥里给!!! 那么废话不多说直接进入正题,如果觉得可以

    2024年02月08日
    浏览(45)
  • 前端八股文everybody准备好了没

    由于最近比较忙活没时间学习新东西,现在得空想着能不能好好整理出一些有用的东西,让记忆深刻一点,免得到时候实习找工作面试的时候一问三不知,也希望大家能指正出错误和对大家有点帮助,一起进步,加油奥里给!!! 那么废话不多说直接进入正题,如果觉得可以

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包