部分面试题

4.QT部分面试题 继承现有控件方法: 继承自 Qt 提供的现有控件类(如QWidget等),并重写其方法来实现自定义行为。步骤创建一个新类,继承自现有的 Qt 控件类。重写需要修改的虚函数(如paintEventmouseEvent等)来实现自定义绘制或交互。在构造函数中设置控件的初始属性。示例:1.自定义按钮的背景颜色和边框。2.按钮点击时改变颜色。3.通过重写paintEvent方法自定义绘制效果。#include //用于获取控件的样式选项。 阅读详情

1、介绍影响深刻的项目,担任角色,遇到的问题,怎么解决的

2、js数据类型,区分基本类型和引用类型的方法

基本数据类型:Number 、 String、Boolean 、 Null 、undefined
引用数据类型是保存在堆内存中的对象Object: Array 、 Function 、Date 、RegExp 、Error 自定义封装的类等。

判断 
1.typeof : 用于判断基本数据类型;引用数据类型不能被准确检测(除了Function),其他都返回object字符串。

2.instanceof: 只有引用数据类型(Function 、Array、Object)被精确判断,其他基本数据类型不能被判断。 instanceof是测试一个对象在原型链中是否存在一个构造函数的prototype属性,即判断对象是否是某一数据类型的实例。

3.constructor
  constructor属性指向的是创建这个对象的构造函数,
  console.log(([]).constructor) // ƒ Array() { [native code] }
  console.log(([]).constructor === Array) //true

4.Object.prototype.toString.call()
   可以判断基本数据类型和引用数据类型 返回字符串'[object 具体类型]'
  console.log(Object.prototype.toString.call(false)) //'[object Boolean]'
            

3、元素不可见方式和使用场景


display: nonevisibility: hiddenopacity: 0
是否占有空间×√√
是否可以进行DOM事件监听××√
是否可以点击××√
是否可以被子元素继承×√√
子元素能否通过改变属性值来改变继承自父亲的隐藏状态×√×

1. display: none

  • **DOM 结构:**浏览器不会渲染 display 属性为 none 的元素,会让元素完全从渲染树中消失,渲染的时候不占据任何空间;
  • **事件监听:**无法进行 DOM 事件监听,不能点击;
  • **性能:**修改元素会造成文档重绘重排( repaint 与reflow ),读屏器不会读取display: none元素内容,性能消耗较大;
  • **继承:**是非继承属性,由于元素从渲染树消失,造成子孙节点消失,即使修改子孙节点属性子孙节点也无法显示,毕竟子类也不会被渲染;
  • **属性值从 none 改为非 none 时的效果:**显示出原来这里不存在的结构;
  • **transition:**transition 不支持 display。
  • **用途:**虽然会造成大量的重绘重排,但是也是对复杂结构减少重绘重排常用的办法。常常将一个“会被大量修改结构和视觉效果”的结构先赋予 display:none 属性,让其在 DOM 树中消失,然后进行 DOM 操作,操作完再让其显示。更多有关重绘重排的方法可以参考这篇文章:前端性能优化之重排和重绘。

2. visibility: hidden

  • **DOM 结构:**不会让元素从渲染树消失,渲染元素继续占据空间,但是内容不可见;
  • **事件监听:**无法进行 DOM 事件监听,不能点击;
  • **性能:**修改元素只会造成本元素的重绘(repaint),是重绘操作,比重排操作性能高一些,性能消耗较少;读屏器读取visibility: hidden元素内容;
  • **继承:**是继承属性,子孙节点消失是由于继承了visibility: hidden,子元素可以通过设置 visibility: visible 来取消隐藏;
  • **属性值从 hidden 改为 visible 时的效果:**显示不会导致页面结构发生变动,不会撑开;
  • **transition:**transition 支持 visibility,visibility 会立即显示,隐藏时会延时。

3. opacity: 0

  • **DOM 结构:**透明度为 100%,不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见;
  • **事件监听:**可以进行 DOM 事件监听,可以点击;
  • 性能:提升为合成层,是重建图层,不和动画属性一起则不会产生repaint(不脱离文档流,不会触发重绘),性能消耗较少;
  • **继承:**会被子元素继承,且子元素并不能通过 opacity: 1 来取消隐藏;
  • **场景:**可以跟transition搭配;
  • **transition:**transition 支持 opacity,opacity 可以延时显示和隐藏。

打个比方: display: none: 从这个世界消失了, 不存在了; opacity: 0: 视觉上隐身了, 看不见, 可以触摸得到; visibility: hidden: 视觉和物理上都隐身了, 看不见也摸不到, 但是存在的;

附加题:CSS 隐藏页面上的一个元素有哪几种方法?

  1. display:none,visibility:hiden,opacity:0 这三种;
  2. 设置 fixed 并设置足够大负距离的 left top 使其“隐藏”;
  3. 用层叠关系 z-index 把元素叠在最底下使其“隐藏”;
  4. 用 text-indent:-9999px 使其文字隐藏。

3、浏览器存储方法

