前端面试题

13 篇文章 0 订阅
3 篇文章 0 订阅

面试题

一.HTML

1.常用哪些浏览器进行测试,对应有哪些内核?

①IE------------------->Trident

②Chrome---------->以前是Webkit现在是Blink

③Firefox------------>Gecko

④Safari-------------->Webkit

⑤Opera-------------->最初是Presto,后来是Webkit,现在是Blink(Webkit的分支)

2.行内元素和块级元素的区别?行内块元素的兼容性使用?(IE8以下)

①行内元素:会在水平方向排列,不能包含块级元素。设置width无效,height无效(可以设置line-height),margin无效,padding上下无效

块级元素:各占一行,垂直方向排列。

②display:inline-block;*display:inline;*zoom:1;
*zoom:1作用是
在IE下触发hasLayout
*display:inline作用作用是
一旦触发了hasLayout设置display:inline和display:block效果相似。

3.清除浮动的方法有哪些,哪个比较好

父级div增加height,一般不用

浮动div标签加空div元素clear:both;

父级div加伪类元素after和zoom-------------------最好用,大多数网站都用

父级div定义overflow:hidden。
父级div定义overflow:auto。

4.box-sizing有哪些属性,分别什么作用?

①content-box:不包含border和padding

②border-box:包含border和padding

5.Doctype作用?标准模式和兼容模式各有什么区别?

<!Doctype>位于 HTML文件的第一行,是在html标签之前。他告诉浏览器的解析器用什么标准文档来解析这个文档。如果<!Doctype>不存在或者格式不正确的就会导致文档以兼容性模式存在。

②标准模式的排版和JS运作的最高模式都是以浏览器支持的最高标准运行。在兼容模式中,总是以宽松的向后兼容的方式显示,模拟老浏览器的行为以防止站点无法工作。

6.HTML5为什么只需要 <!DOCTYPE HTML>?

①HTML5不是基于SGML因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照他们应该的方式来运行)

②HTML4.01是基于SGML,所以需要对DTD进行引用,这样才能告知浏览器文档所使用的文档类型。

7.页面引入样式时,使用link与@import有什么区别?

①link是XHTML标签,除了加载CSS外还可以用于定义RSS,定义Ref连接属性等作用。而@import是CSS所提供的只能用于加载CSS

②link引入CSS时是在页面载入的同时加载的,而@import是页面网页完全载入之后加载的

③link是XHTML标签没有兼容问题,@import是CSS2.1提供的,低版本(ES5以下)的浏览器不支持

④link支持使用javascript控制DOM去改变样式,而@import不支持

8.介绍一下你对浏览器内核的理解

主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。

浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎:解析和执行javascript来实现网页的动态效果。

最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。

9.html5有哪些新特性?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

①HTML5 现在已经不是 SGML 的子集,主要是关于图像画布,音频视频,存储,语义化标签,表单控件,多任务,位置等功能的增加。
(1)绘画 canvas;
(2)用于媒介回放的 video 和 audio 元素;
(3)本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
(4)sessionStorage 的数据在浏览器关闭后自动删除;
(5)语意化更好的内容元素,比如 article、footer、header、nav、section;
(6)表单控件,calendar、date、time、email、url、search;
(7)新的技术webworker, websocket, Geolocation;
②IE6/IE7/IE8支持通过document.createElement方法产生的标签,
可以利用这一特性让这些浏览器支持HTML5新标签,
浏览器支持新标签后,还需要添加标签默认的样式。
当然也可以直接使用成熟的框架、比如html5 shim;
< !--[if lt IE 9]> < script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script> < ![endif]-->

10.简述一下你对HTML语义化的理解?

①表示:用正确的标签做正确的事情。
②好处:

1.页面结构化,使阅读网站源代码的人能够快速理清HTML文档的结构,便于学习和后期维护。

2.即使在没有样式的情况下也以一种文档的格式在用户面前展示,用户容易理解阅读;
3.有利于SEO,因为搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重

二.VUE

1.生命周期(杭州之首)

1.1介绍

beforecreate:组件实例创建之初

created:组件实例已经完成创建

beforeMount:组件挂载之初

mounted:组件挂载上到实例上去之后

beforeUpdate:组件数据发生变化,更新之前

updated:组件数据更新之后

beforeDestroy:组件实例销毁之初

destroyed:组件实例销毁

1.2created与mounted的区别

created是在组件实例创建之后立马执行,这时候的页面虚拟dom还未生成。mounted是页面dom节点渲染完毕之后就立即执行的。两个的相同点就是都能拿到实例对象的方法与属性。不同点就是触发时机。created要比mounted执行的快,mounted中调用接口的话可能页面会闪动(页面的dom结构已经生成)。如果在加载完成前则不会出现这个情况,所以方法created中比较好

2.常用指令(杭州之首)

条件渲染指令:v-if

数组渲染指令:v-for

双向绑定指令:v-model

事件绑定指令:v-on

属性绑定指令:v-bind

3.vue中的key

3.1概念

页面中的标签都对应有相应的虚拟dom,循环中,如果我们进行删除一条数据,如果没有对应的key我们就会把所有的dom渲染一遍。如果有相应的key,我们就找到相应的标签进行删除即可。

3.2作用

为了高效的更新虚拟dom

4.vue中的$nextTick

4.1是什么

