你不知道的大厂面试题附赠答案😯

718 阅读3分钟

大厂笔试+面试

大厂面试考查知识点

  • 安全方面
    • XSS: 跨站脚本攻击(通过input框或者地址栏注入js脚本)
    • CSRF:跨站请求伪造(通过浏览器请求自动携带cookie)
    • SQL注入:
  • 路由相关
    • 路由模式(hash,browser)
    • 路由传参(url,state, path+query, name+params)
    • 路由监听(beforeEach, afterEach, subscribe)
    • 路由原理(hashChange + popState)
  • webpack
    • entry
    • output
    • modules
    • devServer
    • plugins
    • NODE_ENV = development
  • v-model
    • v-bind:value + v-on:onChange
  • redux数据流
    • store->组件: provider+connect
    • 组件->action: dispatch
    • action->store: 纯函数
  • es6
    • promise
    • async/await
    • 装饰器@
    • class
    • 解构+reset操作符
  • git flow
    • 每人一个分支,开发完毕合并分支:直接合并或者PR
    • 修复bug,从主分支临时开一个分支,修复完删除
    • master主分支,develop开发测试分支

大厂笔试题经典案例

1. ES6

1.1关于Class

::: tip Question: 产品线十分丰富,拥有ECS、RDS等数百款产品,每个产品都具有一些通用属性,例如:ID(id),地域(region),名称(name),同时每个产品又包含自己特有的属性。 ECS拥有实例(instance)属性,可选值有ecs.t1.small、ecs.t3.small、ecs.t1.large RDS拥有数据库类型(dbType)属性,可选值有mysql、mssql、PPAS 请使用你的面向对象知识,基于ES6语法编写ECS、RDS两个类,并实现如下方法: 1. config() 返回一个字面量对象,可以拿到所有的成员变量。 2. buy() 返回一个URL,格式www.aliyun.com/buy?id=xxx&… :::

class Base{
	constructor(options){
		this.id = options.id || '';
		this.region = options.region || '';
		this.name = options.name || '';
	}
	config(){
		return {
			id: this.id,
			name: this.name,
			region: this.region
		}
	}
	buy(){
		return `https://www.aliyun.com/buy?id=${this.id}&region=${this.region}&name=${this.name}`
	}
}

class ECS extends Base{
	constructor(options){
		super(options);
		if (['ecs.t1.small', 'ecs.t3.small', 'ecs.t1.large'].indexOf(options.instance) != -1){
			this.instance = options.instance	
		}else{
			this.instance = '';
		}
	}
	config(){
		return Object.assign({}, super.config(), {instance: this.instance});
	}
	buy(){
		return `${super.buy()}&instance=${this.instance}`
	}
}

class RDS extends Base{
	constructor(options){
		super(options);
		if (['mysql', 'mssql', 'PPAS'].indexOf(options.dbType) != -1){
			this.dbType = options.dbType	
		}else{
			this.dbType = '';
		}
	}
	config(){
		return Object.assign({}, super.config(), {dbType: this.dbType});
	}
	buy(){
		return `${super.buy()}&dbType=${this.dbType}`
	}
}

let ecs = new ECS({name:'ecs',id:1,region:'华北',instance:'ecs.t3.small'})
ecs.config();
ecs.buy();