特性cookielocaStoragesessionStorageindexedDB
数据生命周期expires设置过期时间除非主动清理,否则一直存在页面关闭就清理除非主动清理,否则一直存在
存储大小4K5M5M5M
与服务器通信每次请求都会携带在header中,消耗性能不参与不参与不参与

cookie :如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。

document.cookie 

localStorage :以键值对(Key-Value)的方式存储,键值对总是以字符串的形式存储,永久存储,永不失效,除非手动删除

sessionStorage :以键值对(Key-Value)的方式存储, 临时会话,受同源策略限制

window.localStorage.setItem(key,value);  // 设置

IndexedDB 就是浏览器提供的本地数据库, 内部采用对象仓库(object store)存放数据,它可以被网页脚本创建和操作,IndexedDB 允许储存大量数据,提供查找接口,还能建立索引

4、简述Vue的生命周期

常用的有8个(生命周期不仅仅是8个),都是成对出现。分别是

beforeCreate阶段、created阶段;

beforeMount阶段、mounted阶段;

beforeUpdate阶段、updated阶段;

beforeDestroy阶段、destroyed阶段;

简述react的生命周期

componentWillMount() – 在渲染之前执行,在客户端和服务器端都会执行。

componentDidMount() – 仅在第一次渲染后在客户端执行。

componentWillReceiveProps() – 当从父类接收到 props 并且在调用另一个渲染器之前调用。

shouldComponentUpdate() – 根据特定条件返回 true 或 false。如果你希望更新组件,请返回true 否则返回 false。默认情况下,它返回 false。

componentWillUpdate() – 在 DOM 中进行渲染之前调用。

componentDidUpdate() – 在渲染发生后立即调用。

componentWillUnmount() – 从 DOM 卸载组件后调用。用于清理内存空间。

5、Vue父子传值

父传子 props
子传父 $emit
Vuex
v-mode
eventBus

6、数组方法

push 向数组的末尾添加新内容

pop 删除数组的最后一项

unshift 向数组首位添加新内容

shift 删除数组的第一项

slice :截取数组

splice :对数组进行增删改

join 用指定的分隔符将数组每一项拼接为字符串

concat : 拼接数组

index:检测当前值在数组中第一次出现的位置索引

lastIndexOf: 检测当前值在数组中最后一次出现的位置索引

includes :判断一个数组是否包含一个指定的值,返回布尔值

sort:排序

let ary11 = [32,44,23,54,90,12,9]; 

  ary11.sort(function(a,b){        
       // return a-b;  // 结果[9, 12, 23, 32, 44, 54, 90]
       return b-a;  // 结果[90, 54, 44, 32, 23, 12, 9]  
  })  

   console.log(ary11);

reverse :倒序

forEach: 遍历

map: 遍历数组,需要返回return。

7、什么是跨域?怎么解决?

当协议,主机,和端口号有一个不同时,就是跨域。

跨域解决方案

1)(后端)服务器配置CORS(跨域资源共享)

2) (后端)node.js或nginx,反向代理,把跨域改造成同域

3)(前端)将JSON升级成JSONP,在JSON的基础上,利用script 标签可以跨域的特性,加上头设置

8、ES6新特性

箭头函数和普通函数

//普通函数可以有匿名函数,也可以有具名函数。
// 具名函数
function func(){
}
// 匿名函数
let func=function(){    
}     

// 箭头函数全都是匿名函数
let func=()=>{
}

(1).箭头函数是匿名函数,普通函数可以有匿名函数,也可以有具名函数;
(2).箭头函数没有自己的this,this指向外层作用域;
(3).箭头函数箭头函数不能用于构造函数;
(4).箭头函数没有arguments对象

(5).箭头函数不能Generator函数。
(6).箭头函数不具有prototype原型对象。
(7).箭头函数不具有super。
(8).箭头函数不具有new.target。

9、HTTP状态码

1XX : 信息提示 这些状态代码表示临时的响应。

2xx - 成功 这类状态代码表明服务器成功地接受了客户端请求

3xx - 重定向 客户端浏览器必须采取更多操作来实现请求。

4xx - 客户端错误。

5xx - 服务器错误

10、二级事件监听 addEventListener()

  • 参数:三个, 要处理的事件名,作为事件处理程序的函数 、一个布尔值。
  • true,表示在捕获阶段调用事件处理程序;false,表示在冒泡阶段调用事件处理程序。
var btn= document.getElementById("clickBtn");
btn.addEventListener("click",function(){
      alert(this.id);
},false);

js事件处理机制: js中事件的发生包括捕获和冒泡两个阶段,两个阶段的传播顺序为 捕获:从最外边父元素节点传递至发生事件的元素节点,即由外到内; 冒泡:从发生事件的元素节点传递至最外边父元素节点,即由内到外;

11、使用什么代码管理工具,代码怎么管理

使用git (分布式版本控制系统)

常用命令

初始化

git init
git clone [url]

拷贝 一个git 仓库到本地 (可选https 或 SSH)

代码提交

git add .  添加到暂存区
git commit -m ""  提交到本地仓库
git push   上传远程代码并合并

查看、回退

git log 查看提交记录

gitstatus 查看查看仓库状态