页面的dom还没有更新,这时候没有办法更新,如果想操作dom的话必须用$nextTick

5.$set

5.1介绍

数据变化视图不更新,当在项目中直接设置数组的某一项的值或者对象的某一项的值,但是页面没有更新。这是因为 Object.defineProperty()限制,监听不到变化

5.2 方法:数据变成响应式

this.$set(你要改变的数组/对象,你要改变的位置/key,你要改成什么 value)

6.v-show与v-if

6.1相同点

作用效果相同:都能控制元素在页面是否可见

格式上也相同:

占据位置:当为true时占据页面位置,当为false时不占据页面位置

6.2不同点

**控制手段:**v-show隐藏只是为该元素添加css–display:none,元素依然还在。v-if显示隐藏是将元素添加或者删除

**编译过程:**v-if的切换有一个局部的编译/卸载过程,切换过程中适当的销毁和重建内部的事件监听和子组件,v-show只是简单的基于css的切换

**编译条件:**v-if是真正的条件渲染,他会确保在切换的过程中条件块内的事件监听器和子组件被销毁和重建,只有渲染条件为假的时候,不做任何操作,知道为真渲染。

v-show从false变为true时不触发组建的生命周期

v-if从false变为false触发组件的beforeCreate、created、beforeMount、mounted钩子,由true变为false的时候触发组件的beforeDestory和destoryed方法

性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗

6.3使用

如果需要非常频繁地切换,则使用 v-show 较好,例如:手风琴菜单,tab 页签等

如果在运行时条件很少改变,则使用 v-if 较好。例如:用户登录之后,根据他的权限不同来显示不同的内容

7.computed watch(杭州之首)

computed是html,dom加载之后马上执行,如赋值(属性将被混入到vue实例中)

watch用于观察vue实例上的变化,一般情况下依赖项的值变化之后再执行

8.v-if与v-for

v-for与v-if不能一起使用,因为v-for的优先级高,先循环再进行判断,一起使用会造成新能浪费

解决方案:把v-if放在v-for的外层

9.vuex

9.1介绍:

解决数据共享问题,虽然有父向子,子向父等数据传递,但在网站开发过程中一些无直接关联关系的组件也需要共享相同的数据时,就需要使用 vuex 了

9.2:主要成员

state:用来存储数据的

mutations:用来修改state中的数据

actions:是用来处理一些异步操作数据的行为方法

getters:相等于计算属性,是对 state 中的数据做了一些处理

modules 是用来对复杂业务分模块的,每个模块也可以有 state,mutaions,actions,getters

10.插槽

10.1介绍

子组件提供给父组件的占位符

9.mixin(补充)

10.MVVM

MVVM`表示的是 `Model-View-ViewModel
  • Model:模型层,负责处理业务逻辑以及和服务器端进行交互
  • View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面
  • ViewModel:视图模型层,用来连接Model和View,是Model和View之间的通信桥梁

11.vue的优势

11.1 vue的优势与缺点

优势:

①体积小(压缩后33k)

②更高的运行效率

基于虚拟dom,一种可以预先通过javascript进行各种计算,把最终的DOM操作计算出来并优化的技术,由于这个DOM操作属于预处理操作,并没有真实操作DOM,所以我们叫做虚拟DOM

③双向数据绑定

让开发者不用再去操作dom对象,把更多的经历投入到逻辑上

④生态丰富,学习成本低

市场上拥有大量成熟、稳定的基于vue.js 的ui框架 常用组件!拿来即用快速开发。对于初学者友好,入门容易,学习资料多

12.常见的路由跳转

原型作用:

三.JS

1、事件委托

1.1是什么

就是把给子元素绑定的事件统一绑定到祖先元素上

1.2原理

冒泡

1.3好处

性能高

对后续新增的元素同样有绑定事件的效果

1.4如何按需出发

自定义属性

2.引用数据类型和基本数据类型的区别

基本数据类型:

Number String Bollean null undefined Symbol

引用数据类型:

object fuction array

区别:
赋值:

基本数据类型赋值,是生成相应的值,两个对象对应不同的地址

复杂类型的赋值,是将保存对象的内存地址赋值给另一个变量,也就是两个变量指向堆内存的同一个对象

存储位置:

基本数据类型的值存储在栈中,在栈中存放对应的值

引用数据类型对应的值存储在堆中,在栈中存储的是堆内存的地址

3.== 与 ===

3.1介绍

**=:**赋值操作

**==:**两个等号为判断,判断值是否相等,相等则为true 不等就为false

**===:**三个等号为全登,判断类型和值是否都相等 相等则为true 不等为false

3.2区别

相等操作符会先进行类型转换,再对值进行比较。

全等不会做类型转换

4.箭头函数

1.箭头函数没有prototype属性 不能作为构造函数使用(不能使用new())

2.没有argument数据 可以通过…拿到集合数组

3.在定义的时候就确认了this指向 this指向决定外部环境

4.不会通过call apply bind改变this指向 使用的时候第一个参数失效 其余的正常使用

