美团面试准备

1.自我介绍,你的优势?

用过什么技术栈,做过什么项目,自己对前端的一些想法

2.介绍一下 CSS 盒模型

  1. 盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border)
  1. 有两种, IE 盒子模型、标准 W3C 盒子模型;IE的content部分包含了 border 和 padding;
  1. 统一方法:
    box-sizing:content-box : 标准的W3C盒子模型
    box-sizing:border-box: 传统IE6的盒子模型 (IE6 IE7/IE8的怪异模式)
    box-sizing:padding-box: 目前只对火狐生效,也是减去适应..但是从padding开始
  1. CSS 选择器优先级怎么计算

无条件优先的属性只需要在属性后面使用!important。它会覆盖页面内任何位置定义的元素样式。ie6不支持该属性。

第一等级:代表内联样式,如style="",权值为 1000
第二等级:代表id选择器,如#content,权值为100
第三等级:代表类,伪类和属性选择器,如.content,权值为10
第四等级:代表标签选择器和伪元素选择器,如div p,权值为1

  1. position 的值,应用场景。

relative ,absolute,fixed,static

relative相对自身定位
absolute 相对static以外定位的第一个父元素
fixed相对浏览器窗口进行定位

应用场景:广告漂浮层,底部按钮,右上角的小数字图标

5.你对算法数据结构了解多少?链表和数组区别?

数组静态分配内存,链表动态分配内存;
数组在内存中连续,链表不连续;
数组元素在栈区,链表元素在堆区;
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。

6.二分查找

