前端面试题---

js

  1. js中的变量声明:在js中变量没有使用声明符号进行声明的时候,系统会自动创建一个全区变量的声明方式声明该变量

    1. 在js中声明变量由三种方式:第一中、不使用符号进行声明,该方式自动生成为全局变量
    2. 第二种、使用var符号进行声明,该符号声明变量会作为该作用域的全局变量
    3. 第三种、使用符号let进行声明,该符号的底层时函数自调用的形式,声明的变量只在本作用于本条声明之下起作用
  2. 闭包:

    1. 全局变量和局部变量时js变成中常用的变量形式
    2. 在java中,由公共的,私有的,自己和子代可用的三种权限
    3. 闭包就是用特殊的方法使用变量的私有化
    4. 使用方式
      1. 首先变量私有的形式,变量应该对象(对象/方法)内部
      2. 其次,当对象时对象的时候,可以使用 对象.属性名 调用,但是当对象时方法的时候,就没有这种调用模式了
      3. 获取变量的方法并不是直接进行变量的操作,而是在内部使用return的方法返回方法体
    //这里是一个对象
    var object={
      //对象的属性
      name:'obj',
      //获取对象的方法
      getName:function(){
        //方法体获取this指向
        var that=this;
        //返回内嵌方法体
        return function(){
          //通过let的只想问题访问obj的name
          console.log(that.name)
        }
      }
    }
    //使用对象的方法的时候】、
    obj.getName()
    //这种方法时无法执行打印的,因为返回的是一个方法function(){console.log(that.name)}
    obj.getName()();
    //这种方式可以执行getName()方法
    
    //创建方法,因为使用内嵌的return方式返回所以方法需要加()才能直接使用,函数自调用的方式
    var add = (function () {
    //内置属性,私有化,函数自调用的方式,该变量属于局部作用域
    var counter = 0;
    //返回方法
    return function () {
      <!-- 返回方法操作 -->
      return counter += 1;
      }
      //
    })();
    //这种声明的方式直接使用add()即可使用
    
  3. 作用域:作用域在js中分为函数作用域与全局作用域,表示的时一个集合,全局作用域表示的就是所有地方都可以访问到的集合,局部作用域就是只有在局部可以访问的集合

    1. 局部作用域:在js中指的就是函数的内部,同理声明在局部作用域中的变量就是局部变量,局部变量在函数创建的时候创建,函数结束的时候销毁
    2. 全局作用域:在js中指的时global对象,在前端浏览器中值得时windowd对象;这两个对象分别时node后端和前端浏览器的顶级对象,所有的属性和方法都是该对象的子;
    3. 全局变量的声明周期,程序运行的时候创建,程序结束的时候销毁
  4. 闭包的变量在外部无法访问,(不要是上面2中的对象形式)

  5. 重载与重写

    1. 说到重载,就必须提到多态,多态表示的是同一个方法名,但是因为参数列表的不同形成多种不同功能的方法
    2. 重写:重写一般指的是将在继承的时候,父类已经存在该方法但是,子类需要该方法,却与父实现由差异,这个时候直接使用原方法名与参数列表直接重写方法体
  6. 封装继承多态

    1. 封装就是制定一个模板,这个模板包含你需要的所有信息,但需要对象实例的适合用直接通过模板就可以创建
    2. 继承:原生的js的继承方式就是改变this的指向,或者以原型链的形式指定当前类的原型;在es6中封装了原生js的继承方法,使用extend可以继承
    3. 多态指的是参数列表不同形成同名不同体的方法
//这就是封装
function Person(name , age , sex){
  this.name = name ; 
  this.age = age ; 
  this.sex = sex ; 
  this.show = function (){
      console.log( this.age + "========"+ this.sex );
  }
}
//这里变更了this的指向
function Student(name , age , sex , score){
    this.score = score ; 
    Person.apply(this,[name , age , sex]);
}
function Worker(name , age , sex , job){
    this.job = job ; 
    Person.call(this,name , age , sex);
}
//这里使用的是原型链的方式
Dancer.prototype = new Person('Sunshine',18,'女');
function Dancer(salary ){
    this.salary = salary ;
}
var student = new Student('Sunshine',18,'女',100);
var worker = new Worker('Sunshine',18,'女','IT');
var dancer = new Dancer(20000);
console.log(student);
console.log(worker);
console.log(dancer);
  1. prototype

    1. 所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法。
    2. 构造函数名.prototype.新属性或者新方法
    3. 子对象,__proto__一般使用来操作父对象
  2. 创建‘类’

    1. 与对象的方法基本一致,区别在于对象使用{}或者使用new Object()方法,而创建类使用关键词function
function person(name,age){
  this.name=name;
  this.age=age;
}
  1. 数组对象的遍历,一般来说可以使用for循环,或者for in循环,或者for of循环

    1. for循环一般遍历数组
    2. for in循环适合变量键值对形式的对象
    3. for of循环使用遍历对象数组,无法获取到下标,不适合键值对形式
  2. 对象中的属性是什么变量?

    1. 不是全局变量,因为无法直接调用
    2. 不是局部变量,因为使用对象.属性名可以直接调用
    3. 是:对象变量的子变量
  3. 题目:要点使用var声明的变量会变量提升,赋值留在原地;使用let声明变量会在原地声明不会变量提升;不使用声明符号会在原地强制声明