git reset  回退版本(不同分支开发)
git revert 回退版本(多人使用同一分支开发)

拉取、合并、推送

git pull     下载远程代码并合并 ,相当于fetch加merge
git fetch    从远程获取代码库,但不合并
git merge    合并代码(以合并时间为准)
git rebase   合并代码(把你最新的修改放在最前)

12、flx布局

解决某元素的子元素的布局方式,为布局提供最大的灵活性

  1. 开启弹性布局:display: flex;

  2. 设置属性

    1. flex-direction – 设置 主轴方向

      • row - 横向为主轴 X (默认)
      • column - 纵向为主轴 Y
    2. justify-content – 设置主轴对齐方式

      • justify-content: flex-start; – 位于容器的开头
      • justify-content: flex-end; – 位于容器的末尾
      • justify-content: center; – 水平居中(常用)
      • justify-content: space-between; – 两边贴边,中间留空 (常用)
      • justify-content: space-around; – 平分剩余空间
    3. align-items – 设置侧轴对齐方式

      • align-items: stretchl; – 默认值,拉伸填满
      • align-items: center; – 设置垂直居中(常用)
      • align-items: flex-start; – – 位于容器的开头
      • align-items: flex-end; – 位于容器的末尾
      • align-items: baselinel; – 位于容器基线上
    4. align-content – 设置多行时的对齐方式

      • align-content: stretch; – 默认值,拉伸自适应

      • align-content: flex-start; – 位于容器的开头

      • align-content: flex-end; – 位于容器的末尾

      • align-content: center; – 水平垂直居中 (常用)

      • align-content: space-between; – 两边贴边,中间留空 (常用)

      • align-content: space-around; – 平分剩余空间

    5. flex-wrap – 设置是否换行

      • nowrap – 不换行
      • wrap – 换行
    6. order: num; – 设置排列顺序,默认为 0

    7. align-self – 设置元素自身,在侧轴上的对齐方式。脱离原来的排序限制。

    8. flex: num; – 设置子元素占用空间份数

1、重绘、回流(也叫重排)

DOM性能 浏览器的性能大部分都是被这两个问题所消耗
重绘:
DOM树没有元素增加或删除,只是样式的改变,针对浏览器对某一元素进行单独的渲染,这个过程就叫做重绘
重排:
DOM树中的元素被增加或者删除,导致浏览器需要重新的去渲染整个DOM树,回流比重绘更消耗性能,发生回流必定重绘,重绘不一定会导致回流。

因为重绘和回流的存在导致真实DOM性能不佳,所以VUE和recat还有angular等框架增加了虚拟DOM技术,就是为了减少DOM的重绘和重排从而减少浏览器性能消耗,这就是虚拟DOM的好处。

重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为重排(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。

触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如:
  1、页面渲染初始化;(无法避免)

2、添加或删除可见的DOM元素;

3、元素位置的改变,或者使用动画;

4、元素尺寸的改变——大小,外边距,边框;

5、浏览器窗口尺寸的变化(resize事件发生时);

6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;

7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )

当需要对DOM元素进行一系列操作,可以通过以下步骤来减少重绘和重排的次数:
1、使元素脱离文档流(重排)
2、对应用多重改变
3、把元素带回文档(重排)

有三种基本方法可以使DOM脱离文档流:
1、隐藏元素,应用修改,重新显示
2、使用文档片段在当前DOM之外构建一个子树,再把它拷贝回文档(推荐)
3、将原始元素拷贝到一个脱离文档的节点中,修改副本,完成后再替换原始元素。

2.Vue的双向数据绑定,Model如何改变View ,View如何改变Model

实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅
实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。

3、移动端页面怎么适配,有遇过rem不能解决的问题吗?最后怎么解决的

例如百分比,rem适配,栅格布局,vh/vw等等

IE9以下有些不兼容rem,rem 是根据 html 标签的根字体大小来计算客户端需要适配的大小

在微信、QQ 浏览器中内容变大问题

一下根字节的大小,重新计算了样式的宽高。

确实是因为我设置的根节点太小

( 1 :10(750px 的设计稿)在移动端差不多 html 的 font-size: 5px;)

导致有些浏览器识别不了那么小的字体就用浏览器默认最小字体代替导致的样式错乱

解决

  html {
       font-size: calc(100vw / 750 * 100);
      }

1rem=100px=13.333333vw

4、前端网络安全问题

  1. XSS 跨脚本攻击

  2. CSRF 跨站点请求伪造

  3. iframe 滥用

  4. 恶意第三方库,如之前 npm 的包如:event-stream 被爆出恶意攻击数字货币;

  5. HTTPS ,黑客将HTTPS降为HTTP

  6. 避免重要用户信息存在浏览器缓存中

    …

XSS攻击包括

服务端:

  • 存储型攻击:比如说存储用户信息:评论区,
  • 反射型攻击:比如说URL传参,进行网页刷新跳转

JS自身漏洞

  • DOM型攻击:前端JS取出并执行恶意代码