let rds = new ECS({name:'rds',id:2,region:'华东',dbType:'PPAS'})
rds.config();
rds.buy();
#### 1.2 关于promise
:::tip Question:
实现图片的依次加载和并行加载
:::
```js
// 封装加载图片的promise
let loadImg = (src)=>{
    return new Promise((resolve, reject)=>{
        let img = new Image();
        img.onload = ()=>{
            resolve(img);
        }
        img.onerror = ()=>{
            reject(new Error());
        }
    })
}
const imgs = ['url1', 'url2', 'url3'];
// 依次加载图片
async function fSync(){
    for (let i=0,len=imgs.length; i<len; i++){
        let img = await loadImg(imgs[i]);
        document.body.appendChild(img);
    }
}
// 并行加载图片
function fAsync(){
    imgs.forEach(async item=>{
        let img = await loadImg(imgs[i]);
        document.body.appendChild(img);
    })
}

2.DOM树在内存中的表示及JSX的遍历

::: tip Question: 请用递归的方式遍历树形数据结构中的每一个节点 :::

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake'
          }
        ]
      }
    ]
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men'
          }
        ]
      }
    ]
  }
];
// 深度优先遍历
function eachOpt(option){
	option.forEach(element => {
		console.log('element value....',element.value)
		if(Array.isArray(element.children) && element.children.length){
        	eachOpt(element.children)
      	}
   	});
}
eachOpt(options)

3. 字符串的基础操作

:::tip Question: 在开发中,我们经常会碰到将abc-xyz这类格式的字符串转为AbcXyz形式的驼峰字符串进行处理, 例如:hello-world我们希望能够变成驼峰风格的HelloWorld,请编写代码实现这个camelize(str)方法 :::

function camelize(str) {
    //补充代码
  var strArr = str.split('-');
  return strArr.map(item=>{
  	let upperCase = item[0].toUpperCase();
  	return upperCase+item.slice(1)
  }).join('');
}
camelize('hello-world');

4.函数的节流与原生事件

:::tip Question: 请用js实现一个监听浏览器窗口变化的函数,当浏览器窗口的宽度大于等于 600px 的时候console.log('hello')(持续大于等于600px的话打印一次即可),请用你觉得最优的实现 :::

var throttle = function(func, ms){
    var start = +new Date();
    
    return function(){
        var now = +new Date();
        if (now- start > ms){
            setTimeout(function(){
                func();
            }, ms);
            start = now;
        }

    }
}

var flag = false;
var resizeFunc = throttle(function(){
    if (!flag && window.innerWidth >= 600){
        console.log('hello');
        flag = true;
    }else if(window.innerWidth < 600){
        flag = false;
    }
}, 300);

window.addEventListener('resize', resizeFunc);

5.关于排序

5.1 二分排序

:::tip Question 写一个有效的算法完成矩阵搜索,这个矩阵有如下特点: 1) 矩阵中的每行数字都是经过排序的,从左到右依次变大。 2) 每行的第一个数字都比上一行的最后一个数字大 例如: [ [2, 4, 8, 9], [10, 13, 15, 21], [23, 31, 33, 51] ] 实现一个函数,搜索这个数组 输入:4,返回:true 输入:3,返回:false :::

const arr =  [
    [2,   4,  8,  9],
    [10, 13, 15, 21],
    [23, 31, 33, 51]
];



// 一维数组二分法查找
function searchArray(arr, num){
    console.log('arr...', arr, num);
    let len = arr.length;
    if (arr[0] > num || arr[len-1] < num){
        return false;
    }else {
        let mid = Math.floor(arr.length/2);
        if (arr[mid] > num){
            return searchArray(arr.slice(0, mid), num);
        }else if(arr[mid] < num){
            return searchArray(arr.slice(mid+1, len), num);
        }else{
            return true;
        }
    }
}

// 二维数组二分查找
function search(arr, num){
    console.log('arr..', arr);
    let len = arr.length,
        arrLen = arr[0].length;
    let middle = Math.floor(arr.length/2);
    if (arr[0][0] > num || arr[len-1][arrLen-1] < num){
        return false;
    }else{
        if (arr[middle][0] > num ){
            // 当最小值大于num,在前面查找
            return search(arr.slice(0, middle), num);
        }else if(arr[middle][arrLen-1] < num){
            // 当最大值小于num,在后面查找
            return search(arr.slice(middle+1, len), num);
        }else{
            // 在这中间,调用一维数组查找方法
            return searchArray(arr[middle], num);
        }
    }
}
let result = search(arr, 52);
console.log('查询结果...', result);

5.2 快速排序

let arr1 = [1,23,7,5,3,2,8,2,19,99,10,12,17,78,87];
function quickStart(arr){
    let mid = Math.floor(arr.length/2);
    let left = [],
        right = [];
    // 递归终止条件
    if (arr.length <= 1){
        return arr;
    }
    arr.forEach(item=>{
        if (item > arr[mid]){
            right.push(item);
        }else if(item < arr[mid]){
            left.push(item);
        }
    })
    return quickStart(left).concat([arr[mid]], quickStart(right));
}
console.log('排序前', arr1, '排序后:', quickStart(arr1));

5.3 冒泡排序

let arr1 = [1,23,7,5,3,2,8,2,19,99,10,12,17,78,87];
function bubble(arr){
    for (let i=0, len=arr.length; i<len; i++){
        for (let j=i+1, len=arr.length; j<len; j++){
            let tmp = 0;
            if (arr[i] > arr[j]){
                tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }
        }
    }
    return arr;
}
console.log('排序前', arr1, '排序后:', bubble(arr1));