// 第一个打印报错,因为没有声明
console.log(a);
// 已赋值,在原地强行创建变量a
a=10;
// 打印10
console.log(a)
  1. this的使用情况

    1. 方法调用模式 obj.fun(),这时指向的时obj
    2. 函数声明中的this,指向的时windows全局对象
    3. 使用new创建新的实例的时候的thisz指向创建的新实例
    4. 原型链添加方法中的this,谁调用指向谁
    5. call等this更换指向方法更换向谁就指向谁
  2. 闭包向外层抛出方法的方式

    1. 使用return function(){}
    2. 外层函数直接赋值该变量,将变量变成方法名
    3. 函数返回抛出一个对象或数组且里面包含方法
  3. 什么是BFC

    1. BOX FORMATING CONTENT
    2. 作用变量流布局或者外边距的重合与脱离文档里造成的父元素的自适应宽高出现问题
    3. 触发条件
      1. 在body元素直接子层
      2. float除none以外left或者是right
      3. position绝对定位absolute\fixed
      4. overflow除了visible所有值
  4. 垂直居中的方式

    1. 方式一:使用position方式;
      1. 步骤1:父元素使用position:relative
      2. 步骤2:子元素使用position:absolute,然后使用top:50%,这时候子元素距离父元素的上边距距离50%,再使用位移方式使用transform: translate();方式将自己平移;这里位移可以使用平移或者使用外边距都可以
    2. 方式二:使用绝对定位结合margin:auto方式可以垂直居中
      1. 步骤1:父元素使用相对定位
      2. 步骤2:子元素使用绝对定位,设置top:0;bottom:0;然后使用margin:auto可以实现自动垂直居中
    3. 方式三:使用padding垂直居中
      1. 这种方式需要父子元素的高都是绝对的,然后通过计算实现padding的值实现垂直居中
    4. 方式四:设置第三方空块状元素配合负外边距实现垂直居中
      1. 这种方式还是需要值到父子元素的高度,然后空块状元素占据父元素的50%高度,垂直居中的元素margin负的50%自己的高度
    5. 方式五:使用flex布局
      1. 父元素使用流布局并设置align-items:center,表示设置子元素的垂直居中,这种方法适用于文字和块级元素;align-items指定的是纵向的对齐方式,与主轴在哪个方向无关
    6. 方式六:使用流布局的justify-content垂直居中
      1. 父元素使用流布局,指定布局方向纵向flex-direction: column;然后使用justify-content:center布局垂直居中,需要注意的是:justify-content是指主轴上的位置,flex-direction: column;指定主轴是y轴了
    7. 方式七:使用line-height对单行文本进行居中
      1. 父元素的高度与汉高一致的时候,单行文本就会垂直居中,注意:line-height无法设置100%,使用百分比这里是相对字号来说的
    8. 方式八:使用display:table和 vertical-align对容器里的文字进行垂直居中
      1. 父元素设置显示方式为display:table表格的形式,子元素使用vertical-align:middle就可以垂直居中,**该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。**针对的是行内元素
  5. 图片与文字对齐

    1. 通过添加css的“vertical-align:”
      1. 使用这个的时候需要使用行内元素,不是行内元素指定为行内元素
    2. 如果图片是背景图片,可以在css中设置背景图片
      1. 作为背景图片的话,背景样式中由定位属性background: url(logo.jpg) no-repeat left center;
    3. 把文字和图片分别放入不同的div中
      1. 将图片与文字放在不同的div中,然后将div指定为行内元素,然后使用vertical-align
  6. 当子元素使用脱离文档流之后,父元素怎么自适应高度?

    1. 第一种,直接规定父元素的高度,不进行自适应了
    2. 第二种,使用clear属性,注意的是,使用clear不是在父元素中使用,而是在父元素内,结束标签之前使用
    3. 第三种,对父元素使用overflow:hidden,这里触发了上面所诉的BFC触发
  7. 数据库数据类型

    1. number:tinyint,smallint,int,bigint,float,double,decimal
    2. date:date,time,year,datetime,timestamp
    3. char:char,varchar,text,longtext
  8. char与varcahr

    1. char是定长字符串
    2. varchar是变长字符串
    3. 区别是,定长字符串在存储字符的时候不满足会补充空格达到定长,变长字符串长度不满足的时候会按照实际长度存储,长度限制表示最长可存储的字符数
  9. 数据库乱码问题

    1. 首先脚本编辑使用的编码固定为utf8(这里不仅可以使用utf8也可以使用其他的编码格式,但是后面的编码格式必须与这里保持一致)
    2. 其次脚本中第一行就要告诉数据库使用哪种编码格式 set names utf8
    3. 最后在脚本中创建数据库的时候需要使用 charset = utf8告诉数据库使用utf8创建数据库
  10. float和double区别

    1. 单精度浮点数与双精度浮点数,一个是4字节,一个是8字节
  11. continue与break

    1. 都是跳出循环,前者跳出当前循环,执行下一次循环,后者直接跳出循环体
  12. n=5 var num=n++ + ++n + n++ + ++n +n;

    1. 首先加法运算优先级低于自增自减
    2. 5+7 +7+ 9+ 9=37
    3. 扩展:运算符优先级
      1. 基本加减运算优先级都是最低的
      2. 括号是提升优先级的
      3. 赋值运算时从右向左的
      4. 指数运算也是从右向左的
      5. 同级别的运算除加减乘除外,嵌套的情况下基本都是从右向左的
      6. 运算符的优先级
  13. js的数据类型

    1. js的数据类型由数值型 number 字符串型 string 布尔型 Boolean 未定义型 undefined 空值 null 引用对象 object
  14. undefined 与null的区别

    1. undefined 表示的时为定于,属于js的基础数据类型,表示对额树变量声明后未进行赋值
    2. null 表示的是对象不存在,对象的值未设定,也是js的基础数据类型,一个特殊作用就是当一个变量原本指向一个对象时,将变量更改指向null则原来的对象就会被销毁(手动销毁对象)
    3. 特殊点,使用typeof将车null的数据类型的时候又会显示为object类型
  15. 函数自调用

    1. 函数自调用形式加载到了就会立即执行,且函数自调用会创建一个局部作用域
  16. 数组的方法

    1. 创建数组的方法由字面量创建数组,由使用Array对象创建数组
    2. 访问数组的元素需要使用到数组的下标
    3. 遍历数组,可以使用原生的for循环,可以使用 for in 循环,可以使用数组的forEach方法
    4. 注意:使用forEach方法遍历数组时,传递的是一个自定义方法(遍历规则)
