前端常见面试题

基础相关

1 前端需要注意哪些seo

  • 合理的titledescriptionkeywords:搜索对着三项的权重逐个减小,title值强调重点即可,重要关键词出现不要超过2次,而且要靠前,不同页面title要有所不同;description把页面内容高度概括,长度合适,不可过分堆砌关键词,不同页面description有所不同;keywords列举出重要关键词即可
  • 语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
  • 重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
  • 重要内容不要用js输出:爬虫不会执行js获取内容
  • 少用iframe:搜索引擎不会抓取iframe中的内容
  • 非装饰性图片必须加alt
  • 提高网站速度:网站速度是搜索引擎排序的一个重要指标

2 从浏览器输入栏输入url到显示的过程

  • 浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
  • 服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);
  • 浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTMLDOM);
  • 载入解析到的资源文件,渲染页面,完成。

3 dom的重绘和回流

DOM的回流:当页面中元素的位置,大小或结构、定位发生改变,
会引发浏览器对当前页面的结构进行重新的计算;非常耗性能的;

DOM的重绘: 当元素的背景、透明度、颜色发生变化,
那么浏览器会对元素进行重新描绘;这个过程就是浏览器的重绘;

4 cookies,sessionStorage 和 localStorage 的区别

  • cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)
  • cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递
  • sessionStoragelocalStorage不会自动把数据发给服务器,仅在本地保存
  • 存储大小:
    • cookie数据大小不能超过4k
    • sessionStoragelocalStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
  • 有期时间:
    • localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
    • sessionStorage 数据在当前浏览器窗口关闭后自动删除
    • cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

5 iframe有那些缺点

1.会产生很多页面,不容易管理
2.iframe框架结构有时会让人感到迷惑,如果框架个数多的话,可能会出现上下、左右滚动条,会分散访问者的注意力,用户体验度差
3.代码复杂,无法被一些搜索引擎索引到,这一点很关键,现在的搜索引擎爬虫还不能很好的处理iframe中的内容,所以使用iframe会不利于搜索引擎优化
4.很多的移动设备(PDA手机)无法完全显示框架,设备兼容性差。
5.iframe框架页面会增加服务器的http请求,对于大型网站是不可取的。
分析了这么多,现在基本上都是用Ajax来代替iframe,所以iframe已经渐渐的退出了前端开发

6 网页性能优化有哪些?如何提高网页的性能(此题很重要,大家注意,面试前要背诵常用的方法)

  • content方面
    • 减少HTTP请求:合并文件、CSS精灵、inline Image
    • 减少DNS查询:DNS缓存、将资源分布到恰当数量的主机名
    • 减少DOM元素数量
  • Server方面
    • 使用CDN
    • 配置ETag
    • 对组件使用Gzip压缩
  • Cookie方面
    • 减小cookie大小
  • css方面
    • 将样式表放到页面顶部
    • 不使用CSS表达式
    • 使用<link>不使用@import
  • Javascript方面
    • 将脚本放到页面底部
    • javascriptcss从外部引入
    • 压缩javascriptcss
    • 删除不需要的脚本
    • 减少DOM访问
  • 图片方面
    • 优化图片:根据实际颜色需要选择色深、压缩
    • 优化css精灵
    • 不要在HTML中拉伸图片

7 link 和 @import的区别

1、从属关系区别

@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。

2、加载顺序区别

加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。

3、兼容性区别

@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。

4、DOM可控性区别

可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式

8 对BFC规范的理解?

  1. 规范解释:块格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

  2. BFC 的特性:BFC 是一个独立的容器,容器内子元素不会影响容器外的元素

  3. BFC 的作用:包含浮动元素(清除浮动)

9 谈谈对于闭包的理解?使用场景(不要简单回答函数嵌套函数)

闭包的简单理解:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

为什么用闭包:
全局变量:优点是随处可用,可重用,但容易被污染
局部变量:优点是仅在函数内用,不容易被污染,但不能被重用

