赞
踩
闭包是什么:JS中内层函数可以访问外层函数的变量,外层函数无法操作内存函数的变量的特性。我们把这个特性称作闭包。
闭包的好处:
闭包的弊端:内层函数引用外层函数变量,内层函数占用内存。如果不释放内存,过多时,易引起内存泄露。
解决办法:无法自动销户,就及时手动回收,使用后将函数的引用赋null。
1、深拷贝与浅拷贝的区别?
拷贝的层级不同,深拷贝是指每一层数据的改动都不会影响原对象和新对象,浅拷贝只有第一层的属性变动不互相影响,深层的数据变动还会互相影响。
2、实现拷贝的方法有哪些?
浅拷贝:数组可以用拓展运算符[...arr],或者slice().浅拷贝对象可以用Object.assign({},obj)
深拷贝:JSON.parse(JSON.stringify(obj)),或封装递归方法,或使用第三方库的方法,比如 JQuery的$.extend({},obj),或者lodash 的cloneDeep
3、JSON.parse(JSON.stringify(obj))处理的缺点?
constructor
;判断空对象
区分数据类型
- let a = [1,2]
- Object.prototype.toString.call(a) // '[object Array]'
call 和 apply 都是可以改变this 指向的问题, call 方法中传递参数要求一个 一个传递参数。 但是apply 方法要求传递参数是一个数组形式。
- let a = {
- name: 'sunq',
- fn:function(action){
- console.log(this.name + ' love ' + action);
- }
- }
- let b = {name:'sunLi'}
-
- // 正常的this指向
- a.fn('basketball'); // sunq love basketball
- // 改变this指向,并体现call与apply的区别
- a.fn.apply(b,['football']); // sunLi love football
- a.fn.call(b,'football'); // sunLi love football
还是上面的示例,bind也可以实现call和apply的效果。bind的不同之处在于bind会返回一个新的函数。如果需要传参,需要再调用该函数并传参
a.fn.bind(b)('piano'); // sunLi love piano
使用iframe可以实现,变量隔离
localStorage/sessionStorage是window的属性,cookie是document的方法
slice和splice的区别?
数组如何滤重?
[...new Set(arr)]
当页面上的一个元素被点击时,先从document向下一层层捕获到该元素。然后再向上冒泡,一层层触发。
事件委托是将事件写在父级元素上,e.target是事件捕获时那个最小的元素,即选中的元素。所以可以根据e.target操作选中的元素。这样不需要给每个子元素绑定事件,代码更加简约。
js通过原型链模拟实现面向对象,比如通过实例化一个构造函数可以给每个对象挂载自己专属的属性,通过给类的prototype上赋方法是所有对象所共有的方法。每次实例化不再赋值原型链上的方法。
区别:防抖只会在最后一次事件后执行触发函数,节流不管事件多么的频繁,都会保证在规定时间段内触发事件函数。
原理是维护一个定时器,将很多个相同的操作合并成一个。规定在delay后触发函数,如果在此之前触发函数,则取消之前的计时重新计时,只有最后一次操作能被触发。例如:实时搜索的input,一直输入就不发送。
- let input = document.querySelector("input");
- let time = null;//time用来控制事件的触发
-
- input.addEventListener('input',function(){
- //防抖语句,把以前的定时删除,只执行最后一次
- if(time !== null){
- clearTimeout(time);
- }
- time = setTimeout(() => {
- console.log(this.value);//业务实现语句,这里的this指向的是input
- },500)
- })
原理是判断是否达到一定的时间来触发事件。某个时间段内只能触发一次函数。例如:在指定的时间内多次触发无效
- //节流
- function throttle(fn, time) {//连续触发事件 规定的时间
- let flag = false;
- return function () {
- //使用标识判断是否在规定的时间内重复触发了函数,没有就触发,有就不触发
- if (!flag) {//不为假时 执行以下
- fn();//触发事件
- flag = true;//为真
- setTimeout(() => {//超时调用(在规定的时间内只执行一次)
- flag = false;
- }, time);
- }
- }
- }
-
- mybtn.onclick = throttle(btn, 3000);//单击事件 节流(btn,3s时间)
使用场景
两者主要区别在于时间间隔的处理方式和触发函数的执行时机。防抖是等待一段时间后执行事件,如果在这段时间内再次触发事件,会重新等待;而节流是每隔一定时间执行一次事件,不管这段时间内触发了多少次事件。
防抖适合处理连续触发的事件,例如输入框的实时搜索;而节流适合限制高频触发的事件,例如滚动事件、鼠标移动事件。
在 JavaScript 中,可以使用原型继承、构造函数继承和组合继承等方式来实现继承。下面分别介绍这些方式的实现方法:
1. 原型继承
原型继承是 JavaScript 中最基本的继承方式,通过将一个对象的原型设置为另一个对象来实现继承。
- function Parent() {
- this.name = 'Parent';
- }
-
- Parent.prototype.sayHello = function() {
- console.log('Hello from Parent');
- };
-
- function Child() {
- this.name = 'Child';
- }
-
- Child.prototype = Object.create(Parent.prototype);
- Child.prototype.constructor = Child;
-
- const child = new Child();
- child.sayHello(); // 输出:Hello from Parent
2. 构造函数继承
构造函数继承通过在子类构造函数中调用父类构造函数来实现继承。这种方式可以实现实例属性的继承,但无法继承父类原型上的方法。
- function Parent(name) {
- this.name = name;
- }
-
- function Child(name, age) {
- Parent.call(this, name);
- this.age = age;
- }
-
- const child = new Child('Child', 10);
- console.log(child.name); // 输出:Child
3. 组合继承
组合继承结合了原型继承和构造函数继承的优点,通过在子类构造函数中调用父类构造函数并设置子类原型为父类实例来实现继承。
- function Parent(name) {
- this.name = name;
- }
-
- Parent.prototype.sayHello = function() {
- console.log('Hello from Parent');
- };
-
- function Child(name, age) {
- Parent.call(this, name);
- this.age = age;
- }
-
- Child.prototype = new Parent();
- Child.prototype.constructor = Child;
-
- const child = new Child('Child', 10);
- child.sayHello(); // 输出:Hello from Parent
4. ES6 Class 继承
ES6 引入了 Class 语法,提供了更加简洁和易读的继承语法。
- class Parent {
- constructor(name) {
- this.name = name;
- }
-
- sayHello() {
- console.log('Hello from Parent');
- }
- }
-
- class Child extends Parent {
- constructor(name, age) {
- super(name);
- this.age = age;
- }
- }
-
- const child = new Child('Child', 10);
- child.sayHello(); // 输出:Hello from Parent
避免循环插入dom,比如table的行。可以js循环生成多个dom后,一次性插入。
- 方法一:
- .pop{
- width: 300px;
- height: 300px;
- position: fixed;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- margin: auto;
- border: 1px solid red;
- }
-
- 方法二:
- .chartLengend { // 父元素
- width: 60px;
- height: 40px;
- position: relative;
- .line { // 子元素
- width: 100%;
- height: 3px;
- background-color: #DEA182;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- border-radius: 2px;
- }
- }
- .class:last-child{}
- .class:first-child{}
-
- a:link {color:green;}
- a:visited {color:green;}
- a:hover {color:red;}
- a:active {color:yellow;}
- // :before用于在某个元素之前插入某些内容。
- // :after用于在某个元素之后插入某些内容。
- css
- p:before{
- content:"Read this: ";
- }
-
- html:
- <p>I live in Ducksburg</p>
-
- 页面展示:
- Read this: I live in Ducksburg
-
- F12看dom中:
- before
- Read this: I live in Ducksburg
单页面对一个入口DOM通过路由去更改内容,整个应用只有一个html页面
SPA优点:用户体验好,没有页面切换就没有白屏情况;
SPA缺点:首屏加载慢,不利于SEO
SPA弥补:通过压缩、路由懒加载缓解首屏慢;通过SSR 服务器端渲染解决SEO问题;
2.1、什么是组件?
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
声明组件
- // 定义一个名为 button-counter 的新组件
- Vue.component('button-counter', {
- data: function () {
- return {
- count: 0
- }
- },
- template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
- })
使用组件(把组件当作自定义元素)
- <div id="components-demo">
- <button-counter></button-counter>
- </div>
引入组件
new Vue({ el: '#components-demo' })
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:
组件内部声明prop
- Vue.component('blog-post', {
- props: ['title'],
- template: '<h3>{{ title }}</h3>'
- })
父组件里调用,并给prop赋值,传递到组件内部
<blog-post title="My journey with Vue"></blog-post>
其实就是通过在父组件声明方法,并绑定在子组件上。以子组件内部触发方法的形式,向父组件传参,实现子向父传值的效果。如下
父组件中声明方法,并绑定在子组件上
- <template>
- <lineChart v-on:getQuotaVal="getQuotaVal"></lineChart>
- </template>
- <script>
- methods: {
- // 本事件用来监听折线图子组件,从子组件拿到指标数据
- getQuotaVal:function(obj){
- this.lineDateType = obj.lineDateType; // 这样父组件就拿到了,子组件的obj数据
- }
- },
- </script>
子组件触发方法
- that.val = {};
- that.$emit('getQuotaVal',that.val); // 将子组件的数据发送过去;
2.4、兄弟组件间交互
兄弟组件间交互可以通过三种方式,具体如下:
1、通过共同父组件传递
比如兄弟组件A和B,有一个共同父组件P。A要向B发送数据,可以先发消息给P(this.$emit),P接收到消息(P绑定在A上的方法接收方法)。P再发消息给B(P修改B组件的自定义属性的值),B接收数据(Props变量接收)。
2、使用
EventBus(事件总线)
,vue.$bus.on和emit方法。
初始化——全局定义,可以将eventBus绑定到vue实例的原型上,也可以直接绑定到window对象上.
- //main.js
- Vue.prototype.$EventBus = new Vue();
触发事件
this.$EventBus.$emit('eventName', param1,param2,...)
监听事件
- this.$EventBus.$on('eventName', (param1,param2,...)=>{
- //需要执行的代码
- })
移除监听事件
为了避免在监听时,事件被反复触发,通常需要在页面销毁时移除事件监听。或者在开发过程中,由于热更新,事件可能会被多次绑定监听,这时也需要移除事件监听。
this.$EventBus.$off('eventName');
3、通过Vuex实现交互
比如兄弟组件A和B,A为发送方。
则A改动Vuex state中的变量(this.$store.commit('set',{name:xx})),
B组件中通过computed和watch配合使用(this.$store.state.name),监听name变动即可。
v-if控制Dom是否存在,v-show控制样式
vuex是一个状态管理工具,集中式的管理所有组件的状态数据。统一的去管理组件。
比如,组件A、B、C需要交互变量name、sex。可以将name、sex放在Vuex的state属性中。
限制A组件通过commit方法触发mutation里的函数来改变组件状态。组件B、C使用computed、watch监听数据的变化进行操作(接收数据)。
如下举个loading组件的栗子,loading组件与路由区域平级
loading组件内部,根据Loading数据,控制DOM显隐
- <template>
- <div class="cover" v-show="Loading">
- <div>加载中</div>
- </div>
- </template>
-
- <script>
- import Store from '../../store'
- export default {
- name: "Loading",
- computed:{
- Loading(){
- return Store.state.Loading;
- }
- }
- }
- </script>
vuex集中管理状态,创建一个叫store的js文件
- import Vuex from 'vuex';
- Vue.use(Vuex);
-
- export default new Vuex.Store({
- state: {
- // Loading组件
- Loading:false,
- },
- mutations: {
- // Loading组件
- ChangeLoading:function (State,Value) {
- State.Loading = Value;
- }
- },
- });
需要跟loading组件交互的组件中,直接去操作Vuex的状态即可
- import Store from '../../store'
- Store.commit("ChangeLoading",true);
Mutation用于修改state中的状态,通过执行mutation来实现对状态的同步修改。只能执行同步操作,一般用于处理简单的状态修改。在组件中通过commit()
方法来触发mutation的执行。接收一个参数state,即当前的state对象,以及可选的payload参数作为载荷传入。在mutation中直接修改state的值,将其作为一个原子操作。
Action用于执行异步操作,可以包含任意的异步操作逻辑(例如发起API请求、异步数据处理等)。可以用于处理复杂的业务逻辑和流程控制。在组件中通过dispatch()
方法来触发action的执行。接收一个参数context,即一个和store实例具有相同方法和属性的context对象,可以通过context去调用其他的action、mutation等。通过commit方法触发mutation来修改state的值,实现对状态的同步修改。
computed
computed中的属性本质上是一个变量。一个特殊的变量,它由其他变量计算或者说赋值而来。它依赖于其他变量的变化,无需也无法像普通变量一样直接赋值修改。
watch
watch用来监听某个变量,当被监听的值发生变化时,执行相关操作。
与computed的区别是,computed是一个变量,watch用来监听变量。computed监听构成它的变量的变化,导致自己这个变量变化。watch单纯监听某个变量变化,触发事件。computed方法体内只能返回构成它的变量构成,而watch里可以进行任何操作。
- data(){
- return{
- 'first':2
- }
- },
- watch:{
- first(){
- console.log(this.first)
- }
- },
双向绑定主要指修改数据时,无须操作DOM,视图会自动刷新。操作视图时绑定的数据也会跟随变动。vue数据双向绑定是通过数据劫持结合订阅者,发布者的方式来实现的,通过Object.defineProperty()来劫持各个属性的setter,getter,当数据变动时发布消息给订阅者,触发相应的监听回调
数据 => 视图
vue在初始化实例时,会用Object.defineProperty方法,给所有的数据添加setter函数,实现对数据变更的监听。当数据被修改时,生成新的虚拟DOM树,跟老的虚拟DOM对比,根据对比结果找出需要更新的节点进行更新。
视图 => 数据
从视图到数据较为简单,视图变化后触发监听如oninput等,在绑定的方法中修改数据。
缺陷:数据如果为对象直接新增属性,如果为数组通过下标操作数组项,页面无法触发更新。
原因: Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。关于数组作者通过重写push/pop/shift/unshift/splice/reverse/sort这些方法来实现数据的相应绑定,其余的操作无法触发页面更新;
对策:关于对象可以通过Vue.$set(obj,key,value),组件中通过this.$set(obj,key,value)实现新增,修改属性vue可以相应更新视图。关于数组也可以通过Vue.$set(obj,key,value),或者作者重写的那些方法来操作;
如果有些数据需要在初始化时就渲染的,比如select下拉框的下拉内容,在mouted中请求。好处如下
路由守卫可以在全局范围内设置,也可以在单个路由配置中设置。
在 Vue Router 中,路由守卫可以分为以下几种类型:
全局前置守卫(Global Before Guards):
router.beforeEach(to, from, next)
:在路由导航触发之前调用。可以用于全局的权限验证、导航控制等。全局解析守卫(Global Resolve Guards):
router.beforeResolve(to, from, next)
:在导航被确认之前调用,也就是在 beforeEach
之后调用,但在路由组件渲染之前。只在导航被确认之前调用一次。全局后置钩子(Global After Hooks):
router.afterEach(to, from)
:在每次路由导航完成之后调用,不关心导航的成功与否。路由独享守卫(Per-Route Guard):
beforeEnter(to, from, next)
:在单个路由配置中使用,用于对特定路由进行拦截。组件内的导航守卫(Component’s Navigation Guards):
beforeRouteEnter(to, from, next)
:在路由进入前,在组件实例化之前调用。beforeRouteUpdate(to, from, next)
:在当前路由改变,但是该组件被复用时调用。beforeRouteLeave(to, from, next)
:在路由离开前调用,导航离开该组件的对应路由时调用。- this.$router.push({
- path: '/url',
- query: {
- par:parid
- }
- })
接受参数
var parid = this.$route.query.par;
- 父:beforeCreate 首先初始化父原素
- 父:created 父原素挂载数据
- 父:beforeMounte 父原素开始挂载dom,tpl里遇到子组件
- 子:beforeCeate 子组件开始挂载数据
- 子:created 子元素数据挂载成功
- 子:beforeMount 子元素开始挂载dom
- 子:mounted 子元素dom挂载结束
- 父:mounted 父原素dom挂载结束
- 父:beforeUpdate 下面开始类似于dom事件流
- 子:beforeUpdate
- 子:updated
- 父:updated
- 父:beforeDestory
- 子:beforeDestory
- 子:destroyed
- 父:destoryed
子元素在父元素挂载dom时,开始加载。子元素一直到加载完毕dom后,父原素结束dom挂载。后面就类似于dom事件流了。
JS支持两种模块化方式,commonjs和ES6。
commonjs用于nodejs,同步加载模块。ES6的import为了不卡顿,异步加载模块。
新版Nodejs也支持使用import,但是需要修改文件后缀名为.mjs,或者在package.json中,制定type字段为module。
Vuex 存储的状态是在内存中保存的,当页面刷新或者跳转时,状态会被重置。为了避免数据丢失,你可以考虑使用持久化存储(如 localStorage 或 sessionStorage)来保存状态,在页面加载时从持久化存储中恢复状态。
Provide 和 Inject可以将父组件传给所有后代组件
在 Vue 3 中,provide
和 inject
是响应式的,但在 Vue 2 中它们不是响应式的。
1)Vue 3 中的响应式
在 Vue 3 中,使用
provide
和inject
提供的数据是响应式的,这意味着如果提供的数据发生变化,所有依赖这些数据的组件都会自动更新。这种响应式是通过 Vue 3 中的响应式系统来实现的。2)Vue 2 中的非响应式
在 Vue 2 中,
provide
和inject
提供的数据不是响应式的,这意味着如果提供的数据发生变化,依赖这些数据的组件不会自动更新。这是因为 Vue 2 中的provide
和inject
是基于原型链来实现的,而不是响应式系统。
vue的生命周期是vue实例从创建到销毁的一系列过程。每个过程都有相对应的钩子函数,分为 beforeCreate(创建前),created(创建后),beforeMount(加载前),mounted(加载后),beforeUpdate(更新前),updated(更新后),beforeDestroy(销毁前),destroyed(销毁后)。
当使用keep-alive时,有activated和 deactivated两个钩子函数。当组件用keep-alive包裹时切换文件时不会进行销毁,而是进行缓存并执行deactivated 钩子函数,组件被激活时执行actived 钩子函数。
为保证组件的可重用性和独立性。如果直接使用一个对象作为data,则不同的组件将共享同一个data对象,如果某个组件修改了data,则会影响到其他组件,导致数据混乱。所以data必须是一个函数,每个组件实例都有自己的独立的data数据。这样每次创建组件都会返回一个新的data对象就避免了组件间共享问题。
- let a = {
- name: 'sunq',
- fn:function(action){
- console.log(this.name + ' love ' + action);
- }
- }
- let b = {name:'sunLi'}
-
- // 正常的this指向调用他的对象
- a.fn('basketball'); // sunq love basketball
- // 改变this指向
- a.fn.apply(b,['football']); // sunLi love football
-
- // 如果将a对象的fn函数改成箭头函数,this.name会是undefined
- // 箭头函数的this指向不会改变,且总是指向函数定义生效时所在的对象。
new
命令,否则会抛出一个错误。- var Person = function(name){
- this.name = name;
- }
- let sunq = new Person('sq'); // {name: 'sq'}
-
- var Person = (name) => {
- this.name = name;
- }
- let sunq = new Person('sq'); // 报错 Person is not a constructor
arguments
对象yield
命令,因此箭头函数不能用作 Generator 函数。Promise、Genarate、async\await
使用Promise.all()方法,将两个promise传入all方法,拿到异步结果再请求第三个
明明知道的语法,面试官一问我偏偏就是跟实际场景联系不到一块,
string number null undefined boolean object bigInt symbol
6、说几个ES6新增的数组的方法 详情
map 实例方法,类似于forEach,但是返回新数组
find和findIndex 实例方法,传入一个匿名函数,ruturn出符合条件的项或下标
... 拓展运算符 基本功能是将一个数组转为用逗号分隔的参数序列
7、for in和for of的区别
8、多个数据请求,如何顺序执行?
使用promise的then方法,或者写多个promise,async中使用await顺序执行。
9、proxy的理解,与defineProperty的区别?
- // es6的proxy
- let obj = {name:1,sex:2}
- let p = new Proxy(obj,{
- get:(value,key)=>{
- return 'sq的'+obj[key]
- }
- });
- p.name // sq的1
- p.sex // sq的2
-
- // es5的代理
- let newObj = {name:1,sex:2}
- Object.defineProperty(newObj,'name',{
- get:function(val){ //defineProperty中get函数没有入参
- return 'sq的' + val
- }
- })
- newObj.name // sq的undefined
- newObj.sex // 2
10、谈谈promise的原理?
2、如何通过继承扩展 element-ui 组件的功能?
通过继承扩展 element-ui 组件的功能_elementui扩展组件_在厕所喝茶的博客-CSDN博客
- $("#id").children().eq(3).remove();
-
- // 获取多个class中的某一个
- $(".className").eq(n).attr("class") // 可行
- $(".className")[n].attr("class") // 不可行
window.onload
必须等到页面内包括图片的所有元素加载完毕后才能执行。$(document).ready()
是DOM结构绘制完毕后就执行,不必等到加载完毕。通常简写为$()
总结:ready事件在load事件加载之前完成。
- // 方式一
- $("#id").on('click',function(){});
- // 方式二
- $("#id").click(function(){});
- // 方式三
- $("#id").bind("click",function(){});
4、Jquery常用动画?
pull、commit、push、reset、merge、log、branch、stash
stash如何使用?
git reset --soft 版本号
git reset --hard 版本号
soft会退后,代码改动在本地还保存的有。hard会删除本地改动,彻底抹去该版本的痕迹。详情
将自己分支合到目标分支前,最好先将目标分支合到自己分支上处理完冲突,再将自己的分支合回目标分支。
个人理解,敏捷开发就是把一个大需求拆为多个独立的小需求。每个小需求可独立开发、测试、上线,循序渐进的完成整个系统。每个版本的周期可能比较短,比如2周,或者4周。
比如某公司需要开发维护一个巨大的平台,可能把平台外包给多个公司干。如果用如上方法,并行开发,可显著缩减工期。
如果想要保证每个版本又快又顺利的上线,需要有完善的角色支持和流程规范。
个人理解,当团队稍大,工期很紧时,如何有条不紊的保证版本质量就需要一套有效的流程了。
比如一个团队同时收到3个需求,每个需求分发给多个前后端开发。作为版本负责人或者项目负责人,如何把控每个人的代码质量、完成进度、过程留痕、风险规避,其实是有难度的。
一个需求如果经过,需求澄清、方案设计、设计评审、需求传递、版本排期/评审、开发划分、版本开发、测试用例评审、内部测试、代码评审、灰度试用&测试、版本发布、业务验收等完整的流程,可以有效地降低犯错的几率。也方便后期的查找责任人,总结各环节的问题,提升团队的工作效率,使交付越来越平稳。
部分公司面试要求中有写,维护有开源项目且具有50个star者优先。
我业余时间有开发维护一个具备管理后台/用户端/服务端的个人网站:sunq's blog
该个人网站的页面UI/功能设计,用户端/管理后台/服务端代码开发,SEO解决/首屏优化,服务器部署维护等,都由本人独立完成。目前github收获210个star
面试过程中无话可说时,可以拿出来聊聊,缓解尴尬。在面试过程中还真起了点作用,有部分面试官现场看了网站效果,评价网站整体风格简洁唯美。觉得我有独立学习的能力和摸索尝试的习惯,知识面较宽,得到过一些鼓励。
博客的代码全部开源:源码Github地址
TCP面向连接(如打电话要先拨号建立连接)提供可靠的服务,UDP是无连接的,即发送数据之前不需要建立连接,UDP尽最大努力交付,即不保证可靠交付。
UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
每一条TCP连接只能是一对一的,UDP支持一对一,一对多,多对一和多对多的交互通信。
UDP分组首部开销小,TCP首部开销20字节,UDP的首部开销小,只有8个字节。
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流,UDP是面向报文的一次交付一个完整的报文,报文不可分割,报文是UDP数据报处理的最小单位。
UDP适合一次性传输较小数据的网络应用,如DNS,SNMP等。
安装时 --save -dev会放在devDependencies中,--save放在dependencies
devDependencies中安装的是开发环境使用的包,比如eslint、vue-cli-serve;
dependencies中安装的是生产和开发环境下都需要使用的包,比如vue、element、vant等
devDependencies中的依赖模块,在生产环境下不会被打入包内
首先判断是接口慢,还是页面慢。如果接口慢,后端优化。
如果前端页面加载慢,看是否是因为图片等资源过大,尝试替换不同格式体积的图片。定位是否是某些数据处理的函数,比较耗时。或者是否循环操作DOM,js生成dom后再批量插入。
如果页面直接卡死,就需要分析是否内存泄漏。比如大屏展示的定时刷新卡死,排查思路可如下:
使用chrome的任务管理器,操作页面观察的内存占用的变化。定位到是哪些操作,哪块代码导致内存占用飙升。
因为js并没有直接释放缓存的语法,只有靠浏览器的垃圾回收机制自动清理。我们需要做的是及时给不需要的变量赋空。
特别注意大数据的循环实例化后,变量是否及时赋空。定时器等闭包方法中是否存在内存泄漏,循环渲染地图时,是否先将之前地图数据清空等。
单页面一般不会某个页面加载慢,一般都集中在首屏加载时白屏较久。处理方法可参考上文中。
3、是否了解nvm?
find:find
命令用于在指定目录下递归搜索文件。
- find [路径] [选项] [表达式]
-
- find /home/user -name "*.txt"
locate:locate
命令通过搜索数据库来快速定位文件。注意,locate
命令搜索的是预先建立的数据库,因此可能会比find
命令快速,但可能不会返回最新创建或修改的文件。
- locate [文件名]
-
- locate myfile.txt
grep:grep
命令用于在文件中搜索特定的文本模式。
- grep [选项] 模式 [文件]
-
- grep "pattern" file.txt
whereis:whereis
命令用于定位二进制、源代码和帮助文件。
- whereis [选项] 文件名
-
- whereis python
which:which
命令用于查找命令的执行路径。
- which [命令]
-
- which python
在Linux中,常见的解压文件的命令通常取决于文件的压缩格式。以下是一些常用的解压命令:
解压 .tar
文件:使用 tar
命令。
tar -xvf 文件名.tar
gzip -d 文件名.gz
解压 zip 文件:
unzip 文件名.zip
解压 rar 文件:
unrar x 文件名.rar
进程(Process)和线程(Thread)是操作系统中两个重要的概念,它们之间存在密切的关系。
进程:
线程:
关系:
总的来说,进程和线程之间是包含关系,一个进程可以拥有多个线程,而线程则是在进程内执行的单元。通过线程的使用,可以更加高效地利用系统资源,提高程序的并发性和响应性。
为什么要使用superWebview?
使用响应式布局(Responsive Layout):
弹性布局(Flexbox)和网格布局(Grid Layout):
Viewport(视口)设置:
<meta>
标签来设置视口的宽度和缩放选项,以确保页面在移动设备上正确显示并且具有良好的可读性和可操作性。<meta name="viewport" content="width=device-width, initial-scale=1.0">
流式布局(Fluid Layout):
测试和调试:
JavaScript 定时器:
setInterval()
函数可以创建定时器,定期拉取数据;WebSocket 实时更新:
使用框架或库的自动刷新功能:
有空刷刷Leetcode,很多好公司一面前先让写两道算法题。
这种情况下,如果没有一点算法积累,上面的问题咱都没机会被问。
1、除了ajax还有哪些请求?await、aysic、table
2、url输入框后发生什么事
3、加密方式有哪些?对称、非对称
4、mongodb好处?
5、如何辨别ie8是否兼容?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。