【个人面试】

194 阅读10分钟

A公司(C轮 100-499 一面)

vue keep-alive内置组件
watch和computed区别及应用场景
隐藏DOM的几种方式 position:stick
原型怎么理解
JS基本数据类型,typeof可以有哪几种结果
null和undefined区别
app唤起链接怎么做
混合包的一些问题

B公司(已上市 10000人以上 一面)

笔试:

浏览器跨域
for...in和for...of区别
ie盒子和标准盒子模型及差别
一行代码实现数组去重

arr = Array.from(new Set(arr))
arr = [...new Set(arr)]
str = Array.from(new Set(str)).join('')//字符串去重
str = [...new Set(str)].join('')
冒泡排序

一面:

vue-router
导航守卫
route与$router
vuex使用
组件通信
  1. 父子组件
  2. 兄弟组件
  3. 跨级组件
深拷贝,浅拷贝

参考

  1. 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

    //数组使用concat或slice或[...arr],Array.from等
    a1 = [1, 2];
    a2 = a1.concat();//ES5
    a2 = [...a1];//ES6
    a3 = [[1,2], 2];
    a4 = [...a1];
    a4[0][0] = 2;
    console.log(a3)
    //对象使用Object.assign(target,...source)或{...obj}
  2. 深拷贝

    //方法1:转成对象JSON或者数组JSON,函数,undefined,symbol经过JSON.strify会丢失
    //方法2:使用第三方库,jquery的$.extend和lodash的_.cloneDeep
    obj = {
     o:{
        a:1,    b:2,   },
     a:1,
    }
    obj2 = JSON.parse(JSON.stringify(obj));
    obj2.o.a=2;
    console.log(obj2,obj)
Set和Map使用
  1. Set

ES6新数据结构。构造函数参数可接受数组或具有iterable接口的其他数据结构用来初始化。通过Array.from()Set结构转化为Array结构,这样数组的一些方法Set结构就可以间接使用。

set = new Set([1, 2, 3, 4, 4]);
typeof set //'object'
set instanceof Set//true
set//{1, 2, 3, 4}

操作方法:add,delete,has,clear方法。

遍历方法:keys,values,entries,foreach方法,Set数据结构支持for...of直接遍历(默认遍历器生成函数就是values),size属性。

使用Set实现交/并/差集。

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}

// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
  1. Map