5.箭头函数不能 使用generator函数 不能使用yeild关键字(function*)

 <script>
    // 1.箭头函数没有prototype不是构造函数
    // const person1=()=>{}
    // console.log(person.prototype)
    // new person1()
    // 2.没有arguments 可以通过...拿到数组集合

    // const person2=(...args)=>{
    //     console.log(args)
    // }
    // person2(1,2,3,4)
    // 3.this已经确定取决于父环境
    // 4.call apply bind不会改变this指向 (会忽略第一个参数  其余正常使用)
    const person3=(a,b,c)=>{
     console.log(a,b,c)
    }
    // person3.apply({name:'apply'},[1,2,3])
    // person3.call({name:'bind'},1,2,3)
     const pe=  person3.bind({namr:"bind"},1)
     pe(2)
    // 5.箭头函数不能 使用generator函数  不能使用yeild关键字(function\*)
    function* test(){
        yield 'hello'
    }
    const it=test()
    console.log(it.next())

    </script>

5.new的执行过程

5.1.过程

1.开辟内存空间

2.this指向内存空间

3.执行构造函数

4.返回this实例

5.2特殊

在构造函数中 如果返回一个简单数据类型,会忽略,new出来的结果还是实例

在构造函数中 如果返回一个复杂数据类型 new出来的是复杂数据类型

<script>
        // new的过程
        /*
        内存中开辟空间
        this指向这个空间
        执行构造函数
        返回this实例
        */
        function person(name,age){
            this.name=name
            this.age=age
        }
        const person1=new person('dm',19)
        console.log(person1)
        function person2(name,age){
            this.name=name
            this.age=age
            return 'heello'
        }
        const  person3=new person2('简单数据类型',18)
        console.log('简单数据类型',person3)//简单数据类型 person2 {name: "简单数据类型", age: 18}

        function person4(name,age){
            this.name=name
            this.age=age
            return {name:'复杂数据类型',age:'19'}
        }
        const person5=new person4('复杂吗',000)
        console.log('复杂数据类型',person5)//复杂数据类型 {name: "复杂数据类型", age: "19"}
    </script>

6.call bind apply的区别

6.1相同点

第一个参数是用来改变函数this指向的

第二个参数是是用于传参

6.2不同点

call 和apply可以直接调用,bind是生成新的函数

call和bind可以传递多个参数,apply只能传递一个参数 (数组或者伪数组)

       function test1(a,b){
            console.log(a+b)
        }
       test1.call({name:'call'},1,2)
       test1.apply({name:'apply'},[1,3])
       const test2=test1.bind({name:'bind'},11)
       test2(2)

7.防抖和节流

7.1是什么

都是性能优化的一种手段,防抖就是持续触发不执行,不触发的一段时间内执行。节流就是持续出发也执行,只是频率变慢

举个例子 王者英雄回城就是防抖 吃鸡散弹枪就是节流

7.2在哪用

防抖:往输入框内输入内容发请求

节流:获取窗口滚动的位置

7.3怎么做

定时器封装方法 或者loash提供的debounce和throttle方法

8.Promise

8.1是什么

是Es6新增的函数

8.2怎么用

是一个构造函数 徐娅哟通过new创造实例。里面油三种状态,进行中,已完成,失败。成功会触发then,失败触发catch ,不管成功还是失败触发finally

他有几个静态方法

Promise.race() 接收多个promise实例,可以得到最先处理完毕的结果(可能是成功,也可能是失败)

promise.all ()接收多个promise实例都成功了触发then有一个失败就触发catch

promise.any() 接收多个promise实例,可以得到最新处理成功的结果都失败了才会触发catch

8.3解决什么问题

解决回调地狱的问题t

虽然可以解决回调地狱 但是代码繁琐 所以工作中配合promise使用

9.懒加载 预加载

9.1介绍

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

9.2 怎么解决

如果图片进入可视区,我们就把装图片地址的某个属性值给真正的图片src属性

9.3如何判断属性进入可视区

根据位置计算

利用浏览器提供的api intersetionObserver

9.4预加载和懒加载

加载时机不同:懒加载是迟缓加载甚至不加载, 预加载是提前加载

服务器的影响: 懒加载对前端服务器有一定的缓解压力作用,预加载则会增加服务器的压力

10.null和undefined的表现形式有哪些不同

10.1 typeof
typeof null 'object'
typeof undefined 'undefined'
10.2与数字相加
null+4    4
undefined+4 undefined
10.3 Json.stringify
JSON.stringify({name:undefined,age:null})    //"{\"age\":null}"

11.闭包

11.1 定义

一个函数使用了其外部函数的局部变量,使用变量的地方我们称之为闭包现象,定义变量的地方我们称之为闭包函数

      function foo() {
        let fo = 1;
        return function ffoo2() {
          console.log(fo + 1);
        };
      }
      const bar = foo();
      bar();
11.2特性
  • 延长变量的生命周期
  • 滥用闭包会造成内存浪费
11.3 项目中运用

接口里面调接口

12.千分位

12.1倒序

   // 千分位
    function getNUmber(number){
      // 转化为字符串
      let Number2=number.toString()
      // 转化为数组
      let getarray=  Number2.split('').reverse()
      let result=''
      getarray.forEach((item,index) => {
        // 千分符后将 数组换序
        result=item+result
        // 第一个是整除三位  另一个是到头之后不用加逗号
        if(index%3==2&&index!==number.length-1){
          result=','+result
        }
      });
     return result
    }

13.数组扁平化

数组扁平化是指将一个多维数组变为一个一维数组

const arr = [1, [2, [3, [4, 5]]], 6];
const res1 = arr.flat(Infinity);

14.数组去重

const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];
const new =Array.from(new Set(arr))