如何预防?

  1. 输入验证:比如一些常见的数字、URL、电话号码、邮箱地址等等做校验判断
  2. 对HTML代码进行充分转译 使用正则匹配,替换
  3. DOM型,规范JS代码,如尽量使用setAttribute()、.textContent代替innerHTML、document.write()
  4. 严格的CSP,即建立白名单,告诉浏览器,哪些外部资源是可以加载并且执行的,如设置meta标签的http-equiv属性(文件头)
  5. 开启浏览器XSS防御:Http Only cookie,禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
  6. 验证码

CSRF

称为“跨站请求伪造”,攻击者诱导受害者进入第三方网站

攻击类型

\1. 自动发起 Get 请求

\2. 自动发起 POST 请求

\3. 引诱用户点击链接

如何·预防

  1. 针对实际情况将一些关键的 Cookie 设置为 Strict 或者 Lax 模式,这样在跨站点请求时,这些关键的 Cookie 就不会被发送到服务器,从而使得黑客的 CSRF 攻击失效。
  2. 验证请求的来源站点,通过Header中的Origin Header 、Referer Header 确定,但不同浏览器可能会有不一样的实现,不能完全保证
  3. CSRF Token:在浏览器向服务器发起请求时,服务器生成一个 CSRF Token。将CSRF Token输出到页面中(通常保存在Session中),页面提交的请求携带这个Token,服务器验证Token是否 正确

iframe

一个内联框架被用来在当前 HTML 文档中嵌入另一个文档。

  • i)嵌入第三方 iframe 会有很多不可控的问题,同时当第三方 iframe 出现问题或是被劫持之后,也会诱发安全性问题
  • ii)点击劫持
    • 攻击者将目标网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,诱导用户点击。
  • iii)禁止自己的 iframe 中的链接外部网站的JS

预防方案:

  • i)为 iframe 设置 sandbox 属性,通过它可以对iframe的行为进行各种限制,充分实现“最小权限“原则
  • ii)服务端设置 X-Frame-Options Header头,拒绝页面被嵌套,X-Frame-Options 是HTTP 响应头中用来告诉浏览器一个页面是否可以嵌入
  • iii)设置 CSP 即 Content-Security-Policy 请求头
  • iv)减少对 iframe 的使用

5、浏览器缓存策略

浏览器缓存过程:

1.浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器请求下载下来,并把response header及请求的返回时间一并缓存(要与Cache-control和Expires做对比)

2.下一次加载资源的时候,先比较当前时间和上一次返回200时的时间差,如果没有超过Cache-control的max—age,则没有过期直接命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持http1.1 , 则使用Expires判断是否过期)

3.如果过期,服务器则查看header里面的 If-None-Match和If-Modified-Since;

4.服务器优先根据Etag的值(服务器返回资源后时设置的哈希值If-None-Match)判断被请求的文件有没有做修改,下一次加载请求是Etag值一致则没有修改,命中协商缓存,返回304,如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200

5.如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间作对比,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;

使用协商缓存是为了进一步降低数据传输量,如果数据没有改变,就不必要再传一遍

浏览器每次发起请求时,先在本地缓存中查找结果以及缓存标识,根据缓存标识来判断是否使用本地缓存。如果缓存有效,则使 用本地缓存;否则,则向服务器发起请求并携带缓存标识。根据是否需向服务器发起HTTP请求,将缓存过程划分为两个部分: 强制缓存和协商缓存,强缓优先于协商缓存。

  • 强缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用本地缓存,不在时间内,执行比较缓存策略。Cache-control是一个相对时间(优先级高),Expires是一个绝对时间
  • 协商缓存,让客户端与服务器之间能实现缓存文件是否更新的验证、提升缓存的复用率,将缓存信息中的Etag和Last-Modified(字段告知客户端,资源最后一次被修改的时间),每次请求都会去服务器进行校验。服务器对比最后修改时间如果相同则返回304,浏览器直接使用缓存。不同返回200以及资源内容。****

6、讲一讲MVVM吗?

MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。

8、js如何把一个字符串的大小写取反

let str = '124BBBBBgsdff'
str = str.replace(/[a-zA-Z]/g, content => {
    console.log(content)
    // content : 每一次正则匹配的结果  BBBBBgsdff
    return content.toUpperCase() === content ? content.toLowerCase() : content.toUpperCase()
})
console.log(str)

9、单页面多页面开发

单页面:单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。

多页面:每一次页面跳转的时候,后台服务器都会给返回一个新的html文档,这种类型的网站也就是多页网站,也叫做多页应用

单页面:

优点:

-减小服务器压力。

-增强用户体验,增加app的使用流畅性

单页应用没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并有“闪烁”现象。

-单页应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍。

-良好的前后端分离。后端不再负责模板渲染、输出页面工作,后端API通用化

缺点:-首次加载耗时比较多。(解决办法:可以采用基于HTTP Chunk 的首屏数据渐进式预加载方案,)

多页面:

优点:给用户提供一个完美的视觉方向,重点是没有很多的菜单,简洁明了的SEO管理。由于可以针对每页一个关键字优化应用程序

缺点:后端和移动客户端不能同时使用,前端和后端开发紧密结合。开发变得相当复杂。开发人员需要为客户端和服务器端使用框架。这导致应用程序开发时间更长。