var arr = [1,2,3,4];
// 需要遍历的数组
var sum =0;
// 自定义变量存储求和
arr.forEach(function(value,index,array){
// 这里的valuex形参承接的时数组中的每一个元素,index承接的时数组元素的下标,array承接的是数组本身
 array[index] == value; //结果为true
// 这里array[index]与value是array中同一个元素
 sum+=value; 
// 求和计算
 });
// 打印sum
console.log(sum); //结果为 10
  1. 数组的元素的添加删除方法

    1. 默认的数组是先进后出的方式
    2. 添加元素的方法由两种,分别是push和unshift
      1. push是从数组的末尾开始添加元素,下标是数组原本的长度length
      2. unshift是从数组的开头添加元素,下标永远是0
    3. 删除元素的方法同样也有两种,分别是pop和shift
      1. pop默认删除最后一个下表是length-1的元素
      2. shift默认删除下标为0的元素
  2. 特殊的删除与添加方法

    1. splice
    2. 该方法最少有两个元素,开始下标,与删除个数,splice(index,num,…items)
    3. 表示的意思是从下标index开始删除num个元素然后再该位置添加元素
  3. splice与slice的区别

    1. splice是删除并添加新元素方法
    2. slice是截取新数组方法,有两个参数,是开始下标和结束下标
    3. slice返回的是一个新数组,对原始数组不做修改;splice对原始数组会进行操作修改
  4. filter过滤方法与map指定元素处理方法,与ES6的reduce方法

    1. filter方法传递的是一个规则方法,该方法有一个参数用来传递数组的元素,filter会默认对数组进行遍历然后将元素传递到规则方法中,由规则方法进行判读,使用return返回判断后的值,返回的值会存在与创建的一个新数组中
    2. map方法会返回一个新的数组,该方法会默认遍历数组,由传递的规则方法对元素进行处理
    3. reduce是es6的新方法和map,filter方法一样会对数组进行遍历然后传递该规则方法对数据进行处理,会返回新的数组
  5. reducer 函数接收4个参数:

  • Accumulator (acc) (累计器)
  • Current Value (cur) (当前值)
  • Current Index (idx) (当前索引)
  • Source Array (src) (源数组)
  • arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
  1. javascript数组去重的方式

    1. 方式一:使用ES6的Set对象进行去重,因为Set对象元素不可出现重复的值,所以,可以利用去重const aa=[...new Set(array)]或者使用array.from方式冲类似数组对象中获取const bb=Array.from(new Set(array))
    2. 使用for循环嵌套去重,将冲的元素删除
    3. 新建一个空的数组对象,遍历旧的数组对象然后获取对象元素,一次使用indexOf测试新数组中有没有该元素,没有就添加到新数组,有的话就跳过,最后得到的新数组就是一个没有重复元素的数组
    4. 利用sort排序方法,思想是当数组执行sort方式后,判断相邻的两个元素是否相等,相等就pass,不相等间件当前元素添加到新数组
    5. 利用数组的includes方式进行数组的元素是否存在判断,不存在添加,存在pass
  2. 浅拷贝与深拷贝

    1. 浅拷贝只是将数据地址进行赋值,源对象变更复制的对象的数据也就变更了
    2. 深层拷贝就是数据本身也进行了复制,他们的堆内存中的地址是不一样的,所以源对象数据变更不会影响到复制对象的数据
  3. 浅拷贝的实现,与深拷贝的实现

    1. 使用json来回转换
    2. 用for…in实现遍历和复制
    3. 利用数组的Array.prototype.forEach进copy
    4. 浅拷贝使用object.assign方法
  4. 优先级wenti

    1. 加减运算的优先级大于比较运算的优先级
  5. jsonP跨域