15.typeof与instanceof的区别

15.1介绍

**typeof:**用来判断数据类型,返回的是一个字符串

**instanceof:**用于检测构造函数的prototype是否在实例对象的原型链上,返回的是一个布尔值

15.2异同

typeof返回的是变量的基本类型,instanceof返回的是一个布尔值

instanceof虽然能检测出引用数据类型,但是不能检测出基本数据类型

typeof可以检测基本数据类型(null除外),检测引用数据类型的话只能检测出来function其余无法判断

15.3解决弊端的方法
Object.prototype.toString()
//例如
Object.prototype.toString({}) // "[object Object]"
15.4原理

instanceof:也就是顺着原型链去找,直到找到相同的原型对象,返回true,否则为false

注意:如果我们想要判断一个变量是否存在,可以使用typeof:(不能使用if(a), 若a未声明,则报错)

if (typeof a != 'undefined') {
  //变量存在
}
// 判断instanceof  判断构造函数的prototype是否在实例对象的原型上
    getinstanceof(left , right){
      //  先判度是否是基本数据类型
      if(typeof left!=='object'||left==null)   return false
      // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
       let pro=Object.getPrototypeOf(left)
      // 判断引用数据类型
      while(true){
        // 走到底端没有找到
        if(pro==null)  return false
        if(pro==right.prototype) return true
        // 往下继续找
        pro=Object.getPrototypeOf(left)
      }
    }

toString

function getType(obj) {
        let type = typeof obj;
        if (type !== "object") {
          // 先进行typeof判断,如果是基础数据类型,直接返回
          return type;
        }
        // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
        return Object.prototype.toString
          .call(obj)
          .replace(/^\[object (\S+)\]$/, "$1");
      }

16.深拷贝 浅拷贝

16.1介绍

浅拷贝是拷贝一层,当属性为对象时,拷贝的是同一个对象,他们指向同一个地址

浅拷贝是拷贝多层,当属性为对象时,拷贝是新开栈,他们两个指向不同的地址。修改一个对象的属性的时候不会改变另一个对象的属性

16.2方法

浅拷贝方法:

Object.assgin()
Array.prototype.slice()
Array.prototype.concat()
使用拓展运算符实现的复制

深拷贝方法

_.cloneDeep()

jQuery.extend()

JSON.stringify()//这种方式存在弊端,会忽略undefined、symbol和函数

手写循环递归

17.作用域 作用域链

17.1作用域

函数或变量的生效范围

分为局部作用域,块级作用域、全局作用域

17.2作用域链

变量在当前作用域进行查找,如果访问不到,他会一层一层向外进行查找,整个逐级向上查找的过程我们称为作用域链.

18.原型 原型链

18.1原型

在我们创建函数的时候系统自动帮我们生成一个对象,解决构造函数内部方法内存资源浪费问题

实际开发中通常把实例对象一些通用的方法放入原型上,在vue中也会绑定一些通用方法实羡所有诩见共享资源,像一些常见的 r o u t e r 和 router和 routerstore 都是挂载到 vue 的原型上的。

18.2原型链

原型链是 js 对象一种查找机制,遵循就近原则。当我们访问一个对象中的成员的时候,会优先访问自己的,如果自己没有就访问原型的,如果原型也没有就会访问原型的原型,直到原型链的终点 null. 如果还没有,此时属性就会获取 undefined,方法就会报错 xxx is not a function。一般原型链主要是用来实现面向对象继承的。

19.继承???

20.递归–细化

  • 递归是什么? 一个函数在内部调用自己,这个函数就是递归函数。
  • 递归核心思想? 其核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
  • 递归的边界条件? 递归需要有边界条件、递归前进阶段和递归返回阶段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
4.1介绍

4.微/宏任务

4.2区别

2、深拷贝,浅拷贝,实现深拷贝的几个方法

2.1 类型