SEO:可以查询到该网站搜索各大引擎的信息,可以一目了然的看到当前该域名的相关信息,及时调整网页优化等

12、setTimeout、promise、async/await 的区别

setTimeout属性宏任务,Promise里面的then方法属于微任务,Async/Await中await语法后面紧跟的表达式是同步的,但接下来的代码是异步的,属于微任务。

宏任务优先级:
主代码块 > setImmediate > MessageChannel > setTimeout / setInterval

微任务优先级
微任务microtask:process.nextTick > Promise = MutationObserver

setTimeout
console.log("script start");
   setTimeout(function () {
       console.log('setTimeout')
   }, 0);
console.log('script end');

输出script start -> script end -> set

Promise:
Promise本身是同步的,但在执行resolve或者rejects时是异步的,即then方法是异步的。

   console.log("script start");
    let promise1 = new Promise(function(resolve) {
        console.log("promise1");
        resolve();
        console.log("promise1 end");
    }).then(function(){
        console.log('promise2');
    })
setTimeout(function () {
    console.log('setTimeout');
}, 0)
console.log('script end');

输出顺序: script start -> promise1 -> promise1 end -> script end -> promise2 ->setTimeout

async/await:
 async function async1(){
        console.log('async1 start');
        await async2();
        console.log('async1 end')
    }
    async function async2(){
        console.log('async2')
    }
console.log('script start');
async1();
console.log('script end')

输出顺序:script start -> async1 start -> async2 -> script end -> async1 end

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

await后面跟一个表达式,async方法执行时,遇到await后会立即执行表达式,然后把表达式后边的代码放到微任务队列中,让出执行栈让同步代码先执行;

setTimeout

 console.log("script start");
    setTimeout(function () {
        console.log('setTimeout')
    }, 0);
    console.log('script end');

输出顺序: script start -> script end -> setTimeout

13、什么是防抖和节流?有什么区别?如何实现?

/** 防抖:
 * 应用场景:当用户进行了某个行为(例如点击)之后。不希望每次行为都会触发方法,而是行为做出后,一段时间内没有再次重复行为,
 * 才给用户响应
 * 实现原理 : 每次触发事件时设置一个延时调用方法,并且取消之前的延时调用方法。(每次触发事件时都取消之前的延时调用方法)
 *  @params fun 传入的防抖函数(callback) delay 等待时间
 *  */
const debounce = (fun, delay = 500) => {
    let timer = null //设定一个定时器
    return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fun.apply(this, args)
        }, delay)
    }
}
/** 节流
 *  应用场景:用户进行高频事件触发(滚动),但在限制在n秒内只会执行一次。
 *  实现原理: 每次触发时间的时候,判断当前是否存在等待执行的延时函数
 * @params fun 传入的防抖函数(callback) delay 等待时间
 * */

const throttle = (fun, delay = 1000) => {
    let flag = true;
    return function (...args) {
        if (!flag) return;
        flag = false
        setTimeout(() => {
            fun.apply(this, args)
            flag = true
        }, delay)
    }
}

14、call、aplay 和 bind 三者之间的区别?

重点:箭头函数,不能改变this指向,只有普通function函数,能改变this指向

  • call方法与apply方法, 传参方法不一样
  • apply传入的参数是包含多个参数的数组
  • call传入的参数是若干个参数列表
  • bind方法会创建一个新的函数,当被调用的时候,将其this关键字设置为提供的值,我们必须手动去调用

call apply 都是立即执行函数
参数1,都是改变的this指向,其他参数,是原始函数的形参(可以有,也可以没有)

call方法是通过其他多个参数来实现:

语法: 函数.call(参数1,其他参数…可以是多个或者没有 )

apply方法是通过一个数组参数,来实现

语法: 函数.apply(参数1,参数2) 只有两个参数

15、Vue路由跳转方式 push 、go、router-link、replace

this.$router.push() (函数里面调用)

1.  不带参数
 
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
 
2. query传参 
 
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
 
// html 取参  $route.query.id
// script 取参  this.$route.query.id
 
3. params传参
 
this.$router.push({name:'home',params: {id:'1'}})  // 只能用 name
 
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
 
// html 取参  $route.params.id
// script 取参  this.$route.params.id
 
4. query和params区别
query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
 
params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失

this.$router.replace() (用法同上,push)

router-link (声明式路由)

1. 不带参数
 
<router-link :to="{name:'home'}"> 
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name  
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
 
2.带参数
 
<router-link :to="{name:'home', params: {id:1}}">  
 
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id" 
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留

this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数

16、简述javascript原型、原型链?有什么特点?

原型:每一个构造函数都有一个prototype属性指向一个对象,这个对象就是构造函数实例的原型

原型链:每一个实例都有一个__proto__属性执行原型对象,来获取原型对象上的属性和方法,原型对象也有一个__proto

属性指向另外一个原型对象,以此类推,直到原型链的最终端null为止,这个串成链的过程就是原型链

特点:实现继承 一个对象可以拿到另一个对象上的属性和方法

构造函数都有一个prototype属性指向原型对象