何时使用: 只要即重用一个变量,又保护变量不被污染时。

闭包的缺点:

比普通函数占用更多的内存。

解决:闭包不在使用时,要及时释放,将不使用的局部变量全部删除。。

将引用内层函数对象的变量赋值为null。

闭包的使用场景:

1.setTimeout

原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。

function f1(a) {
    function f2() {
        console.log(a);
    }
    return f2;
}
var fun = f1(1);
setTimeout(fun,1000);//一秒之后打印出1

2.回调

定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
</head>
<body>
    <a href="#" id="size-12">12</a>
    <a href="#" id="size-20">20</a>
    <a href="#" id="size-30">30</a>

    <script type="text/javascript">
        function changeSize(size){
            return function(){
                document.body.style.fontSize = size + 'px';
            };
        }

        var size12 = changeSize(12);
        var size14 = changeSize(20);
        var size16 = changeSize(30);

        document.getElementById('size-12').onclick = size12;
        document.getElementById('size-20').onclick = size14;
        document.getElementById('size-30').onclick = size16;

    </script>
</body>
</html>

当点击数字时,字体也会变成相应的大小。

3.函数防抖

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。

/*
* fn [function] 需要防抖的函数
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null    //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
        }
    }
}

4.封装私有变量

如下面代码:用js创建一个计数器

function f1() {
    var sum = 0;
    var obj = {
       inc:function () {
           sum++;
           return sum;
       }
};
    return obj;
}
let result = f1();
console.log(result.inc());//1
console.log(result.inc());//2
console.log(result.inc());//3

10 谈谈你对 js 作用域链的理解(变量作用域)

  • 作用域链:作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的
  • 作用域:就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期

11 js原型、原型链

在这里插入图片描述

  • 每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时

  • 如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念

  • 关系:instance.constructor.prototype = instance.__proto__

  • 特点:

    • JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变
  • 当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的

  • 就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象

12 谈谈你对于this的理解(此题不要忘了箭头函数,以及this指向出现问题的解决方案 预保留this)

在这里插入图片描述

1.普通函数指向 window

2.事件函数 指向事件源

3.定时器 中也是window

4.this在对象的方法中,指向 调用这个方法的对象

call bind apply 改变this指向
  1. call

    fn.call(2,3,4,5,6);			 
    
       a,没有参数fn.call()  就相当于函数调用
       b,有参数       第一个参数,就是这个函数调用时的this指向,从第二个参数开始,会当做实参传
    
  2. apply

      fn.apply(2,[3,4,5,6]);
    
       a,没有参数:fn.apply() 相当于函数调用
    
       b,第一个参数是函数调用时的this指向,只有两个参数,第二个参数,必须是数组,会将数组解析出来,数组的每个元素都会当成一个实参传入
    
  3. bind

     var fn2 = fn.bind(2);
    
    	a,bind调用,返回一个函数副本,这个函数副本中的this指向,指向了bind调用时穿的参数
    

13 new一个函数 做了什么

1.在构造函数内部隐示的创建了一个空对象
2.构造函数内部的this指向这个空对象
3.构造函数隐示的返回这个空对象

14 js运行机制(js如何运行)(js运行之前先找var声明的变量以及function声明函数块),这题考的是变量声明提前,以及function函数块提前

1、提升(这里有变量提升和函数提升);

变量和函数声明从它们的代码中出现的位置被“移动”到了最上面。这个过程就叫提升。

只有声明本身会被提升,而赋值或其他运行逻辑会留在原地

2、js的单线程特性

js是个单线程的语言,所以如果说遇到setTimeout、setInterval、ajax请求等需要停顿的语句,就停下来等这个停顿时间过去的话,语言的运行就阻塞在这里了。所以说,js就想了个办法,那就是我遇到setTimeout这样停顿类的语句,不管你停顿多久吧(可能是停顿0),都一律跳过去,等那些不需要停顿的语句执行完了,再回过头来执行需要等待的语句。

3、setTimeout函数的执行机制

setTimeout:在指定时间内, 将任务放入事件队列,等待js引擎空闲后被执行.

15 ajax工作原理

1.Ajax简介

Ajax(Asyncchronous JavaScript and Xml),翻译过来就是说:异步的javaScript和xml, Ajax不是新的编程语言,而是一种使用现有标准的新方法。

Ajax的优点:在不重新加载整个页面的情况下,可以与服务器交换数据,并更新部分网页的艺术。
2. Ajax的工作原理

Ajax的工作原理相当于在用户和服务器之间加了一个中间层(Ajax引擎),使用户操作与服务器响应异步化。并不是所有用户请求都提交服务器。像一些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。

3. Ajax实现步骤
 1. 创建XMLHttpRequest
   2. 设置请求方式
   3. 调用回调函数
   4. 发送请求

16 js模块化 amd cmd

1. CommonJS

CommonJS主要用在Node开发上,每个文件就是一个模块,没个文件都有自己的一个作用域。通过module.exports暴露public成员。例如:

// 文件名:x.js
let x = 1;
function add() {
  x += 1;
  return x;
}
module.exports.x = x;
module.exports.add = add;

此外,CommonJS通过require()引入模块依赖,require函数可以引入Node的内置模块、自定义模块和npm等第三方模块。

// 文件名:main.js
let xm = require('./x.js');
console.log(xm.x);  // 1
console.log(xm.add());  // 2
console.log(xm.x);   // 1
2. AMD和CMD
2.1 AMD 推崇依赖前置
// 定义AMD规范的模块
define([function() {
  return 模块
})

区别于CommonJS,AMD规范的被依赖模块是异步加载的,而定义的模块是被当作回调函数来执行的,依赖于require.js模块管理工具库。当然,AMD规范不是采用匿名函数自调用的方式来封装,我们依然可以利用闭包的原理来实现模块的私有成员和公有成员:

define(['module1', 'module2'], function(m1, m2) {
  let x = 1;
  function add() {
    x += 1;
    return x;
  }
  return { add };
})
2.2 CMD 推崇依赖就近

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。AMD 推崇依赖前置,CMD 推崇依赖就近。

define(function(require, exports, module) {
  //  同步加载模块
  var a = require('./a');
  a.doSomething();
  // 异步加载一个模块,在加载完成时,执行回调
  require.async(['./b'], function(b) {
    b.doSomething();
  });
  // 对外暴露成员
  exports.doSomething = function() {};
});
// 使用模块
seajs.use('path');

17 什么是同源限制(跨域相关)

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

1.什么是同源

域名、协议、端口相同,也就是在同一个域里。

2.非同源受到的限制
    cookie不能读取 (如我在这一个站点无法读另一个站点的cookie)
    dom无法获得
    ajax请求不能发送
3.什么是浏览器跨域

例如:

    一个域的页面去请求另一个域的资源;
    A域的页面去请求B域的资源。

18 如何解决跨域问题(cors 反向代理 jsonp等)

1.cors

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

优点是:正统,符合标准,
缺点是:需要服务器端配合,比较麻烦。
2.jsonp

AJAX 无法跨域是受到“同源政策”的限制,但是带有src属性的标签(例如

3 反向代理方式

反向代理和正向代理的区别:

正向代理(Forward Proxy),通常都被简称为代理,就是在用户无法正常访问外部资源,比方说受到GFW的影响无法访问twitter的时候,我们可以通过代理的方式,让用户绕过防火墙,从而连接到目标网络或者服务。

反向代理(Reverse Proxy)是指以代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 请求连接的客户端,此时,代理服务器对外就表现为一个服务器。

如何使用反向代理服务器来达到跨域问题解决:
前端ajax请求的是本地反向代理服务器

本地反向代理服务器接收到后:
    修改请求的 http-header 信息,例如 referer,host,端口等
    修改后将请求发送到实际的服务器
实际的服务器会以为是同源(参考同源策略)的请求而作出处理

19 同步和异步的区别

同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。

同步,就是实时处理(如打电话),比如服务器一接收客户端请求,马上响应,这样客户端可以在最短的时间内得到结果,但是如果多个客户端,或者一个客户端发出的请求很频繁,服务器无法同步处理,就会造成涌塞。

同步如打电话,通信双方不能断(我们是同时进行,同步),你一句我一句,这样的好处是,对方想表达的信息我马上能收到,但是,我在打着电话,我无法做别的事情。

异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

异步,就是分时处理(如收发短信),服务器接收到客户端请求后并不是立即处理,而是等待服务器比较空闲的时候加以处理,可以避免涌塞。

20 如何解决js异步回调地狱(promise、async、await、generator等)

1.什么是回调地狱

在异步编程中,许多操作都会放在回调函数(callback)中,每增加一个异步请求,就会多添加一层回调函数的嵌套,多个异步操作就形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改,过多的回调也就会导致陷入“回调地狱”。

2.promise

Promise 对象存在以下三种状态:

Pending(进行中)

Fulfilled(已成功)

Rejected(已失败)

promise,它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。

Promise对象是一个构造函数,接受一个带了resolve和reject参数的函数;

在状态由pending变为fulfilled时,从resolve中将value传出;

在状态由pending变为rejected时,将error抛出

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数

Promise 提供then方法加载回调函数,catch方法捕捉执行过程中抛出的错误。

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。

3.Generator 函数
1.function关键字与函数名之间有一个星号;2.函数体内部使用yield表达式,定义不同的内部状态

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
  var hw = helloWorldGenerator();
  
2.调用遍历器对象的next方法,使得指针移向下一个状态

hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

  3.for...of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法。
  
function* foo() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  return 6;
}

for (let v of foo()) {
  console.log(v);
}
4.async/await

async 函数其实就是 Generator 函数的语法糖

await后一般是一个Promise对象。

async函数返回一个 Promise对象时,就可以使用then方法添加回调函数。

当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

21 es6新增了哪些属性(常用的整理回答)

因为字数太多详细见这篇文章

https://blog.csdn.net/weixin_43307658/article/details/86698281

22 简述http协议

因为字数太多详细见这篇文章

https://blog.csdn.net/qq_28602957/article/details/52852140?utm_source=distribute.pc_relevant.none-task

23 移动端 布局方案有哪些实现方式

一、固定布局

固定布局是第一次做移动端时最好的选择方式,思路沿用PC端,上手比较快。在标签里把 viewport 加好,然后设想整个网页的宽度为 320px 即可。 其他地方根据 PC 端来布局。 缺点:大屏手机显示网页比较宽,固定布局宽度参照永远是 320px,导致左右两 边会有空白。

二、流动布局

流动布局与固定宽度布局基本不同点就在于对网站尺寸的测量单位不同,流动布局就是使用百分比来代替px作为单位。 优点是流动布局可以很好解决自适应需求。缺点是不够灵活,添加元素时,需要更改其他元素的值。

三、bootstrap布局

bootstrap是一个比较流行的响应式前端框架,利用bootstrap的栅格系统可以实现响应式的移动端布局。栅格系统:Bootstrap中定义了一套响应式的网格系统,其使用方式就是将一个容器划分成12列,然后通过col-xx-xx的类名控制每一列的占比, 在使用的时候,我们给相应的div设置col-lg-2 col-md-3 col-sm-4 col-xs-6,以此完成布局。

四、媒体查询+REM布局

使用媒体查询可以根据不同的设备宽度加载不同的css样式。rem是一个相对单位,会根据根节点的字体大小来计算的,使用媒体查询和rem可以实现移动端的响应式。

五、flex布局

Flexbox是CSS3引入的新的布局模式,也称为弹性布局,他会根据页面的剩余宽度自动分配空间。 它决定了元素如何在页面上排列,使它们能在不同的屏幕尺寸和设备下可预测地展现出来。它能够扩展和收缩 flex 容器内的元素, 以最大限度地填充可用空间。Flexbox布局最适合应用程序的组件和小规模的布局,而网格布局更适合那些更大规模的布局。

24 请简述rem布局原理

1、em

em作为font-size的单位时,其代表父元素的字体大小,em作为其他属性单位时,代表自身字体大小——MDN

比如父元素font-size:12px;

自身元素如果写成:font-sise:2em;则自身元素用px表示就是24px(相对父元素字体大小);

但是自身元素设置:width:2rem,那么自身元素用px表示就是48px(相对自身字体大小);

2.2、rem

rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其出初始字体大小——MDN

比如根元素(html)设置font-size=12px; 非根元素设置width:2rem;则换成px表示就是24px;

如果根元素设置成font-size=1rem;则根元素换成px就是相对于初始字体大小,一般是12px;

2.3、vm/vh

vw : 视口宽度的 1/100;vh :视口高度的 1/100 —— MDN

在pc端,视口宽高就是浏览器得宽高;

25 flex弹性布局有哪些属性

flex容器属性详解:

flex-direction:row/column;(横排/竖排) 决定元素的排列方向;
flex-wrap:nowrap/wrap/wrap-reverse(翻转);排列不下时如何排,默认排不下就压缩进行排
flex-flow是: flex-direction 和 flex-wrap的简写;(例如:flex-flow:row nowrap;)
justify-content:center; 元素在主轴上的对齐方式(center元素居中对齐);
align-items 元素在交叉轴的对齐方式;

flex元素属性详解:
flex-grow 当有多余空间时,元素的放大比例;
flex-shirink当空间不足时,元素的缩小比例;
flex-basis 元素在主轴上占据的空间;
flex时grow / shrink / basis的简写;
order 定义元素的排列顺序;
align-self 定义元素自身的对齐方式;

26 call apply 和bind的区别

call 和 apply 的共同点

它们的共同点是,都能够改变函数执行时的上下文,将一个对象的方法交给另一个对象来执行,并且是立即执行的。

为何要改变执行上下文?举一个生活中的小例子:平时没时间做饭的我,周末想炖个腌笃鲜尝尝。但是没有适合的锅,而我又不想出去买。所以就问邻居借了一个锅来用,这样既达到了目的,又节省了开支,一举两得。

改变执行上下文也是一样的,A 对象有一个方法,而 B 对象因为某种原因,也需要用到同样的方法,那么这时候我们是单独为 B 对象扩展一个方法呢,还是借用一下 A 对象的方法呢?当然是借用 A 对象的啦,既完成了需求,又减少了内存的占用。

另外,它们的写法也很类似,调用 call 和 apply 的对象,必须是一个函数 Function。接下来,就会说到具体的写法,那也是它们区别的主要体现。

call 和 apply 的区别

它们的区别,主要体现在参数的写法上

call 的写法

Function.call(obj,[param1[,param2[,…[,paramN]]]])

需要注意以下几点:

调用 call 的对象,必须是个函数 Function。
call 的第一个参数,是一个对象。 Function 的调用者,将会指向这个对象。如果不传,则默认为全局对象 window。

第二个参数开始,可以接收任意个参数。每个参数会映射到相应位置的 Function 的参数上。但是如果将所有的参数作为数组传入,它们会作为一个整体映射到 Function 对应的第一个参数上,之后参数都为空。

apply 的写法

Function.apply(obj[,argArray])

需要注意的是:

它的调用者必须是函数 Function,并且只接收两个参数,第一个参数的规则与 call 一致。

第二个参数,必须是数组或者类数组,它们会被转换成类数组,传入 Function 中,并且会被映射到 Function 对应的参数上。这也是 call 和 apply 之间,很重要的一个区别。

bind 的使用

最后来说说 bind。在 MDN 上的解释是:bind() 方法创建一个新的函数,在调用时设置 this 关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

它的语法如下:

Function.bind(thisArg[, arg1[, arg2[, …]]])

bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。

如果 bind 的第一个参数是 null 或者 undefined,this 就指向全局对象 window。
总结

call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上的写法略有区别。

bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,并且需要稍后再调用一下,才会执行。

27 函数的防抖和节流

一、防抖函数

1.1 概念:

触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。

1.2 使用场景:

就像是我的搜索栏功能,是在里面内容变化后就实时触发搜索事件,但是有时候我们输
的内容很长,在没有输完的时候就触发了事件,这样对性能来说是不好的,造成了很多
无用的请求,这时候就需要用到防抖函数,来让其在搜索内容变化后的200毫秒内如果
没有再更改才发起请求。

1.3 实现防抖函数的思路:

在高频触发事件的时候,取消原来的延时事件。

二、节流函数

2.1 概念:

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率;

2.2 使用场景:

就像我接了一个任务,只能在5秒完成任务给回复,在执行后的这5秒内,你再怎么给
我布置任务我都不管直接当没听到,直到到5秒后执行完这个任务,你才可以再次给
我布置任务,以此类推。。。

2.3 实现思路:

每次触发事件时都判断当前是否有等待执行的延时函数,如果有直接截断事件不用往下执行了;

三、个人理解两者的区别

防抖函数和节流函数的一个区别就是防抖是按照最后一次触发为下一次事件执行的时间计算点,
前面的没满足间隔时间的都从最后这一次开始来决定什么时候执行延时事件;
而节流函数是按照第一次触发事件作为时间计算点,后面没到间隔时间的事件都忽略;

28 移动端1px问题如何解决?

原因

由于不同的手机有不同的像素密度导致的。如果移动显示屏的分辨率始终是普通屏幕的2倍,1px的边框在devicePixelRatio=2的移动显示屏下会显示成2px,所以在高清瓶下看着1px总是感觉变胖了

解决方法

1.在ios8+中当devicePixelRatio=2的时候使用0.5px

2.伪类 + transform 实现

原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

优点:所有场景都能满足,支持圆角(伪类和本体类都需要加border-radius)

缺点:对于已经使用伪类的元素(例如clearfix),可能需要多层嵌套

3.viewport + rem 实现

这种兼容方案相对比较完美,适合新的项目,老的项目修改成本过大。

在devicePixelRatio = 2 时,输出viewport:

在devicePixelRatio = 3 时,输出viewport:

优点:所有场景都能满足,一套代码,可以兼容基本所有布局

缺点:老项目修改代价过大,只适用于新项目

4.使用box-shadow模拟边框

利用css 对阴影处理的方式实现0.5px的效果

样式设置:

.box-shadow-1px {

box-shadow: inset 0px -1px 1px -1px #c8c7cc;

}

优点:代码量少,可以满足所有场景

缺点:边框有阴影,颜色变浅

29 对象 深拷贝和浅拷贝

浅拷贝 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

深拷贝 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

区别:浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的数据都会拷贝出来;

30 长链接 双向通信 websocket(什么时候用,怎么用)

详细见这篇文章
http://www.cocoachina.com/articles/896577?filter=mac

vue常见面试题

vue常见面试题点击
https://juejin.im/post/5d59f2a451882549be53b170

2 vue面试题中如果是后台管理 可能会问到vue中如何实现权限管理,大家去搜索。之前让你们看手摸手撸后台管理中有提到,还有,大家也注意看一下 vue-element-admin

3 vuex是什么,简述,同时,vuex如何实现长久存储

react常见面试题

http://note.youdao.com/noteshare?id=d4316ae35ab0e5f8c082218adf4d9047&sub=DE835BC97EEE49C1BA430377A2A366C9

小程序常见面试题

https://www.jianshu.com/p/c604914d325d

其他常问的问题?

1开发过程中遇到的最大的问题是什么?怎么解决的

2有没有用过第三方的插件或者库

(用过,如环信 做IM库) (IM是即时通信的意思,自己百度,如实时聊天,语音视频等)】

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值