值类型(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null

**引用类型:**对象(Object)、数组(Array)、函数(Function)

2.2 浅拷贝与深拷贝

浅拷贝:只是增加了一个指针指向已存在的内存地址

方法1:Object.assign()

浅拷贝,只能拷贝一层,如果想全部拷贝,必须深层次的进行拷贝

eg:

let obj1={name:'张三',action:{say:'hi'}};
let obj2=Object.assign({},obj1);//把obj1复制给{}中
obj2.name='李四'
obj2.action.say='hello'
console.log('obj1',obj1)
//obj1 {name:'张三',action:{say:'hello'}}
console.log('obj2',obj2)
//obj2 {name:'李四',action:{say:'hello'}}

方法2:展开运算符...

展开运算符是es6的一个特性,他提供了一种非常方便的方式来执行浅拷贝,这与Object.assign()功能相同

let obj1={name:'张三',action:{say:'hi'}}
let obj2={...obj1}
obj2.name='李四'
obj2.action.say='hello'
console.log('obj1',obj1)
//obj1 {name:'张三',action:{say:'hello'}}
console.log('obj2',obj2)
//obj2 {name:'李四',action:{say:'hello'}}

***注意:concat(),slice()也属于浅拷贝

深拷贝:是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的地址

方法1:JSON.parse(JSON.stringify())

//深拷贝
let obj1={name:'张三',action:{say:'hi'}}
let obj2=JSON.parse(JSON.stringify(obj1))
obj2.name='李四'
obj2.action.say='hello'
console.log('obj1',obj1)
//obj1 {name:'张三',action:{say:'hi'}}
console.log('obj2',obj2)
//obj2 {name:'李四',action:{say:'hello'}}

方法2:jQuery.extend()

$.extend(deepCopy, target, object1, [objectN]) //第一个参数为true,就是深拷贝

//深拷贝
let obj1={name:'张三',action:{say:'hi'}}
let obj2=$.extend(true,{},obj1)
obj2.name='李四'
obj2.action.say='hello'
console.log('obj1',obj1)
//obj1   {name:'张三',action:{say:hi}}
console.log('obj2',obj2)
//obj2 {name:'李四',action:{name:'hello'}}

3、this指向–最新总结------看视频

绑定
默认绑定:

独立调用 ,函数没有绑定到对象上调用 (this指向window)严格模式下 this的指向是undefined

      // 普通函数的独立调用
        function foo(){
            console.log('this的指向',this)
        }
        foo()//window
        // 函数定义在对象中  但是独立调用
        var obj={
            name:'dyl',
            foo:function(){
                console.log('this的指向',this)
            }
        }
        
        var obj1=obj.foo
        obj1() //window
        // 严格模式下的独立调用 this指向undefined
        // 高阶函数
        function test(fn){
            fn()
        }
        test(obj.foo)//window
        //总结:被谁调用只想谁
隐式绑定

通过某个对象进行调用

 function foo(){
        console.log('this的指向',this)
    }
    var obj={
        Foo:foo
    }
    // console.log(obj.Foo)
    console.log(obj.Foo())//window
    var Foo=obj.Foo
    Foo()//window
new绑定
  • 通过构建函数 new 关键字生成一个实例对象,此时 this 指向这个实例对象

            /*
            new
            1.创建新的空对象
            2.将this指向这个空对象
            3.执行函数体的代码
            4.没有显示返回非空对象时 默认返回这个对象
            
            */ 
            function foo(){
                console.log('this的指向',this)
                this.name='dlkdlklklk'
            }
            new foo()  //foo{ name:'dlkdlklklk'}
    
显式绑定

apply()/call()/bind() 可以改变this指向 第一个参数是this指向 之后的是参数

区别:applay第二个参数是数组形式 call第一个之后是数列 bind是数列 但是多余的可以在外边定义的函数里面加

bind绑定是创建一个新的函数 applay与call 是原来的

       function foo(){
            console.log('this的指向',this)
        }
        var obj={name:'djkjkjk'}
        // 调用foo时 总是绑定在obj身上  不希望obj有函数
        // 如果用apply  call
        foo.apply(obj)
        foo.call(obj)
        // 利用bind的话 直接用bar()
        var bar=foo.bind(obj)//this->obj//创建新的函数
        bar()
箭头函数

优点:

比函数表达式更加简洁

不会绑定this arguments属性

不能作为构造函数来使用

箭头函数的指向和定义这个箭头函数的上下文有关

优先级

new绑定 显式绑定 隐式绑定 默认绑定

         默认规则的优先级最低
         显示绑定高于银饰绑定
         new绑定高于隐式绑定
         new绑定高于bind

         new bind call/apply  隐式绑定  默认绑定

7、cookie与session、token—未完成

8、事件的捕获和事件冒泡的流转过程是什么样子的

8.1 js事件流

一个完整的js事件流是从window开始,最后回到window的过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZD1PKSdW-1677692357150)(E:\HDKJ\自学\image\事件流图.jpg)]

*** 注意: 1-5是捕获过程,5-6是目标阶段,6-10是冒泡阶段;

8.2 代码示例
<body>
    <div onclick="console.log('我是div')" class="bigdiv">
        <button onclick="console.log('我是button')" class="bigbutton">
            <span onclick="console.log('我是span')">按钮</span>
        </button>
    </div> 
</body>
<style>
    .bigdiv{
        height: 300px;
        position: relative;
        background-color: bisque;
    }
    .bigbutton{
       position: absolute;
       width: 50px;
       height: 50px;
       left: 50%;
       top: 50%;
       transform: translate(-50%,-50%);
       background-color: aqua;
    }
</style>

详情图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MD2S0TT3-1677692357151)(E:\HDKJ\自学\image\捕获冒泡图.jpg)]

8.3 addEventListener 方法

定义与方法

addEventListener()方法用于向指定元素添加事件句柄

***提示:使用removeEventListener()方法来移除addEventListener()方法添加的事件句柄

语法:

elment.addEventListener(event,function,useCapture)

参数值

event 必须。字符串,指定事件名。

***注意: 不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。

function 必须。指定要事件触发时执行的函数。

当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。例如, “click” 事件属于 MouseEvent(鼠标事件) 对象。

useCapture 可选。布尔值,指定事件是否在捕获或冒泡阶段执行。

可能值

true - 事件句柄在捕获阶段执行

false- false- 默认。事件句柄在冒泡阶段执行

8.4 如何阻止事件冒泡

(1) 在点击方法那里添加 .stop

  <div @click="outDiv" >
        //添加.stop阻止冒泡行为
        <div @click.stop="inDiv" >按钮</div>
   </div>

(2)阻止默认行为 .prevent

这样就不会跳转到链接地址了

<a href="https://baidu.com" @click.prevent="gobaidu">去百度</a>

如果后面再加上.once 那么只阻止一次,第二次还会跳转