二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
(1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
(2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
(3)如果某一步数组为空,则表示找不到目标元素。

    // 递归算法
        function binary_search(arr,low, high, key) {
            if (low > high){
                return -1;
            }
            var mid = parseInt((high + low) / 2);
            if(arr[mid] == key){
                return mid;
            }else if (arr[mid] > key){
                high = mid - 1;
                return binary_search(arr, low, high, key);
            }else if (arr[mid] < key){
                low = mid + 1;
                return binary_search(arr, low, high, key);
            }
        };
        var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
        var result = binary_search(arr, 0, 13, 10);
        alert(result); // 9 返回目标元素的索引值  

7.描述了一个题,其实就是幂函数,说了递归的实现,问有没有什么注意的?说了溢出,然后提示没有溢出,又提示我没考虑负数。。然后纠正了,然后问了复杂度。然后做了优化。。

8.TCP 三次握手

美团面试准备_第1张图片
WechatIMG241.jpeg
美团面试准备_第2张图片
WechatIMG242.jpeg
美团面试准备_第3张图片
WechatIMG243.jpeg
WechatIMG244.jpeg

9.Http、Https 区别?

  1. 加密与不加密区别。
  2. 在HTTP(应用层) 和TCP(传输层)之间插入一个SSL协议, 就是HTTPS。
  3. Https方式访问,客户端到服务器端传输的数据是加密的,即使被截获也没法破解,安全性很高;http方式访问,账户密码是明文传输的,极易泄露

10.安全问题了解么?说一下 XSS? 怎么防护?

XSS: 通过客户端脚本语言(最常见如:JavaScript)
在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

CSRF:又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

通常来说CSRF是由XSS实现的,所以CSRF时常也被称为XSRF[用XSS的方式实现伪造请求](但实现的方式绝不止一种,还可以直接通过命令行模式(命令行敲命令来发起请求)直接伪造请求[只要通过合法验证即可])。
XSS更偏向于代码实现(即写一段拥有跨站请求功能的JavaScript脚本注入到一条帖子里,然后有用户访问了这个帖子,这就算是中了XSS攻击了),CSRF更偏向于一个攻击结果,只要发起了冒牌请求那么就算是CSRF了。

简单来说,条条大路(XSS路,命令行路)通罗马(CSRF马,XSRF马)。

防御手段:

  1. 在输出html时,加上Content Security Policy的Http Header
    (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)
    (缺陷:IE或低版本的浏览器可能不支持)
  2. 在设置Cookie时,加上HttpOnly参数
    (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6)
    (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全)
  3. 在开发API时,检验请求的Referer参数
    (作用:可以在一定程度上防止CSRF攻击)
    (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)

11.写一个函数每次调用输出会自增 1?

var getId = (function () {
  
    "use strict"; //严格模式

    var i = 0;
    return function () {
        return i++;
    };
    
})();

12.严格模式详解

  • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;

严格模式下,变量都必须先用var命令声明,然后再使用。

"use strict";
  v = 1; // 报错,v未声明
  for(i = 0; i < 2; i++) { // 报错,i未声明
  }

使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。

function f(){
    "use strict";
    this.a = 1;
  };
  f();// 报错,this未定义

禁止this关键字指向全局对象

function f(){
    return !this;
  } 
  // 返回false,因为"this"指向全局对象,"!this"就是false
  function f(){ 
    "use strict";
    return !this;
  } 
  // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

13.JavaScript 数据类型?哪些存储在堆里哪些在栈里?你刚才说到栈后进先出,哪种数据结构先进先出?

JavaScript 数据类型:字符串,数字,布尔,Null,Undefined,数组,对象

JavaScript的数据类型分为两大种:

  1. 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
  2. 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。

堆:队列优先,先进先出;
栈:先进后出;

14.说一下 JavaScript 作用域?(答了目的和几种类型,新增的块级作用域)

全局作用域,函数作用域,块作用域

15.Vue 双向数据绑定原理

  • vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的


    美团面试准备_第4张图片
    image

我们可以看到属性a有两个相对应的get和set方法,为什么会多出这两个方法呢?因为vue是通过Object.defineProperty()来实现数据劫持的。

Object.defineProperty( )是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,

  1. Vuex 状态机更新机制

Vuex 规定,属于应用层级的状态只能通过 Mutation 中的方法来修改,而派发 Mutation 中的事件只能通过 action。

从左到又,从组件出发,组件中调用 action,在 action 这一层级我们可以和后台数据交互,比如获取初始化的数据源,或者中间数据的过滤等。然后在 action 中去派发 Mutation。Mutation 去触发状态的改变,状态的改变,将触发视图的更新。

数据流都是单向的
组件能够调用 action
action 用来派发 Mutation
只有 mutation 可以改变状态
store 是响应式的,无论 state 什么时候更新,组件都将同步更新

17.事件流,事件代理,点击一个div 里面的一系列 li 弹出它的 innerHTML 怎么做? li 里面还有子元素,比如 span 怎么处理?

  • 使用闭包
  
  • 事件委托
  
  • 引入jquery,使用其中的on或delegate进行事件绑定
  
  
  
  • vue2的形式


import Vue from 'vue'
import html from './index.html'

window.onload = function(){
  new Vue({
    template: html,
    methods:{
      show(event){
        console.log(event.target.value);
      }
    }
  }).$mount('app')
}

18.对跨域了解么?你都知道什么方案?怎么实现?

jsonp ,服务端反向代理,jsonp可以跨域是因为src标签没有受同源策略限制

19.从哪些方面提高网站的渲染速度? 你刚才提到 GZip,具体怎么做?

1.内容方面
减少http请求
代码压缩
js代码写在之前
浏览器缓存(cookie/sessionStorage/localStorage)
将静态资源放置在子域名下,实现并行下载数目增加
缓存ajax结果
减少DOM节点数

2.服务器方面
cdn加速
gzip压缩

3.js
引用压缩过的库(.min)
减少操作DOM节点,必要时将节点缓存起来(离线更新);
少用递归或者用尾递归优化
减少全局变量
懒加载
预加载

4.css
精简css代码的编写,减少嵌套层次
使用sprite图
尽量采用简写
用link代替@import
动画要用在脱离文档流的元素上

5.图片处理
图片一般要压缩到小于200k(banner等)
可将资源放至子域名下
用iconfont代替小图标

20.数组去重的几种方法

//es6
function unique (arr) {
  return Array.from(new Set(arr))
}
思路:

1.创建一个新的数组存放结果

2.创建一个空对象

3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,
同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。

说明:至于如何对比,就是每次从原数组中取出一个元素,
然后到对象中去访问这个属性,如果能访问到值,则说明重复。

//es5
Array.prototype.unique3 = function(){
 var res = [];
 var json = {};
 for(var i = 0; i < this.length; i++){
  if(!json[this[i]]){
   res.push(this[i]);
   json[this[i]] = 1;
  }
 }
 return res;
}
var arr = [112,112,34,'你好',112,112,34,'你好','str','str1'];
alert(arr.unique3());

21.js判断一个变量的数据类型

typeof、instanceof 、constructor、prototype

22.vuex的原理

Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components ,界面随之刷新

23.vue双向绑定的原理

vue实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。

在MDN上对该方法的说明是:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

它接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。

属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的get和set就是属于存取描述符对象的属性。

然后我们可以通过在存取描述符中的get和set方法内写入自定义的逻辑来实现对象获取属性和设置属性时的行为。

var keyValue = 1;
var obj = {};
Object.defineProperty(obj,'key', {
    enumerable: true,
    configurable: true,
    get: function(){
        return keyValue;
    },
    set: function(newValue){
        keyValue = newValue;
        console.log(`keyValue的值已发生改变,目前的值是:${keyValue}`);
    }
});

obj.key; // 1

obj.key = 'obj对象的key属性已经绑定了变量keyValue的值';
// keyValue的值已发生改变,目前的值是:obj对象的key属性已经绑定了变量keyValue的值
// "obj对象的key属性已经绑定了变量keyValue的值"

keyValue; // "obj对象的key属性已经绑定了变量keyValue的值"

上面这个例子就是改变了对象获取属性及设置属性的默认行为。

对象obj获取属性key的值时,会触发上面的get方法,得到的是变量keyValue的值,然后当重新设置key的值时,触发set方法,会将变量keyValue的值改变为设置的值,如此就实现了一个简单的双向绑定:改变keyValue,obj.key得到的值也会改变,重新设置obj.key,keyValue一样会随之改变。

当然,vue的双向绑定实际更复杂,但最基本的原理就是基于Object.defineProperty()方法改变数据存取的默认行为来实现的。

24.浏览器的渲染机制

美团面试准备_第5张图片
image

浏览器的整个流程如上图所示。

1、 首先当用户输入一个URL的时候,浏览器就会发送一个请求,请求URL对应的资源。

2、 然后浏览器的HTML解析器会将这个文件解析,并且构建成一棵DOM树。

3、 在构建DOM树的时候,遇到JS和CSS元素,HTML解析器就换将控制权转让给JS解析器或者是CSS解析器。

4、 JS解析器或者是CSS解析器解析完这个元素时候,HTML又继续解析下个元素,直到整棵DOM树构建完成。

5、 DOM树构建完之后,浏览器把DOM树中的一些不可视元素去掉,然后与CSSOM合成一棵render树。

6、 接着浏览器根据这棵render树,计算出各个节点(元素)在屏幕的位置。这个过程叫做layout,输出的是一棵layout树。

7、 最后浏览器根据这棵layout树,将页面渲染到屏幕上去。

25.从地址栏输入url到页面都发生了什么

1.DNS域名解析

2.TCP连接

3.HTTP请求

4.处理请求返回HTTP响应

5.页面渲染

6.关闭连接

26.跨域的问题

1.什么是跨域?

  • 浏览器有同源策略,不允许ajax访问其他域接口
  • 跨域条件:协议,域名,单口,有一个不同就算跨域

2.怎么实现跨域

  • 服务端反向代理实现跨域,jsonp跨域

3.jsonp跨域的原理

  • 因为src不受同源策略影响

27.rem的问题

28.闭包的优缺点

(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

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

  • 箭头函数作为匿名函数,是不能作为构造函数的,不能使用new
var B = ()=>{
  value:1;
}

var b = new B(); //TypeError: B is not a constructor
  • 箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值
  • 箭头函数没有原型属性
var a = ()=>{
  return 1;
}

function b(){
  return 2;
}

console.log(a.prototype);//undefined
console.log(b.prototype);//object{...}

对于函数的this指向问题,我总结了下面两句话:

箭头函数的this永远指向其上下文的 this,任何方法都改变不了其指向,如call(), bind(), apply()
普通函数的this指向调用它的那个对象

30.三栏布局的5种写法


    
 
    

    

31.浅拷贝,深拷贝,用JSON.stringify的缺点

b = JSON.parse( JSON.stringify(a) )

缺点:
无法复制函数
原型链没了,对象就是object,所属的类没了。

使用JSON接口有弊端,使用Object.create不会复制对象本身, 而是用对象的constructor重新构造一个对象。
所以可以考虑使用Object.assign:

let old_obj = [{a:1},{b:2}];
let new_obj = old_obj.map((ele)=>{
    return Object.assign({},ele);
});
old_obj[0].a=99;
console.log(new_obj); // "[{a:1},{b:2}]" 

32.阶乘的实现方法

function factorial (num) { 
    if (num < 0) { 
        return -1; 
    } else if (num === 0 || num === 1) { 
        return 1; 
    } else { 
        return (num * factorial(num - 1)); 
    } 
};
factorial(6);

33.继承的几种实现

 
  1. vue的生命周期
!DOCTYPE html>


    
    



{{ message }}

34.js相关算法

1.二分查找

  // 递归算法
        function binary_search(arr,low, high, key) {
            if (low > high){
                return -1;
            }
            var mid = parseInt((high + low) / 2);
            if(arr[mid] == key){
                return mid;
            }else if (arr[mid] > key){
                high = mid - 1;
                return binary_search(arr, low, high, key);
            }else if (arr[mid] < key){
                low = mid + 1;
                return binary_search(arr, low, high, key);
            }
        };
        var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
        var result = binary_search(arr, 0, 13, 10);
        alert(result); // 9 返回目标元素的索引值  

2.数组对象排序

    function sortId(a,b){  
       return a.id-b.id  
    }
    result.sort(sortId);
    console.log(result); 

34.DOM元素的增删改查

  • Document.createElement() // 创建元素

  • Element.removeAttribute() // 从元素中删除指定的属性

  • Element.removeChild()// 删除子元素

  • Element.innerHTML // 设置或获取描述元素后代的HTML语句

  • Document.getElementById() // 返回对拥有指定 id 的第一个对象的引用
    Document.getElementsByTagName() // 返回带有指定标签名的对象集合
    Document.getElementsByName() // 返回带有指定名称的对象集合
    Document.getElementsByClassName() // 返回一个节点列表(数组),包含了所有拥有指定 class 的子元素
    attribute.getAttribute()

你可能感兴趣的:(美团面试准备)