ES6新数据结构,相对于传统对象的键名只能是字符串,Map的键名可以是各种类型(包括对象的,是一种更完善的hash结构实现。作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数。这就是说,SetMap都可以用来生成新的 Map。只有对同一个对象的引用,Map 结构才将其视为同一个键。常用方法和属性同Set,此外,还有set,get方法。Map 的遍历顺序就是插入顺序。Map的默认遍历器实现是使用entries方法。

m = new Map()
typeof m;//'object'
m instanceof Map;//true
m instanceof Object;//true
图片懒加载
微服务

总结:部门业务主要是PC端,考察多涉及

Vue全家桶ES6
,其他主要浏览器兼容JS执行原理基础CSS。可以看出来小姐姐考察点很全面,部门代码质量相对比较高~喜欢~

C公司(C轮 500-999 二面)

一面:

BFC盒子

参考

可以通过创建BFC盒子,解决margin折叠问题。

常见的创建条件为:

  • overflow:hidden;
  • float:left/right;
  • position:absolute;
  • display:inline-block;
  • display:flex;
手写实现bind函数

call,bind,apply都是JS内置的API,可以改变this指向。

三者区别:

//都只有一个参数时,该参数即为指定的this,类似于执行了this = obj;
obj = {
    a:1,
};
function f(){
    this.a = 2;
    console.log(obj.a)
};
f.call(obj);//直接执行
f.apply(obj);//直接执行
newF = f.bind(obj);//返回一个新函数
newF();

//多参数使用,第一个参数均为指定this,其余参数为函数参数,call和bind支持多参数,apply第二个参数为数组
let obj1 = {
    num: 1
};
let obj2 = {
    num: 2
}

function fn (x,y) {
    console.log(x+y+this.num);
}
fn.call(obj1,1,2); // 4
fn.apply(obj1,[1,2]); // 4

//bind支持函数柯里化:我们在调用_fn之前传入了一部分参数,调用时参入了剩余参数
//方式1
fn.bind(obj1,1,2)();
//方式2
fn.bind(obj1,1)(2);
//方式3
let _fn = fn.bind(obj1,1);_fn(2); // 4

PS:函数柯里化,一个函数传入部分参数,返回一个新函数处理剩余参数。

function f(x){
    return function(y){
        console.log(x+y);
    }
}
f(1)(2);//方式1
_f = f(1);//方式2
_f(2);

  • bind

特点:
1.改变this指向
2.返回一个新函数
3.支持函数柯里化
let obj1 = {
    num: 1
};
function fn (x,y) {
    console.log(x,y,x+y+this.num);
}
Function.prototype.myBind = function(context,...args){
    let fn = this;//构造函数原型上的函数this指向实例,即调用myBind的fn
    args = args?args:[];
    return function newFn(...newArgs){
        if(this instanceof newFn){
            return new fn(...args,...newArgs);//args为闭包
        }
        return fn.apply(context,[...args,...newArgs])
    }
}
fn.myBind(obj1,1,2)();
// fn.myBind(obj1,1)(2);
// _fn = fn.myBind(obj1,1,2);
// test = new _fn();

  • call

特点:
let obj1 = {
    num: 1
};
function fn (x,y) {
    console.log(x,y,x+y+this.num);
}
let obj1 = {
    num: 1
};
function fn (x,y) {
    console.log(x,y,x+y+this.num);
}
Function.prototype.myApply = function(context,...args){//!!!!区别在这里呀,也可以使用arguments类数组
    context = context || window;
    args = args?args:[];
    const key = Symbol();
    context[key] = this;//调用实例
    let result = context[key](...args);//通过对象调用方式改变this指向
    delete context[key]
    return result;
}
fn.myApply(obj1,[1,2]);

  • apply

特点:第二个参数为数组
let obj1 = {
    num: 1
};
function fn (x,y) {
    console.log(x,y,x+y+this.num);
}
let obj1 = {
    num: 1
};
function fn (x,y) {
    console.log(x,y,x+y+this.num);
}
Function.prototype.myApply = function(context,args){
    context = context || window;
    args = args?args:[];
    const key = Symbol();
    context[key] = this;//调用实例
    let result = context[key](...args);//通过对象调用方式改变this指向
    delete context[key]
    return result;
}
fn.myApply(obj1,[1,2]);

手写防抖、节流

针对持续触发的监听事件,如resize,scroll,touchmove,mousemove等做函数防抖(操作结束后一定时间执行一次)和节流(操作进行过程中固定时间执行多次)。无法控制DOM事件的触发次数,但可以控制DOM监听函数的执行频率。

  • 防抖

function debounce(fn,wait){
    console.log(1)
    let timeout;//形成了闭包
    return function(){
        let content = this;//this指向与debounce保持一致 存疑...
        let args = arguments;//args[0]为event,仍然可以获取event对象
        if(timeout) clearTimeout(timeout);
        timeout = setTimeout(()=>{
            fn.apply(content,args);
        },wait)
    }
};
function handle(){
    console.log(2)
}
//window.onscroll = debounce;只是挂载debounce函数并没有执行
window.onscroll = debounce(handle,1000);//考虑到需要传递行参挂载其他函数,使用return新的function地形式;则执行了debounce函数并挂载了匿名function

  • 节流

//使用时间戳
function throttle(fn,wait){
    console.log(1)
    let previous = 0;
    return function(){
        let content = this;//this指向与debounce保持一致 存疑...
        let args = arguments;//args[0]为event,仍然可以获取event对象
        let now = new Date();
        if(now - previous>wait){
           fn.apply(content,args)
            previous = now;
        }
    }
};
function handle(){
    console.log(2)
}
window.onscroll = throttle(handle,1000);

//使用定时器
function throttle(fn,wait){
    console.log(1)
    let timeout;
    return function(){
        let content = this;//this指向与debounce保持一致 存疑...
        let args = arguments;//args[0]为event,仍然可以获取event对象
//         if(timeout){ clearTimeout(timeout)}
        if(!timeout){
           timeout = setTimeout(()=>{
                timeout = null;
                fn.apply(content,args)
            },wait);    
        }
    }
};
function handle(){
    console.log(2)
}
window.onscroll = throttle(handle,1000);

this
原型

深浅拷贝
vue源码
双向绑定原理,监听订阅是怎么实现的,具体如何监听的
设计模式使用
闭包使用
box-sizing

width的宽度即为设置的两种值,content-boxborder-box

日常学习方式
完成最好的一次项目经历
职业规划

总结:主要围绕日常开发比较常用的轮子考察,JS基础CSS基础框架较少,以及个人特质的考察。

D公司 (未融资 一面)

笔试:

类型转换

目标类型只有boolean,string,number三种。

px,em,rem区别及如何适配

参考

参考

如何减少页面加载时间
使用this的三个场景
cookies,sessionStorage,localStorage的区别
  • cookies
  1. 大小4KB,比较小
  • sessionStorage
  • 随请求发送
  • 可设置过期时间等
  1. 大小5MB,较大
  2. 关闭页面或者浏览器
  • localStorage
  1. 大小5MB,较大
  2. 手动clear()
判断字符串中出现次数最多的字符及对应次数
ajax的优缺点及原理

总结:CSS基础JS基础AJAX等。

E公司(已上市 1000-9999 二面)

一面:

px,em,rem优缺点

个别机型表现存在差异。

DOM原生事件绑定的几种方法

参考

  • DOM0级(on+type)

只可注册绑定一个,后者会覆盖前者;只支持冒泡阶段。参考

  • DOM2级(addEventListener) 

同个DOM可注册多个监听器;第三个options选项可灵活控制各场景,对于touchmove,touchstart手动设置选项passivetrue可组织默认连带的滚动行为,使页面触摸更流畅;最好手动原样去除DOM事件removeEventListener。参考。IE9以下的IE浏览器不支持 addEventListener()和removeEventListener(),使用 attachEvent()与detachEvent() 代替,因为IE9以下是不支持事件捕获的,所以也没有第三个参数,第一个事件名称前要加on。

  • html(on事件)

阻止默认事件兼容

function preventDef(e){
	var g = e || window.event;
	if(g.preventDefault){
		g.preventDefault();
	}else if(g.returnValue){
		g.returnValue = false;
	}
	return false;
}

事件流和事件委托/代理

捕获阶段,目标阶段(目标元素身上不区分冒泡捕获,按绑定的前后顺序来执行。),冒泡阶段。

利用事件冒泡的机制,事件最终都会冒泡到祖先元素,只需要给祖先绑定事件就可以监听所有子元素的事件,而不用给每个DOM都绑定事件。同时可以在listener中进行区别处理。

  • 优点:
    • 可以大量节省内存占用,减少事件注册。
    • 可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适
  • 缺点:
    • 事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。
  • event.currentTarget,event.target

    参考

    event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素,只有被点击的那个目标元素的event.target才会等于event.currentTarget也就是说,event.currentTarget始终是监听事件者,而event.target是事件的真正发出者
    原型
    new的原理(this关系挂载,原型关系挂载)

    function Animal(type) {
        this.type = type;
    }
    Animal.prototype.say = function() {
        console.log('say')
    }
    
    function mockNew() {
        let Constructor = [].shift.call(arguments); // 取出构造函数
        
        let obj = {}   // new 执行会创建一个新对象
        
        obj.__proto__ = Constructor.prototype //原型关系挂载
        
        Constructor.apply(obj, arguments)//this关系挂载
        return obj
    }
    let animal = mockNew(Animal, 'dog')
        
    console.log(animal.type) // dog
    animal.say() // say作者:JOKER_链接:https://juejin.cn/post/6844903782803832845来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    原型链
    for in,Objects.keys(),for of区别
    • for in
    1. 对象/数组本身及其原型链上的可枚举属性
    2. 对于自定义数组可枚举属性也可以遍历
    3. 返回的结果是string类型的对象key和数组索引
    4. 某些情况下可能按随机顺序遍历数组,不推荐使用此方法遍历数组
    • Objects.keys()
    1. 对象自身及自定义的可枚举属性,不会遍历原型链及Symbol属性
    2. 返回的结果是对象key组成的数组
    3. 对数组的遍历与for in一致
    4. 此外,Object.entries()返回的是[key,value]二级数组。
    • for of
    1. 支持对数组,类数组对象(NodeList),字符串,Set,Map的遍历
    2. 对数组的遍历不支持自定义属性(类对象属性)和原型属性
    3. 不支持遍历普通对象

    参考

    深浅拷贝
    event loop
    promise.finally
    浏览器跨域

    参考

    同源策略:相同网络协议,域名,端口号;浏览器安全;

    非同源存在的问题:

    1. 数据:无法获取非同源网页的 cookie、localstorage 和 indexedDB。
    2. DOM:无法访问非同源网页的 DOM (iframe)。
    3. 请求:无法向非同源地址发送 AJAX 请求 或 fetch 请求(可以发送,但浏览器拒绝接受响应)。

    解决方式:

    1. 数据:
    • window.postMessage :一个 HTML5 的 api,允许两个窗口之间进行跨域发送消息。
    1. DOM:
    • document.domain:
    • window.name:
    1. 请求:
    • CORS:服务器端配置。相关响应头信息Access-Control-Allow-Origin
    • JSONP:前后端配合完成,使用简单且兼容性不错,但是只限于 get 请求。

    原理就是利用 <script> 标签的 src 属性没有跨域的限制,通过指向一个需要访问的地址,由服务端返回一个预先定义好的 Javascript 函数的调用,并且将服务器数据以该函数参数的形式传递过来

    //定义获取数据的回调方法
    function getData(data) {
      console.log(data);
    }
    
    // 创建一个script标签,并且告诉后端回调函数名叫 getData
    var body = document.getElementsByTagName('body')[0];
    var script = document.gerElement('script');
    script.type = 'text/javasctipt';
    script.src = 'demo.js?callback=getData';
    body.appendChild(script);
    
    //script 加载完毕之后从页面中删除,否则每次点击生成许多script标签
    script.onload = function () {
      document.body.removeChild(script);
    }
    协商缓存与强制缓存

    总结:考察JS原理熟练掌握及灵活应用浏览器相关

    个人项目介绍

    vue
    angular
    微信小程序
    node