<a href="https://baidu.com" @click.prevent.once="gobaidu">去百度</a>

阻止默认行为---->原生方法

<a href="https://baidu.com" @click="gobaidu">去百度</a>
gobaidu(event){
    //原生阻止默认行为
            event.preventDefault()
            console.log('去百度')
              }

四.小程序

1.小程序的生命周期

1.1 应用的生命周期函数

特指小程序从启动->运行->销毁期间一次调用的那些函数

//1.小程序初始化完成时,执行此函数,全局只触发一次。可以做一些初始化的工作
onLaunch(options){
     console.log('onLaunch')
}
//2.小程序启动,或从后台进入前台显示时触发
onShow(options){
    console.log('onShow')
}
//3.小程序从前台进入后台时触发
onHide(){
    console.log('onHide')
}
1.2 页面的生命中周期函数

特指小程序中,每个页面从加载->渲染->销毁期间依次调用的那些函数

//小程序的页面生命周期函数需要在页面的.js文件中进行声明
//1.监听页面加载,一个页面只调用一次
onLoad(optionds){
    console.log('onLoad')
}
//2.监听页面显示
onShow(){
    console.log('onShow')
}
//3.监听页面初次渲染完成,然后对页面数据进行修改,一个页面只调用一次
onReady(){
    console.log('onReady')
}
//4.监听页面隐藏
onHide(){
    console.log('onHide')
}
//5.监听页面卸载,一个页面只调用一次
onUnload(){
    console.log('onUnload')
}

2.min-height和height的区别

2.1height

给元素指定高度,一旦元素的内容超出这个高度就会溢出

2.2min-height

给元素设置最小高度,当内容少的时候,元素是这个高度,当内容超出时,元素高度会自动适应内容,不会出现内容溢出情况。

3.前端设置宽高时height: 100% 和 100vh 的区别

vh就是当前屏幕可见高度的1%,也就是说

height:100vh == height:100%;

但是有个好处是当元素没有内容时候,设置height:100%该元素不会被撑开

但是设置height:100vh,该元素会被撑开屏幕高度一致

4.小程序登录

登录需要三端交互

小程序 服务端 微信接口服务

小程序端调取wx.login()拿到code 调接口将code传到服务器 服务器与微信服务交互 最终服务端返回一个登录态给前端 前端把数据存入本地 之后需要登陆状态码的时候作为参数进行使用

5.小程序中支付流程

五、常见面试题

1.性能优化—待更新

1.1打包编译优化

接口缓存:前端合理利用localStorage
去掉部分重复的接口调用:判断条件严谨
组件重复打包
假设A.js文件是一个常用的库,现在有多个路由使用了A.js文件,这就造成了重复下载
解决方案:在webpack的config文件中,修改CommonsChunkPlugin的配置
minChunks为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件

2.兼容性问题

2.1小程序与app

①创建一个时间对象时,会通过new Date()来创建,比如new Date(‘2022-09-09’)
但是这种形式ios是不可行的 在ios就得写new Date(‘2022/09/09’)
此时利用字符串替换就可以了 new Date(“2022-09-09”).replace(/-/g, “/”)
②安卓和ios的调起拍照功能和苹果的不同
app或者小程序调拍照组件,当点击拍照按钮的时候第一次会提示是否打开拍照权限,但是你拒绝一次之后之后就不再提示。使用者就会认为此功能出错,其实是自己相机权限没有打开。但是苹果每次都提示
解决方案:chooseImage出错时会进入fail方法 当code为11时 给一个提示相机权限拒绝了,去设置里开启

③replaceAll方法在app端不兼容,会报错,可以使用replace代替

2.2.浏览器兼容问题

不同浏览器标签默认的margin padding不同 使用通配符*{margin:0;padding:0}

window.location.href问题
IE或者Firefox2.0.x下,可以使用window.location或window.location.href;

            Firefox1.5.x下,只能使用window.location

            解决方法:统一使用window.location

3.公司是干什么的

公司是做商业地产的,给购物中心做后台管理。我的团队主要负责的是会员系统。给会员提供优质的服务以及一些活动。
超市 联华 壹度便利 快客 百姓超市等

4.懒加载 预加载

4.1介绍

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

4.2 怎么解决

如果图片进入可视区,我们就把装图片地址的某个属性值给真正的图片src属性

4.3如何判断属性进入可视区

根据位置计算

利用浏览器提供的api intersetionObserver

4.4预加载和懒加载

加载时机不同:懒加载是迟缓加载甚至不加载, 预加载是提前加载

服务器的影响: 懒加载对前端服务器有一定的缓解压力作用,预加载则会增加服务器的压力

4.路由跳转模式

5.计算属性支持异步吗

6.路由模式

4.未来规划

1.近几年,我是想走技术路线,想找个平台稳定的专研前端方面的技术。
2.我对前端开发很感兴趣,想在这一领域深耕一下,更全面了解这块。为了达到这个目的,
3.首先我做好本职工作,然后尽量解决项目中遇到的问题,如果项目里用到的技术不熟悉,我会第一时间去了解。
4.我知道这个领域会遇到很多高并发的问题,我现在对这些有一些了解。
===>
(
问题=>大数量的用户同时访问同一API,造成极多的请求同时发起到服务器。大部分的高并发是在后端处理的,然而一些情况下,后端无法阻止用户的行为,这就需要前端配合,例如抢购、秒杀等用户活跃的场景
处理方式=>减少请求数量 节流+防抖 利用缓存减少一些不必要的请求 压缩资源
)
5.自己遇到的问题也会进行一定的总结,希望通过踏实努力地工作,多学习新知识、新方法,不断完善自己,让自己在开发技能上不断进步