原型对象都有一个consttuctor属性指向构造函数

构造函数new实例化实例对象

实例对象上有__proto属性指向原型

17、js事件处理程序

流程包括 事件源,事件,事件处理程序

  • 事件源:网页元素,如按钮、输入框
  • 事件,事件为浏览器或用户的行为。如鼠标点击,屏幕滚动、选中数输入框等
  • 事件处理程序则是响应某个事件的函数。如,onClick,onLoad等。

事件处理程序分为HTML处理程序,DOM0级事件处理程序,DOM2级事件处理程序

  1. HTML处理程序

直接在HTML中添加事件处理程序,弊端:代码耦合性太强,不利于项目维护,且在不同浏览器会出现差异。

		<button type="button" onclick="alert('消息框');" onmouseout="console.log('控制台')">Html事件处理程序</button>
		<button type="button" onclick="fun1();" onmouseout="console.log('控制台')">Html事件处理程序</button>	

		<script type="text/javascript">
			//Html事件处理程序
			function fun1(){
				alert("消息框");
			}
			
			//加载事件 load   当页面中元素和引入的资源加载完毕之后执行里面的代码
			window.onload = function(){
					alert("加载完成");
			}
		</script>
  1. DOM0级处理程序

使用JavaScript指定事件处理程序,将一个函数赋值给一个事件处理程序属性,弊端:不能给同一个元素绑定同一个事件多次

        <button type="button" id="but1">DOM0级事件处理程序</button>
		<script type="text/javascript">

			//获取元素
			var but1 = document.getElementById("but1");
			// 2.给元素绑定事件
			but1.onclick = function(){
				console.log('DOM0级事件处理程序1');
			}
			//添加的第二的Click事件起作用,第一个被覆盖
			but1.onclick = function(){
				console.log('DOM0级事件处理程序2');
			}
		</script>
  1. DOM2级处理程序

定义了addEventListener()和removeEventListener()方法来定义和删除事件处理程序。

<button type="button" id="but2">DOM2级事件处理程序</button>
		<button type="button" id="but3">删除DOM2级事件处理程序</button>
		<script type="text/javascript">
			//DOM2级事件处理程序
			//获取元素
			var but2 = document.getElementById("but2");
			var but3 = document.getElementById("but3");
			
			but2.addEventListener("click",function(){
				console.log("DOM2级事件处理程序1");
			});
			but2.addEventListener("click",function(){
				console.log("DOM2级事件处理程序2");
			});
			
			function fun3(){
				console.log("有方法名的处理程序");
			}
			but2.addEventListener('mouseover',fun3);
				
			//移除but2的某个事件
			but3.addEventListener("click",function(){
				but2.removeEventListener('mouseover',fun3);
			});
		</script>

跨浏览器的事件处理程序

 <button id="myBtn">点击我</button>

//此代码可以兼容所有浏览器
    //addEventListener attachEvent
    var EventUtil = {
        addHandler:function(element,type,handler){
            //绑定事件
            //chrome,firefox.IE9等, addEventListener
            //IE8及IE8以下的浏览器,attachEvent
            if(element.addEventListener){
                element.addEventListener(type,handler,false);
            }else if(element.attachEvent){
                element.attachEvent("on"+type,handler);
            }else{
                element["on"+type] = null
            }
        },
        // removeHandler:function(element,type,handler){
        //     //移除事件
        //     //chrome,firefox.IE9等, removeEventListener
        //     //IE8及IE8以下的浏览器,detachEvent
        //     if(element.removeEventListener){
        //         element.removeEventListener(type,handler,false);
        //     }else if(element.detachEvent){
        //         element.detachEvent("on"+type,handler);
        //     }else{
        //         element["on"+type] = null
        //     }
        // }
	
    }
    
    var btn = document.getElementById("myBtn");
    var handler = function(){
        alert("Clicked");
    }
    EventUtil.addHandler(btn,"click",handler);  //添加事件
    // EventUtil.removeHandler(btn,"click",handler); //移除事件

Promise状态完成后不会再改变

then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
then方法的特点
返回一个新的Promise实例,并接收两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)

const p = new Promise(function(resolve,reject){
  resolve('success');
});

p.then(function(value){
  console.log(value);
});
console.log('first');
//输出结果
// first
// success