server.on('/login/:waysName',function(req, res){
   req.params.waysName==>jsonp
   req.query.callback==>test
//    主要的是后端判断是否使用jsonp的方式进行数据返回
// 前端script路径传递参数的时候需要传递一个callback函数名
// 该函数时前端脚本中全局夯函数,因为当jsonP方式获取到服务端的文件后会立即加载,然后会立即执行,这里调用全局函数用来处理数据
    var urlPath = url.parse(req.url).pathname;
    // 这里是使用url接续地址,哦判断是不是使用jsonP方式进行获取数据
    var qs = querystring.parse(req.url.split('?')[1]);
    // 这里时使用解析查询字符串确定返回的callback使用哪个方法进行树的处理
    if(urlPath === '/jsonp' && qs.callback){
        // 对返回头进行设置
        res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
        // 需要发送的数据
        var data = {
            "name": "Monkey"
        };
        // 将其转化为json字符串
        data = JSON.stringify(data);
        // 拼接返回的json的字符串
        var callback = qs.callback+'('+data+');';
        // 返回字符串
        res.end(callback);
    }
    else{
        res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
        res.end('Hell World\n');    
    }    
});
<script src="http://127.0.0.1:8080/login/jsonp?callback=test">script>
  1. 使用cors进行跨域
    1. 使用npm包管理器进行下站cors第三方模块
    2. 使用require加载该模块
    3. 挂载并设置该模块
  • Access-Control-Allow-Origin指示请求的资源能共享给哪些域。
  • Access-Control-Allow-Credentials指示当请求的凭证标记为 true 时,是否响应该请求。
  • Access-Control-Allow-Headers用在对预请求的响应中,指示实际的请求中可以使用哪些 HTTP 头。
  • Access-Control-Allow-Methods指定对预请求的响应中,哪些 HTTP 方法允许访问请求的资源。
  • Access-Control-Expose-Headers指示哪些 HTTP 头的名称能在响应中列出。
  • Access-Control-Max-Age指示预请求的结果能被缓存多久。
  • Access-Control-Request-Headers用于发起一个预请求,告知服务器正式请求会使用那些 HTTP 头。
  • Access-Control-Request-Method用于发起一个预请求,告知服务器正式请求会使用哪一种 HTTP 请求方法。
  • Origin指示获取资源的请求是从什么域发起的。

后端的时候挂载使用cors方式app.use(cors());这种方式中使用的挂载是没有设置具体参数的,这种情况表示的是允许所有的跨域请求

为单个的请求进行跨域部署:

app.get('/', cors(), (req, res) => {
    res.json({
        message: 'Hello World'
    });
});

用选项配置cors:自定义选项配置跨域

var corsOptions = {
    origin: 'http://localhost:8080',
    optionsSuccessStatus: 200 // For legacy browser support
}
app.use(cors(corsOptions));

这种表示可以从地址localhost:8080访问该API,禁止其他域进行访问
39. 使用代理跨域方式
1. 再vue脚手架的项目中配置vue.config.js文件配置

module.exports = {
  devServer:{
    proxy:{
      "/juhe":{
        target:"http://apis.juhe.cn",
        changeOrigin: true,
        secure:false,
        pathRewrite:{
          "^/juhe":""
        }
      }
    }
  }
}
  1. 回调函数
function handle(data){
    console.log(data);
}
function test(sql,callback){
    let arr=sql.split('');
    callback(arr)
}
test('我是山大王',handle)
  1. HTML5的新特性
    1. 语义化标签一套
      1. header \ section \aside \footer \article\nav \details…
    2. 增强型表单
      1. 增强型表单主要是input标签的type分类增加了很多预定义的内容
      2. 新增了几个特殊标签
      3. 新增了表单属性
    3. 视频和音频
      1. audio音频
      2. video视频
    4. canvas绘画
      1. 绘画元素使用js进行操作
      2. 步骤:1、获取canvas绘画的元素的位置;2、获取到2d元素的上下文对象;3、对模板进行绘制
    5. svg绘图
    6. 地理定位
      1. 使用getCurrentPosition()方法来获取用户的位置。以实现“LBS服务”
    7. 拖放API
      1. draggable=“true” οndragstart=“drag(event)”
      2. 拖动生命周期?:拖动开始ondragstart,拖动过程中ondrag,ondragenter,ondragover,ondragleave,,拖动结束ondrop ,ondragend
    8. webworker
      1. Web Worker可以通过加载一个脚本文件,进而创建一个独立工作的线程,在主线程之外运行。Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类加载一个javascript文件来开辟一个新的线程,起到互不阻塞执行的效果,并且提供主线程和新县城之间数据交换的接口:postMessage、onmessage。
    9. webstorage
      1. websorage拥有5M的存储容量,而cookie却只有4K,这是完全不能比的。cookie作为HTTP协议的一部分用来处理客户端和服务器的通信是不可或缺的,session正式依赖与实现的客户端状态保持。localStorage:没有时间限制的数据存储sessionStorage:在浏览器关闭的时候就会清除。
      2. cookie会随着请求一起发送,但是webstorage不会
      3. webstorage的存储数据的方式是使用键值对的方式进行数据的插入操作,获取直接根据对应的key进行获取
    10. websocket