5.跳转

C端路由跳转
wx.navigateTo()
wx.redirectTo()
wx.relauch()
B端路由跳转
1.通过标签做跳转

router-link  
<router-link to = "/page">跳转到page页面</router-link>
<router-link :to = "{ name: 'page', params: { id: '110' } }">跳转到page页面</router-link>
<router-link :to = "{ name: 'page', query: { id: '110' } }">跳转到page页面</router-link>
2.this.router.push():(在script里面做跳转)
  this.router.push({ path: '/home', query: { id: '001' } })  
    // 根据路由路径 + query 的方式跳转传参
    this.router.push({ name: 'home', query: { id: '001' } })   
    // 根据路由名称 + query 的方式跳转传参
    this.router.push({ name: 'home', params: { id: '001' } })  
    // 根据路由名称 + params 的方式跳转传参
  拿    $route

10.懒加载 预加载

2.封装axios

1.get与post请求

① get 检索&&获取 post 创建||更新

②从安全性层次来说

第一映像get是不安全的,post是安全的,因此在发送请求时数据会暴露出来,而post请求则不会将参数显示在url地址中

第二个理解是:get请求是安全的,post请求是不安全的,因为gat请求只为去服务器中拿数据,不会对服务器造成任何威胁,而如果使用post请求给服务器提交数据就会产生风险

③ 参数类型

因为get请求只能将参数写在url上,所以对参数类型有严格规定,只能是ASCTLL字符,同时对url长度也有一定的限制。最长是2048个字符;相反,post参数类型多样,像声音视频等,特别是上传文件,一定会使用到post请求中,post请求对参数的长度没有限制

④get请求可以收藏为书签而post不能

因为get请求的参数可以缓存到浏览器中,但是post请求的参数无法缓存,这个区别就导致每次访问get请求都会解析到页面,而post请求的参数会丢失,无法访问页面。如果收藏了post请求作为书签,浏览器就会将post请求的url当时get请求访问,并且没有参数,所以无法访问到

2.computed,methods,watch的区别

2.1 computed与methods的区别

computed是有缓存的(值不改变的情况下只在控制台显示一次)

methods没有(调用多次控制台显示多次)

2.2 computed与watch区别

watch是监听,数据或者路由发生改变才可以响应(执行),

computed是不管值改变没有都会执行,computed计算某一个属性的改变,如果某一个属性改变了,计算属性会监听到并且返回

3.闭包

4.reduce

5.git

6.最近的项目

7.跨域

跨域本质是浏览器基于同源策略的一种安全手段 协议 主机 端口号

方法:JSONP CORS Proxy

通常使用的是

8.二十个接口

9.插槽

10 key 作用

11.深拷贝浅拷贝运用场景

六 CSS

1.em与rem

em是相当于元素自身字体大小的一个单位