Promise 应用场景 (https://www.php.cn/js-tutorial-451746.html)

1:多个请求合并在一起发

具体描述:一个页面,有多个请求,我们需求所有的请求都返回数据后再一起处理渲染

如果发多个的话,每个请求的loading状态要单独设置,使用Promise.all 汇总请求结果,从开始到结束,我们只设置一个 loading 即可。

2:合并请求结果并处理错误

描述:我们需求单独处理一个请求的数据渲染和错误处理逻辑,有多个请求,我们就需要在多个地方写

3:验证多个请求结果是否都是满足条件

描述:在一个微信小程序项目中,做一个表单的输入内容安全验证,调用的是云函数写的方法,表单有多7个字段需要验证,都是调用的一个 内容安全校验接口,全部验证通过则 可以 进行正常的提交

hadoop部分面试题 1、下面哪个Linux命令可以一次显示一页内容? (B) A pause () B cat C more(查看一页) D grep(查找) 2、怎样更改一个文件的权限设置? (B) A attrib B chmod C change D. file 3、假如当前系统是在 level 3 运行,怎样不重启系统就可转换到 level 5 运行? ... 阅读详情

相关推荐

百度部分笔试和面试题

笔试题3   #include &lt;algorithm&gt; #include &lt;cstdio&gt; int main() {   char s[1011];   // 输入   while (scanf("%s", s) != EOF) {     // 规律打印图形     int flag = 1, m = 0, n = 0, a = 0, b = 0, ...

LETFLY'S LAB 830

移动端入门知识(2)

一、单位(续集) 我们大家都知道盒子的宽度可以设置为100%,并且会生效;如果我们高度设置为100%会生效吗?这个我们大家可以去尝试一下,答案是不能的。 想把盒子的高度设置为100%有两种方法: 1.就要用绝对定位和固定定位中的一个 position: fixed; /* position: absolute; */ width: 100%; height: 100%; 2.用vw和vh单位 width: 100vw; height: 100vh; 下面就让我来介绍一下vw和vh吧!

wx112728的博客 510

【SAP PO】SAP PO 接口配置完整教程之一RFC服务发布

SAP RFC开发,PO接口配置

XLevon的博客 2万+

HTML 移动端布局

HTML 移动端布局与K值

Ace0902的博客 995

AVS3代码阅读HPM4.0

参考AVS3代码阅读(HPM6.0)(一.整体架构以及CU划分部分代码) 版本:HPM4.0 核心文件:app_encoder.c   要做的是帧间预测,所以前面的函数先暂时不管了,挖个坑以后再填。直接从enc_pic看起。 enc_pic()    ...

CRR的博客 3187

嵌入式开发必备:aarch64-linux-gnu-gcc交叉编译工具链保姆级安装指南(含常见错误解决)

本文详细介绍了aarch64-linux-gnu-gcc交叉编译工具链的安装与配置方法,涵盖从系统软件源安装到Linaro二进制包部署的全流程。针对嵌入式开发中常见的依赖错误、版本冲突等问题提供实用解决方案,并分享性能优化技巧与项目集成经验,帮助开发者高效完成ARM64设备的跨平台开发。

yoga7的博客 1030

CSS中vw vh rem的关系及作用

【代码】CSS中vw vh rem的关系及作用。

conquer_galaxy的博客 2292

电化学阻抗谱(EIS)在锂离子电池中的应用

摘要电化学阻抗谱(electrochemical impedance spectroscopy, EIS)是一种重要的电化学测试方法,在锂离子电池动力学反应机理研究及动力学参数测量等方面具有广泛的应用。在锂离子电池运行过程中,各反应步骤的动力学参数及时间常数不同,而EIS可以在较宽的频率范围内对体系施加小幅正弦激励信号,使得在特定频率下突出特定时间常数的电极过程,从而将复杂的电极过程分离,实现单一电极过程动力学的分析。通过对交流阻抗信息的研究,也可以为锂离子电池及其他电池的应用与管理、电化学过程设计及电极材

qiushireader的博客 2651

前端布局之移动端布局相关

移动端布局 视口 二倍图 阿里巴巴矢量图标库

qq_56668869的博客 861

全国30米分辨率逐年植被覆盖度(FVC)数据集

植被覆盖度是描述地表植被的重要参数与生态环境的基本指标,在大气圈、土壤圈、水圈和生物圈中都占据着重要的地位,区域及全球范围的植被覆盖度估算对植被及相关领域的研究具有重要意义。分别对LANDSAT 5/7/8系列数据计算FVC,其中Landsat5 和Landsat 7NDVI计算利用 B4和B3波段,Landsat8 和Landsat9 NDVI计算利用 B5和B4波段。算法从当年所有观测数据中,以低云、低探测角度和最高NDVI值为标准,选择最佳的可用像元值,并进行换算。(3) FVC的计算。

地球资源数据云的官方博客 1808

基于单片机的继电器参数测试系统设计

由于原有测试系统在参数设置上过于单一,在对继电器测试过程中需要多次进行器件连接,导致对其测试准确度下降,会造成继电器的二次损伤,基于单片机研究继电器参数测试系统的设计方法。在硬件设计上,构建二级模式集散控制框架,利用单片机进行数据采集和处理,满足实时继电器参数数据的同步控制;设计双极性反向比例输出电路,分别利用电极电阻对继电器两侧电压进行放大,实现继电器实时电压的检测。实验结果:以两组类型断电器为测试对象,分别连接示波器进行真实数据采集,在本文系统的应用下所得参数测试结果,与真实的数据相一致,具有实际应用效

weixin_45905610的博客 1439

字体图标的使用-补充、calc计算属性-拓展1、完美的动画轮播-拓展2

目录 一、字体图标的使用-补充 二、calc计算属性-拓展1 (1)calc() 只作用于属性值 (2)CSS很多长度都可以与calc()一起使用 (3)不能在媒体查询中使用 (4)calc()的数学运算符 加法(+)和减法(-)要求这两个数都是长度 除法(/)要求第二个数字是无单位的。 乘法(*)要求其中一个数是无单位的。 (5)空白空间很重要 三、完美的动画轮播-拓展2 一、字体图标的使用-补充 1、搜索阿里巴巴矢量图标库进入官方网站 2、找到自己喜欢的图标 不

qq_52301431的博客 899

camera QXXX架构

This article introduces the QCX camera architecture for Qualcomm’s latest automotive chips including SA8650. It elaborates the layered camera stack under QNX, HGY and HQX systems, covering client applications, stream manager, CamX components and hardware d

qq_39257814的博客 4544

【leetcode】面试题 16.16. 部分排序

面试题 16.16. 部分排序题目难度:中等方法一:双指针(找最大逆序对) 链接:https://leetcode-cn.com/problems/sub-sort-lcci/ 来源:力扣(LeetCode) 题目难度:中等 给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。 注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。 示例 1: 输入: [1

一个写湿的程序猿 663

pyecharts在jupyter notebook中不能够渲染图表问题。

在使用jupyter notebook中使用pyecharts绘制可视化图表的时候,发现图表不能渲染到页面中,生成的html是没问题的,本文主要解决在jupyter notebook中不能渲染这个问题。

猿小白的博客 1167

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

腾讯php部分面试题答案

腾讯php部分面试题答案

mwanglur111的专栏 562

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【吊打面试官系列-MySQL面试题】SQL 语言包括哪几部分?每部分都有哪些操作关键字?

SQL 语言包括哪几部分?每部分都有哪些操作关键字?

java1234的博客 363

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Leetcode刷题100天—面试题 16.16. 部分排序(排序)—day58

前言: 作者:神的孩子在歌唱 大家好,我叫智 面试题 16.16. 部分排序 难度中等78 给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。 示例: 输入: [1,2,4,7,10,11,7,12,6,7,16,18,19] 输出: [3,9] 提示: 0 <= len(array) &l

智的博客 2300

2018leetcode算法面试题汇总部分解答

见链接https://blog.youkuaiyun.com/qq_36185831/article/details/88748237

weixin_43167121的博客 404

Java基础部分面试题 (2025)

本文整理了2025年Java相关面试题,涵盖基础、框架、数据库等核心知识点。Java基础部分包括面向对象特性、集合框架、多线程等常见问题;框架部分重点解析Spring AOP/IOC原理、MyBatis等;数据库部分详解MySQL事务、索引优化及分库分表策略。文章还分析了Spring动态代理选择机制,比较了JDK和CGLIB代理的适用场景。这些面试题既考察基础理论,又涉及实际应用场景,适合Java开发者系统复习核心知识体系。

2401_89221445的博客 742

面试题16.部分排序

寻找未排序的部分 == 寻找逆序对,且最远的逆序对 最右边位置:最右逆序对的位置 最左边位置:从右往左的逆序对 左 --> 右 扫描过的最大值是:8 如果发现当前值小于最大值,记录它的位置(2) 右 --> 左 扫描过的最小值是:1 如果发现当前值大于最小值,记录它的位置(5) 并且当 r == -1 时,即说明没有逆序对,直接返回 [-1,-1] ...

高一少年的博客 283

开发测试岗部分面试题整理

CPU 和 GPU的区别 CPU 力气大啥P事都能干,还要协调。 GPU 上面那家伙的小弟,老大让他处理图形,这方面处理简单,但是量大,老大虽然能处理,可是老大只有那么几个兄弟,所以不如交给小弟处理了,小弟兄弟多,有数百至数千个,而且是专门只干这行和只能干这行。

学而时习之 8092

自己把985道Java面试题整理细分26部分,五面成功面上滴滴

前不久自己在网络上白嫖了很多资料,自己也通过线下的方式联系了一些在阿里、腾讯这些大厂的朋友(我是天津大学计算机专业业)拿到了一些内部的面试题,自己手动总结细分化了26个部分,如果有不足的地方欢迎大家补充!

老男孩的架构路 128

RabbitMQ的一部分面试题

YiRuhan 324

机器学习部分面试题小汇总

为什么需要对数值类型的特征做归一化?哪些算法必须做归一化? 为什么归一化——数值范围较大的特征会对模型的训练产生过大的影响,导致模型偏向于这些特征,所以需要消除数据特征之间的量纲影响,使得不同指标之间具有可比性。此外,特征的尺度差异会导致权重更新不均衡,影响收敛速度。一些算法对特征的尺度敏感,归一化可以提高模型的稳定性和预测精度。 哪些算法必须做归一化?——通过梯度下降法求解模型的通常需要归一化,包括线性回归、逻辑回归、SVM、神经网络等;决策树模型不需要归一化,因为决策树在进行节点分裂时,主要依靠数据集关

qq_44066896的博客 1095

java基础部分面试题

 一. Java基础部分基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法。1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。2、Java有没有goto?java中的保留字,现在没有在java中使用。3...

Super_XL的博客 729
上一篇: XHTML 与 HTML 有何不同?
下一篇: 配置node环境
前端小程
博客等级 码龄5年 81粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值