Vue前端面试题--2021.11.29(非vue3)

2021-12-16  本文已影响0人  誰在花里胡哨

前段时间总结的部分面试题,有需要的可以看下哈~~😁

什么是构造函数

用 new 关键字来调用的函数,称为构造函数。构造函数首字母一般大写

function Person4() {
  this.gender = '男';
  // return { gender: '中性' };
}
var p4 = new Person4();
console.log(p4.gender);  // '中性' 

什么是继承

继承指的是一个对象可以共享父级对象的一些属性。

什么是原型链

对于对象而言,每个 JS 对象一定对应一个原型对象,并从原型对象继承属性和方法。对象proto属性的值就是它所对应的原型对象。对象的proto指向自己构造函数的 prototype。所以对象的原型链就是obj.proto.proto__....。

function Person() {
  return { };
}
var p = new Person();
console.log(p)
// {}
[[Prototype]]: Object
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()

对于函数而言,只有函数才有 prototype 属性,Person.prototype 是一个对象,并且有两个属性, 一个是 constructor 指向其构造函数 Person, 一个是 proto 属性:是一个对象,指向上一层的原型。

console.log(Person.prototype)
// {constructor: ƒ}
// constructor: ƒ Person()
// [[Prototype]]: Object

所有的对象会一层层往上找原型,最终点是 Object,而 Object 的上一层原型就是 null 了。

this的指向

cookie、localStorage和sessionStorage 三者之间的区别

ES6常用语法

let [a,b] = [1,2]
let {a,b} = {a:1,b:2}
let str = `${name}的女朋友`;
  let str = ' 10 10 ';
  console.log(str); // ' 10 10 '
  console.log(str.trim()); // '10 10'
  // 如果要去除所有空格
  let str = ' 10 10 ';
  console.log(str.replace(/ /g, '')); // 1010
(1)箭头函数没有自己的`this`对象,内部的`this`就是定义时上层作用域中的`this`。。

(2)不可以当作构造函数,也就是说,不可以对箭头函数使用`new`命令,否则会抛出一个错误。

(3)不可以使用`arguments`对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用`yield`命令,因此箭头函数不能用作 Generator 函数。
let obj = {...obj1}
let arr = [...arr1,...arr2] //合并数组 对象类似
[...'hello'] 
// [ "h", "e", "l", "l", "o" ]
let arr = [1,2,[3,4],[5,6,[7,8]]]
console.log(arr.flat(1)); //[1, 2, 3, 4, 5, 6, Array(2)]
console.log(arr.flat(2)); //[1, 2, 3, 4, 5, 6, 7, 8]

数组去重方法

Array.from(new Set(arr))
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];

function unlink(arr) {
    for (var i = 0; i < arr.length; i++) {    // 首次遍历数组
        for (var j = i + 1; j < arr.length; j++) {   // 再次遍历数组
            if (arr[i] == arr[j]) {          // 判断连个值是否相等
                arr.splice(j, 1);           // 相等删除后者
                j--;
            }
        }
    }
    return arr
}
console.log(unlink(arr));
var arr = [1, 1, 8, 8, 12, 12, 15, 15, 16, 16];
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
console.log(unique(arr))

数组排序

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b}); 
// 1,5,10,25,40,100 升序 反之 b-a 降序

类型判断

基本数据类型:Undefined、Null、Boolean、Number、String,Symbol
引用数据类型 :Object

let bool = true;
let num = 1;
let str = 'abc';
let  und= undefined;
let nul = null;
let arr = [1,2,3,4];
let obj = {name:'xiaoming',age:22};
let fun = function(){console.log('hello')};
let s1 = Symbol();
console.log(typeof bool); //boolean
console.log(typeof num);//number
console.log(typeof str);//string
console.log(typeof und);//undefined
console.log(typeof nul);//object
console.log(typeof arr);//object
console.log(typeof obj);//object
console.log(typeof fun);//function
console.log(typeof s1); //symbol
console.log(bool instanceof Boolean);// false
console.log(num instanceof Number);// false
console.log(str instanceof String);// false
console.log(und instanceof Object);// false
console.log(nul instanceof Object);// false
console.log(arr instanceof Array);// true
console.log(obj instanceof Object);// true
console.log(fun instanceof Function);// true
console.log(s1 instanceof Symbol);// false
console.log(bool.constructor === Boolean);// true
console.log(num.constructor === Number);// true
console.log(str.constructor === String);// true
console.log(arr.constructor === Array);// true
console.log(obj.constructor === Object);// true
console.log(fun.constructor === Function);// true
console.log(s1.constructor === Symbol);//true
console.log(Object.prototype.toString.call(bool));//[object Boolean]
console.log(Object.prototype.toString.call(num));//[object Number]
console.log(Object.prototype.toString.call(str));//[object String]
console.log(Object.prototype.toString.call(und));//[object Undefined]
console.log(Object.prototype.toString.call(nul));//[object Null]
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(obj));//[object Object]
console.log(Object.prototype.toString.call(fun));//[object Function]
console.log(Object.prototype.toString.call(s1)); //[object Symbol]

vue v-on绑定多个事件

<div v-on="{mousedown:onInput,mouseup:onFocus,click:onBlur}"></div>

防抖和节流

 function debounce(func, wait) {
  let timeout;
  return function () {
    const context = this;
    const args = [...arguments];
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(context, args)
    }, wait);
  }
}

function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }
    }
}

前端性能优化

WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。

如果采取 setTimeout 或 setInterval 来实现动画的话,回调函数将在帧中的某个时点运行,可能刚好在末尾,而这可能经常会使我们丢失帧,导致卡顿。

怎样理解 Vue 的单向数据流?

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
或者通过 .sync 去实现双向通信

// 子组件
props:{
  msg:String
}
...
computed:{
 msgData:{
  get(){
    return this.msg
  },
 set(val){
   this.$emit('update:msg',val)
  }
 }
}
//父组件
<children :msg.sync="data" />

父组件可以监听到子组件的生命周期吗?

可以

// Parent.vue
<Child @mounted="doSomething"/>
    
// Child.vue
mounted() {
  this.$emit("mounted");
}

组件中 data 为什么是一个函数?

因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。

Vue 组件间通信有哪几种方式?

props / $emit 适用 父子组件通信
ref 与 $parent / $children 适用 父子组件通信
EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信

Vue 是如何实现数据双向绑定的?

1.实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
2.实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
3.实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
4.实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。


image.png

虚拟 DOM 实现原理?

虚拟dom的比较,就是找出新节点(vnode)和旧节点(oldVnode)之间的差异,然后对差异进行打补丁(patch)
虚拟 DOM 的实现原理主要包括以下 3 部分:

Vue 中的 key 有什么作用?

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速。

你有对 Vue 项目进行哪些优化?

v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
长列表性能优化
事件的销毁
图片资源懒加载
路由懒加载
第三方插件的按需引入
优化无限列表性能
服务端渲染 SSR or 预渲染

Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap
构建结果输出分析
Vue 项目的编译优化

vue有哪些优势

为什么要用vuex而不直接定义全局变量

上一篇 下一篇

猜你喜欢

热点阅读