rem相当于根元素字体大小的一个单位

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html{
            font-size: 100px;
        }
        .div1{
            font-size: 50px;
        }
        .div2{
            /* width: 2em; ---->100px */
            /* width: 2rem;----->200px */
            height: 2em;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div class="div1">
        <div class="div2"></div>
    </div>
</body>
</html>

2.rem的适配原理

原理:利用媒体查询或者js检测获取设备宽度,不同宽度下设置相应的根元素字体大小。设备宽度变->根元素字体大小变->所有使用rem作单子的元素也变

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        document.documentElement.style.fontSize=document.documentElement.clientWidth/10+'px'
    </script>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .div1{
            width: 5rem;
            height: 50px;
            background-color: antiquewhite;
        }
    </style>
</head>
<body>
 <div class="div1">
 </div>
</body>
</html>

3.如何设置一个元素水平/垂直居中

1.方法1

父元素设置display:flex;然后通过justify-content:center;设置主轴居中;通过align-items: center;设置侧轴居中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
         .div1{
            display: flex;
            width: 100px;
            height: 100px;
            /* 主轴居中 */
            justify-content: center;
            /* 侧轴居中 */
            align-items: center;
            background-color: pink;
         }
         .div2{
            width: 50px;
            height: 50px;
            background-color: deeppink;
         }
    </style>
</head>
<body>
   <div class="div1">
    <div class="div2">
    </div>
   </div>
</body>
</html>

2.方法2

定位:子绝父相 子元素top:50%;left:50%;margin-top:‘子元素高的一半’,margin-left:子元素宽的一半 不要用百分比 相对于父元素的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .div1{
            width: 100px;
            height: 100px;
            background-color: pink;
            position: relative;
        }
        .div2{
            width: 50px;
            height: 50px;
            position: absolute;
            background-color: deeppink;
            left: 50%;
            top: 50%;
            /* 不要用-50% 是相对于父元素的 */
            margin-top: -25px;
            margin-left: -25px;
        }
    </style>
</head>
<body>
    <div class="div1">
        <div class="div2"></div>
    </div>
</body>
</html>

3.方法三

margin的缺点始要知道自身的大小

transform:translate(-50%,-50%)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .div1{
            width: 100px;
            height: 100px;
            background-color: pink;
            position: relative;
        }
        .div2{
            /* 宽高不确定 */
            width: 55%;
            height: 60%;
            position: absolute;
            background-color: deeppink;
            left: 50%;
            top: 50%;
            transform: translate(-50%,-50%);
        }
    </style>
</head>
<body>
    <div class="div1">
        <div class="div2"></div>
    </div>
</body>
</html>

4.BFC

4.1是什么

块级格式化上下文,是一种渲染特性。他决定了子元素将如何布局,以及和其他元素之间的关系

4.2如何触发

根元素()

浮动元素(float不为none)

绝对定位元素(position:absolute或者float)

其余参考MDN

4.3有什么作用

可以包含内部浮动元素

排除外部带来的影响

阻止外边距重叠

解决margin塌陷问题

5、position有几种属性值以及区别

position具有四个属性:static(默认的)、absolute、relative、fixed

fixed:相对于浏览器窗口定位的、不会随滚动条的滚动而滚动

absolute:基于不为static的父元素进行定位,脱离了标准流

relative:基于自身定位,没有脱离标准流,仍然占据空间

static:没有定位,是默认值

9、display有哪些值?说明他们的作用?

display:none; 设置元素隐藏,具体可见:display:none
display:block; 设置元素为块级元素,块级元素可以独占一行,可设宽高。
display:inline; 设置元素为行内元素,一行可有多个行内块元素,可设宽高。
display:inline-block 设置元素为行内块元素,既有行内元素的(一行可有多个)特性,又有块元素的(可设宽高)特性
display:inline-table inline-table 得到的是,外面是“内联盒子”,里面是“table盒子”。
display:table 元素会作为块级表格来显示,类似 table,表格前后带有换行符;配合table-cell使用可实现水平垂直居中,具体可见:水平垂直居中
table-row 元素会作为一个表格行显示,类似 tr;
table-cell 元素会作为一个表格单元格显示,类似 td和 th。
display:list-item 为元素内容生成一个块型盒,随后再生成一个列表型的行内盒。

10、css选择器有哪些?优先级是什么样子的

10.1 元素与优先级:

1.在属性后面使用!important会覆盖页面内任何位置定义的元素样式

2.作为style属性写在元素内的样式

3.id选择器

4.类选择器

5.元素选择器

6.通配符选择器

7.浏览器自定义或继承

总结排序:!important>行内样式>ID选择器>类选择器>元素>通配符>继承>浏览器默认属性

10.2 补充解释

通配符选择器 也称为全局选择器,就是对所有的htmlz元素起作用。语法格式为: *{propery:value}。其中“*”表示对所有元素起作用,property表示css的属性,value表示属性值。

    

7.git

1、git的一些使用和版本冲突的问题

1.1 git使用
1.1.1 新建分支

git clone 远端地址 拉取代码

git branch -a 查看本地分支与远程分支

git branch -r 查看远程分支

git branch 查看本地分支

git checkout -b 新分支 新建分支基于哪个分支下并且转到新分支

git log 查看当前分支记录

1.1.2 修改代码并合并

git add . 把工作时的所有变化提交到暂存区

git commit -m “提交说明” 要是将暂存区里的改动给提交到本地的版本库

git checkout develop 切换到主分支

git pull 拉取最新代码

git checkout 新分支 切换到新分支

git rebase develop 合并主分支

1.1.3 将代码推送到远程

*** 如果有冲突->修改文件之后提交

*git add .

*git commit -m “提交说明”

*git rebase --continue

git push origin 新分支 提交新分支

1.1.4 回退代码

(1) 回退到add 之前

git reset --soft HEAD^ 拉取服务器最近一次提交到暂存区,该操作不影响工作区

(2) 回退到指定版本

git reset --hard 目标版本号

git log 查看记录

1.1.5 添加暂存区

git stash save “save message” 添加到缓存区

git stash list 查看stash了哪些存储

git stash apply 应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1}

git stash pop 命令恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下,默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

git stash drop stash@{$num} 丢弃stash@{$num}存储,从列表中删除这个存储

git stash clear 删除所有缓存的stash

**注意:当在文件里面添加新的文件夹的时候git stash 不能追踪到 此时需要先添加到暂存区git add .

1.1.6 git revert和git reset的区别

原文https://blog.csdn.net/hudashi/article/details/7664460?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165158052016782246415098%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165158052016782246415098&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-6-7664460.142^v9^pc_search_result_cache,157^v4^control&utm_term=git+revert&spm=1018.2226.3001.4187

git revert 是生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留

git reset 是回到某次提交,提交及其之前的commit都会被保留,但是此次之后的修改都会被退回到暂存区

eg: 假设有三个commit

commit3: add test3.c

commit2: add test2.c

commit1: add test1.c

eg1 当执行git revert HEAD~1 commit2被撤销了

git log 可以看到

revert “commit2”:this reverts commit 5fe21s2…
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c

git status 没有任何变化

eg2 如果换做执行 git reset --soft(默认) HEAD~1后,运行git log

commit2: add test2.c

commit1: add test1.c

运行git status, 则test3.c处于暂存区,准备提交

eg3如果换做执行 git reset --hard HEAD~1后

显示:HEAD is now at commit2,运行git log

commit2: add test2.c

commit1: add test1.c

运行git status, 没有任何变化

***注意:git revert 是撤消该commit,作为一个新的commit。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值