function draw(){
    var canvas = document.getElementById('tutorial');
    if(!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "rgb(200,0,0)";
      //绘制矩形
    ctx.fillRect (10, 10, 55, 50);
 
    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
    ctx.fillRect (30, 30, 55, 50);
}
draw();
  1. let const var

    1. var声明的是当前作用域下的全局变量,存在变量提升
    2. let声明的是一个局部变量,且不存在变量提升,let的存在使得js的块级作用域以另外一种方式实现
    3. const表示的是声明一个常量,常量声明后不可更改
  2. 结构与赋值

    1. 解构的方法是使用对应的位置设置变量承载被解构对象的对应位置的数据let [a, b, c] = [1, 2, 3];
    2. 打散运算符 … ;该运算符使用在实参列表表示的是打散操作,将对象的数据全部打散提出;使用在形参列表中表示收集
  3. map对象

    1. map是一个类数组对象,存储的方式是键值对,类似于索引数组
    2. 特点map的键值对中的key可以使用任意类型的数据
  4. Set对象

    1. set对象也是一个类数组对象,存储方式与数组相似;索引下标为数字下标
    2. 特点是set中不允许出现重复的值,0加正负符号表示判断是一致的,undefined判断是一致的NAN判断不是一致的但是也只能存在一个
    3. set的常用方法之一是数组去重,因为set的构造函数存在使用数组当作参数创建Set对象的方式
  5. ES6 Proxy方式
    4. Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式
    5. Proxy类似使用了了属性访问器,自定义规则

let target = {
    name: 'Tom',
    age: 24
}
let handler = {
    get: function(target, key) {
        console.log('getting '+key);
        return target[key]; // 不是target.key
    },
    set: function(target, key, value) {
        console.log('setting '+key);
        target[key] = value;
    }
}
let proxy = new Proxy(target, handler)
proxy.name     // 实际执行 handler.get
proxy.age = 25 // 实际执行 handler.set
// getting name
// setting age
// 25

面试重点

  1. 深拷贝 浅拷贝 (小程序js高级第二天)面试必问

深拷贝与将拷贝的区别在于浅拷贝拷贝的对象与原目标对象指向的是不是同一个数据对象;浅拷贝拷贝的对象,两个对象有一个数据被更改,另外一个都会获取到被更改后的数据,深拷贝数据更改不会影响到另一个对象;另外先简单的数字字符串等赋值使用拷贝不会出现被更改的现象;这是因为存储的位置不同导致的;浅拷贝和深拷贝是针对存储在堆内存中的数据来说的,存储在栈内存的数据不存在深浅拷贝的现象

  1. this的指向问题

this的使用场景,在定义函数的时候且该this没有被使用,使用this,这里指向的是windows或者global全局对象;在调用的时候使用的this指向的是被调用的对象,谁调用指向谁;构造函数中的this一般是自动指向的空对象,函数内部的this就会被空对象替换掉;如果这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

  1. js的执行机制是什么?想在js中实现异步执行一段代码应该怎么写呢?

js的执行是同步的,也就是阻塞的,顺序执行,现在js中异步执行一段代码需要使用异步函数,比如说setTimeOut方式或者是SetInterval方式执行;另外就是使用事件监听的方式减函数执行为异步函数;使用观察者模式执行;使用ES6的Promises方式执行

  1. 事件模型(三个阶段:捕获,目标触发,冒泡)(小程序Dom最后一天)

事件模型指的是在HTML中的DOM操作,捕获,目标触发,冒泡;捕获阶段是首先要确定你需要在声明地方实现事件触发,需要通过DOM操作获取到绑定事件的元素;目标触发对触发事件的元素添加事件监听,等待触发获取触发事件;冒泡,指的是事件触发时,事件会从当前点击开始以从内向外的方式依次触发上层元素的事件,称为事件冒泡;

  1. 事件冒泡是什么?有什么办法可以阻止冒泡?

事件冒泡是当在一个元素上绑定一个事件,比如说点击事件,然后该事件被触发,如果定义了该事件触发处理函数,就会调用这个函数,如果没有就会先父级对象传递该事件,直至获取到事件处理函数,或者到达顶级元素(需要注意的是,冒泡会一致冒泡到顶级祖先元素);阻止事件冒泡的方法:1使用event.stopPropagation()进行事件冒泡的阻止;注意的是该方法会阻止事件冒泡但是不会阻止先超链接标签的默认事件行为;2jquery使用return false方式可以阻止冒泡和标签的默认行为;3、使用event.preventDefault(); 会阻止标签的默认事件

  1. 常用数组api

常用的数组的API有以下几种作用:截取数组、删除数组元素、删除并插入数组元素、将数组转换为字符串、数组的链接组合为新数组、获取数据元素的下标、数组是否包含特定的元素、数组的反转、数组的排序、数组的遍历,方法:

  • slice(start,end) 选取数组的一部分返回一个新的数组
  • splice(index,num,…item) 删除从index开始的num个数组并从index开始插入后面的元素item
  • join() 将数组的元素都放到一个字符串对象中默认使用逗号分开,可以指定分割符号
  • concat() 将两个数组拼接为新的数组
  • indexOf () 获取指定元素的下标,存在返回元素的下标,不存在返回-1
  • includes() ES6的方法,获取数组中是否包含指定的元素,存在返回true,不存在返回false
  • reverse() 该方法会减数组的元素的顺序反转
  • sort()该方法用来给数组排序,默认是按照字符编码排序,可以指定排序规则
  • forEach 方法该方法会自动遍历数组,传递参数callback,回调函数会有三个参数,分别是元素,下标和数组,可以自定义规则对元素进行处理,使用return返回处理结果
  1. Css弹性布局

css弹性布局的使用方法:display:flex
弹性布局的几个属性:

  • flex-direction:该属性指定弹性布局的主轴方向,row表示横轴为主轴,column表示纵轴为主轴,row-reverse表示横轴从右到左,column-reverse表示的是纵轴从下到上
  • justify-content:该属性表示内容对齐方式,有几个参数,分别是flex-start,flex-end,center,space-around,space-between’;需要注意的是该属性与主轴指向息息相关
  • align-items:表示的是内部元素的纵轴排列方式
  • flex-wrap:该属性表示的是内部元素的这行方式,默认是不折行的
  1. Css页面布局单位

css布局单位有px像素,em相对父元素的字体大小,rem相对根元素的字体大小,%百分比,vw相对屏幕宽度的百分比,vh相对屏幕高度的百分比,rpx手机端的相对宽度但闻,移动端全部为750rpx

  1. Css选择器

css选择器,有id选择器,类选择器,伪类选择器,属性选择器,子代选择器,后代选择器,兄弟选择器,标签选择器,分组选择器等等

  1. 怎么去清除浮动

清除浮动:在浮动的元素后面紧接着的元素的样式中使用clear属性;使用BFC方式清除浮动,(父元素使用overflow:hidden、父元素也添加浮动属性、使用::after伪类为元素添加一个clear属性、父元素使用定位)

  1. 闭包的原理 适用场景 (小程序js高级第一天)

闭包就是减变量放到了函数作用域中这样在全局的情况下就没法直接访问函数作用域中的变量,然后为了访问函数作用域的变量,在函数内部定义与获取或者操作方法,然后将该方法作为返回值返回外层对象

  1. 为什么跳转页面,有些样式没有生效(小程序vue第七天 history模式)

跳转页面后有些样式没有生效,1、样式写错了2、样式绑定的元素没有加载、3、样式文件路径错误
使用history的时候,history唯一改变的就是url的模式,使用history后跳转页面后的样式没有生效,可能是因为打包产生了路径的变化但是在路由中并没有做相应的配置

  1. 普通函数和箭头函数的区别

箭头函数省略了function 关键字,当参数只有一个的时候,甚至省略了小括号,当函数体是return时且只有一行的时候省略了大括号和关键之return

  1. Computed和watch的区别 watch 如何监听

computed是计算属性,组件的声明周期中只执行一次;watch是监听函数模块,只要被监听的变量出现变化,就会触发对应的监听函数。监听函数使用被监听的函数的变量名作为监听的方法名

  1. Keep-alive两种函数作用

keep-alive保持存活,组件间的相互切换默认是会销毁掉被切换掉的组件,重新切换到该组件的时候重新初始化,当有要求保持不销毁组件的时候要求保持原来的状态就可以使用keep-alive
使用方法是在路由字典中使用meta字段,添加keepAlive?:true属性即可,然后使用keep-alive的标签包含router-view,结合v-if使用

<keep-alive>
    <router-view v-if='$route.meta.keepAlive'>
keep-alive>

使用方式二:组件的script结构中,包含参数name:'自定义命名';,在使用的时候使用keep-alive标签包含组件使用标签,并使用属性include='name'

<script>
export default {
name: 'a',
data () {
return {}
}
}
script>

<keep-alive include='a'><component>component>keep-alive>

<keep-alive exclude="a"><component>component>keep-alive>
  1. Mutation action getter 具体用法

这三个都是VUEX的组成部分,Mutation表示的是对VUEX保存的数据的修改方法的集合,action表示的是一些执行方法的集合,提交的是mutations,getter表示的是获取数据的方法的集合
使用方式一:
getters: 直接使用this. s t o r e . g e t t e r s . 方 法 名 ( 参 数 ) m u t a t i o n s : ‘ t h i s . store.getters.方法名(参数) mutations:`this. store.getters.mutations:this.store.commit(‘increment’),传递参数的使用方式:store.commit(‘increment’, 10)actios:store.dispatch(‘increment’)**使用方式二:** getters:在使用的组件中使用import { mapGetters } from 'vuex’在组件的需要使用的对象中使用打散符号,将方法布置到当前组件中 mutations:import { mapMutations } from ‘vuex’`

  1. Mvvm(小程序vue第一天) MVC diff算法

model+view+view-model,model+view+controler
diff算法就是用来比较虚拟dom树和真实DOM树的不同之处,然后将虚拟dom树的不同指出修改到真实dom树上

  1. Foreach和map的区别 Foreach和for of for in的区别

for: 循环可以使用break,containue,return
forEach: 数组自带的遍历方式,自动遍历数组,
map: 只能遍历数组,具有返回值
for of: 遍历具有迭代器属性的数组类数组对象,无法获取下标
for in: 会遍历原型链数据

  1. Reduce里不加初始值有什么区别呢?

Reduce里传递的是用改方法函数,作为累加器,如果不传递参数,会报错undefined is not a function

  1. Get和post的区别 大概率会问

get是不安全的,属于明文,所有的传递的参数信息都会在url中显示出来,post对用户来说是不可见的;get传递的数据少,因为url的长度是幽香的,post传递的数据多,一般漠然不受限制;get执行效率比post高

  1. Json字符串解析

JSON.parse()将json字符串还原成对象,JSON.stringify()将对象转换为字符串

  1. Axios如何同步执行

axios本身是一种异步请求方式,想要使用axios进行同步执行,需要使用async -await
ES7中对异步操作可以使用async -await进行同步限制,async修饰的同步方法需要等待await修饰的代码操作完成才能继续执行
使用方式:

async reated(){
    let data = await axios.get(url,pramas{
        id:1
    }).then(res=>console.log(res))
}
  1. 说说axios怎么封装?

可以创建一个js文件用来保存封装的axios方法
- 导入axios对象 import axios from 'axios'
- 设置默认请求地址 axios.defaults.baseURL = 'http://shopping.com/'
- 设置默认超时事件 axios.defaults.timeout = 10000
- 请求头设置 axios.defaults.headers.post['Content=Type']='application/json'
- 设置方法 function get(){} function post(){}
- 将设置的请求方法进行导出 moudle.export={get,post}

  1. 虚拟Dom树是什么

虚拟DOM树是一个元素对象树,用来描述一段html片段的,当页面渲染的时候,会创建一个虚拟dom树,再次渲染的时候会从新创建一个新的虚拟DOM树,通过diff算法,记录新旧虚拟DOM的差异从而将差异更新到真实DOM树上

  1. Vue双向绑定的原理是什么 访问器属性+虚拟Dom树 必问

vue的双向绑定的原理是虚拟DOM树加上属性访问器,原理的官方名称为数据劫持加发布者模式+订阅者模式;使用属性访问器给data中的对象添加get,set规则,使用虚拟DOM树查找修改差异,渲染到真实DOM树上;view-model可以通过事件绑定进行一个监听,动态更改数据变化;虚拟DOM树实现从 model到view的数据渲染

  1. v-if(删除)和v-show(dispaly:none)的区别 必问

两者都是根据条件判断是否显示,不同之处在于v-if是直接销毁元素,而不是隐藏元素,v-show是对元素进行了隐藏,display:none

  1. vue的生命周期 create和beforeMount之间发生了那些事情?(vue第四天笔记)

vue的声明周期有create,mount,update,destory分别由两个钩子函数,before和after,表示该生命周期前后执行。create生命周期包含beforeCreate,created,afterCreate三个阶段

  1. 谈谈原型链 大概率会问

js中所有的函数都有一个原型对象属性,这个原型默认是Object的实例,也就是一个空对象;原型链简单来说就是由原型对象属性构成的链状结构,对象的__proto__属性就是该对象的原型,原型也是对象也有该属性,所以形成一个链状结构,这个结构到Object这里也就到头了;instanceof是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址.使用原型链可以实现继承。

  1. Es6 新特性 大概率会问

首先变量方面的由let,const,然后是解构,打散收集符号,模板字符串,箭头函数,参数加强(默认值设置),class类与继承extend,子类的super方法,for of遍历方法和for in

  1. 数组去重 大概率会问

一种方法利用ES6的Set对象元素不能重复,且Set的构造方法可以传递一个数组,直接将数组作为参数创建一个Set对象,然后将对象打散到一个新的数组中,新的数组没有重复元素;一种思想,创建一个新空数组,遍历原本的数组,判断每个元素在新数组中是否存在,存在就pass不存在就添加到新数组,至于使用什么方法,for循环遍历,数组的forEach方法,数组的map方法,indexof,includes等均可

  1. Promise有哪些状态? 每个状态分别触发什么方法? catch方法触发了会怎么影响后续代码 大概率会问

Promises由三种状态分别是进行中,已履行,拒绝,pending,fulfilled,rejected,进行中表示正在执行,这个时候不会触发方式,旅行表示执行结束通过,这时候触发resolve方法传递参数给.then方法里的callback,拒绝触发reject方法,也会传递参数,给.catch方法

  1. Async,await和promise有什么关系?

promises是一种构造函数,使用new Promises创建的对象都会带有.then,.catch…all等方法,promises用来解决使用异步函数回调函数的深层嵌套产生回调地狱的象先,使得异步函数可以实现链式编辑;async以及await是ES7出现的,优化Promises的解决方案;async是修饰符号,被修饰的函数会默认返回一个promises对象,所以可以直接进行.then操作;await也是一个修饰符,和async一致,返回的是一个Promises对象,表示的是等待一个异步操作完成的结果
Promise可以避免异步种的回调地狱 使异步变得更加简单清新,更可控
async以及awai却是为了简化Promise,可以说async以及awai是JavaScript异步编程目前的终级解决方案

  1. vue-router是什么 必问

vue-router是路由,官方的路由管理器。通过vue-router方便管理和跳转组件。vue项目都是单页面项目,使用路由可以实现组件间的跳转。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。而之所以不适用a标签是因为单页面标签只有一个html

  1. Vue组件传参(小程序vue第三天) 必问

vue组件间的传参一般由vueX方式传参,路由传参,父子组件间传参可以使用props方式传参,子传父参数不仅可以使用vueX方式传递参数,还可以使用Vue本身(在父元素中定义方法myfun,子元素中使用this.$emit(‘myfun’,item)既可以激活使用父组件中的myfun方法,并传递子组件的数据)

  1. 路由传参 (小程序vue第五天)

路由传参方式一:在路由字典中的path属性中配置例如 path: ‘/login/:userId/:id’,配置字典中的name属性,传值页面的跳转使用传递对象的方式进行跳转,使用name关键字进行路由的映射,使用params对象传递查询字符串,获取查询字符串的方式是this. r o u t e . p a r a m s . 查 询 参 数 名 ( 或 者 直 接 使 用 p a t h t h i s . route.params.查询参数名(或者直接使用path this. route.params.使paththis.router.push(’/login/uname.upwd’方式,获取还是使用this.$route.params.userId...))
路由传递参数二:使用query的方式进行查询字符串传参,传递参数this.$router.push({path:'/login',query:{userId:'雄安命'}}),获取传递参数的方式是this.$route.query.userId或者是this.$router.currentRoute.query.userId
第三种使用方式:

  1. 组件传值,父传子,子传父

组件传值一般使用的较多的是vueX方式,该方式满足各种方式的组件传值,另外还有利用路由跳转携带参数传值的,父子组件中可以使用props方式进行父传子,子传父可以使用vuex,使用vue的emit方法唤醒父组件的自定义方法,并传递子组件的参数

  1. Vuex 是什么

vueX是一公告的数据源,是一个专门为vue开发的状态管理模式,核心是store,用来保存数据的,还有其他几大对象比如getters,moutations,actions,moudles几大模块,分别保存对state的数据的获取方法,更改方法,对更改方法集合对象操作的方法,以及模块管理集合

  1. Vue是怎么监听路由变化的? 简单的讲讲什么是路由守卫

如果需要监听路由变化可以使用vue的watch方法

watch:{
	$route(to,from){
	  console.log(from.path);//从哪来
	  console.log(to.path);//到哪去
        this.刷新方法
	}
}

监听路由变化获取新老路由的值

watch:{
    $route:{
      handler(val,oldval){
        console.log(val);//新路由信息
        console.log(oldval);//老路由信息
      },
      // 深度观察监听
      deep: true
    }
  }

监听路由触发的方法

methods:{
  getPath(){
    console.log(1111)
  }
},
watch:{
  '$route':'getPath'
}

全局监听路由可以使用路由首位监听

// 全局监听路由
router.beforeEach((to, from, next) => {
    console.log(to);
    next();
});

组件内监听路由

 beforeRouteEnter (to, from, next) {
     // 在渲染该组件的对应路由被 confirm 前调用
     // 不!能!获取组件实例 `this`
     // 因为当钩子执行前,组件实例还没被创建
 },
 beforeRouteUpdate (to, from, next) {
	 // 在当前路由改变,但是该组件被复用时调用
	 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
	 // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
	 // 可以访问组件实例 `this`
 },
 beforeRouteLeave (to, from, next) {
	 // 导航离开该组件的对应路由时调用
	 // 可以访问组件实例 `this`
 }

什么是路由首位?路由首位就是在路由执行之前或者之后执行的路由方法,主要用来通过跳转或取消的方式守卫导航。路由首位有全局的,单个的还有组件级别的。
全局前置守卫:前置守卫顾名思义就是导航触发的时候先会经过前置守卫,当前置守卫执行执行玩发出resolve之后,导航才会执行
全局解析守卫:导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置钩子: 这些钩子不会接受 next 函数也不会改变导航本身
路由独享守卫: 单独在路由字典中对应的路由上直接设置路由
组件内的守卫: 组件内特殊的钩子方法beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave分别表示路由调用前,当前路由改变但是该组件被复用,导航离开当前组件

  1. 用过哪些开源的组件?

Echarts可视化组件,vantUI,miniUI,elementUI,bootstrap,swiper等

  1. 发布订阅模式,观察者模式
    1. 发布订阅模式指定就是一种一对多的关系,他不是具体的代码编写方法,而是一种解决问题的方案;当发布者的数据发生改变的时候,订阅者会受到通知,相应的订阅者的数据也会发生相应的改变。也就是对对应数据进行监听。现在的编程中发布者与订阅者之间没有直接链接,是通过中间件进行的稍息的分发称为消息代理;发布订阅模式与观察者模式之间的区别是有没有消息代理
  2. vue中 关于$emit的用法
    $emit属于vue的实例方法/事件,主要作用是触发当前实例上的事件,回调函数会接收所有传入事件触发函数的额外参数。
vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')

可以利用监听事件和触发事件进行子传父的阐述传递

  1. 分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景。

display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击

  1. 文本超出访问后使用省略号省略并隐藏超出部分

text-overflow: ellipsis; overflow: hidden; display: -webkit-box; /重点,不能用block等其他/ -webkit-line-clamp: 2; //行数 /*! autoprefixer:off / -webkit-box-orient: vertical; / autoprefixer:on */

这种指定了文本的行数,可以多行不确定文本函数但确定会溢出,使用over-flow隐藏溢出内容,然后使用伪类::after方法创建一个伪元素,使用内容为省略号

div{
  width: 300px;
  position: relative;
  line-height: 1.4em;
  height: 4.2em;
  overflow: hidden;
}
div::after{
  content: "...";
  position: absolute;
  right: 0;
  bottom: 0;
}
  1. 什么是防抖和节流?

防抖就是避免用户连续在一定时间内不停触发事件,限制单位时间内时间触发的次数;节流:在事件发生后一段时间后执行触发事件,这期间用户继续触发动作视为只触发一次,直到事件执行完毕后才能重新触发

你可能感兴趣的:(面试,面试)