判断数组的形式有哪些

  • 通过Object.prototype.toString.call()做判断
Object.prototype.toString.call(obj).slice(8,-1) === 'Array';
  • 通过原型链做判断
obj.__proto__ === Array.prototype;
  • 通过ES6的Array.isArray()做判断
Array.isArrray(obj);
  • 通过instanceof做判断
obj instanceof Array
  • 通过Array.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(obj)

Vue的父子组件生命周期钩子函数执行程序?

<!-- 加载渲染过程 -->    <!-- 父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created ->    子beforeMount -> 子mounted -> 父mounted -->    <!-- 子组件更新过程 -->    <!-- 父beforeUpdate -> 子beforeUpdate -> 子updaed -> 父updated -->    <!-- 父组件跟新过程 -->    <!-- 父beforeUpdate -> 父updated -->    <!-- 销毁过程 -->    <!-- 父beforeDestroy -> 子beforeDestroy -> 子destroyed ->父destroyed -->

== 操作符的强制类型转换规定?

对于 == 来说,如果比照单方的类型不一样,就会进行类型转换。如果比照 xy 是否雷同,就会进行如下判断流程:

  1. 首先会判断两者类型是否雷同,雷同的话就比拟两者的大小;
  2. 类型不雷同的话,就会进行类型转换;
  3. 会先判断是否在比照 nullundefined,是的话就会返回 true
  4. 判断两者类型是否为 stringnumber,是的话就会将字符串转换为 number
1 == '1'      ↓1 ==  1
  1. 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
'1' == true        ↓'1' ==  1        ↓ 1  ==  1
  1. 判断其中一方是否为 object 且另一方为 stringnumber 或者 symbol,是的话就会把 object 转为原始类型再进行判断
'1' == { name: 'js' }        ↓'1' == '[object Object]'

写代码:实现函数可能深度克隆根本类型

浅克隆:

function shallowClone(obj) {  let cloneObj = {};  for (let i in obj) {    cloneObj[i] = obj[i];  }  return cloneObj;}

深克隆:

  • 思考根底类型
  • 援用类型

    • RegExp、Date、函数 不是 JSON 平安的
    • 会失落 constructor,所有的构造函数都指向 Object
    • 破解循环援用
function deepCopy(obj) {  if (typeof obj === 'object') {    var result = obj.constructor === Array ? [] : {};    for (var i in obj) {      result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];    }  } else {    var result = obj;  }  return result;}

如何防止回流与重绘?

缩小回流与重绘的措施:

  • 操作DOM时,尽量在低层级的DOM节点进行操作
  • 不要应用table布局, 一个小的改变可能会使整个table进行从新布局
  • 应用CSS的表达式
  • 不要频繁操作元素的款式,对于动态页面,能够批改类名,而不是款式。
  • 应用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其余元素
  • 防止频繁操作DOM,能够创立一个文档片段documentFragment,在它下面利用所有DOM操作,最初再把它增加到文档中
  • 将元素先设置display: none,操作完结后再把它显示进去。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
  • 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制

浏览器针对页面的回流与重绘,进行了本身的优化——渲染队列

浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了肯定的数量或者到了肯定的工夫距离,浏览器就会对队列进行批处理。这样就会让屡次的回流、重绘变成一次回流重绘。

下面,将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,本来应该是触发屡次回流,变成了只触发一次回流。

webpack配置入口进口

module.exports={    //入口文件的配置项    entry:{},    //进口文件的配置项    output:{},    //模块:例如解读CSS,图片如何转换,压缩    module:{},    //插件,用于生产模版和各项性能    plugins:[],    //配置webpack开发服务性能    devServer:{}}简略形容了一下这几个属性是干什么的。形容一下npm run dev / npm run build执行的是哪些文件通过配置proxyTable来达到开发环境跨域的问题,而后又能够扩大和他聊聊跨域的产生,如何跨域最初能够在聊聊webpack的优化,例如babel-loader的优化,gzip压缩等等

URL有哪些组成部分

一个残缺的URL包含以下几局部:

  • 协定局部:该URL的协定局部为“http:”,这代表网页应用的是HTTP协定。在Internet中能够应用多种协定,如HTTP,FTP等等本例中应用的是HTTP协定。在"HTTP"前面的“//”为分隔符;
  • 域名局部
  • 端口局部:跟在域名前面的是端口,域名和端口之间应用“:”作为分隔符。端口不是一个URL必须的局部,如果省略端口局部,将采纳默认端口(HTTP协定默认端口是80,HTTPS协定默认端口是443);
  • 虚拟目录局部:从域名后的第一个“/”开始到最初一个“/”为止,是虚拟目录局部。虚拟目录也不是一个URL必须的局部。本例中的虚拟目录是“/news/”;
  • 文件名局部:从域名后的最初一个“/”开始到“?”为止,是文件名局部,如果没有“?”,则是从域名后的最初一个“/”开始到“#”为止,是文件局部,如果没有“?”和“#”,那么从域名后的最初一个“/”开始到完结,都是文件名局部。本例中的文件名是“index.asp”。文件名局部也不是一个URL必须的局部,如果省略该局部,则应用默认的文件名;
  • 锚局部:从“#”开始到最初,都是锚局部。本例中的锚局部是“name”。锚局部也不是一个URL必须的局部;
  • 参数局部:从“?”开始到“#”为止之间的局部为参数局部,又称搜寻局部、查问局部。本例中的参数局部为“boardID=5&ID=24618&page=1”。参数能够容许有多个参数,参数与参数之间用“&”作为分隔符。

说一下你对盒模型的了解?

CSS3中的盒模型有以下两种:规范盒模型、IE盒模型盒模型都是由四个局部组成的,别离是margin、border、padding和content规范盒模型和IE盒模型的区别在于设置width和height时, 所对应的范畴不同1、规范盒模型的width和height属性的范畴只蕴含了content2、IE盒模型的width和height属性的范畴蕴含了border、padding和content能够通过批改元素的box-sizing属性来扭转元素的盒模型;1、box-sizing:content-box示意规范盒模型(默认值)2、box-sizing:border-box示意IE盒模型(怪异盒模型)

AJAX

题目形容:利用 XMLHttpRequest 手写 AJAX 实现

实现代码如下:

const getJSON = function (url) {  return new Promise((resolve, reject) => {    const xhr = new XMLHttpRequest();    xhr.open("GET", url, false);    xhr.setRequestHeader("Content-Type", "application/json");    xhr.onreadystatechange = function () {      if (xhr.readyState !== 4) return;      if (xhr.status === 200 || xhr.status === 304) {        resolve(xhr.responseText);      } else {        reject(new Error(xhr.responseText));      }    };    xhr.send();  });};

::before 和 :after 的双冒号和单冒号有什么区别?

(1)冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。
(2)::before就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素。并不存在于dom之中,只存在在页面之中。

留神: :before:after 这两个伪元素,是在CSS2.1里新呈现的。起初,伪元素的前缀应用的是单冒号语法,但随着Web的进化,在CSS3的标准里,伪元素的语法被批改成应用双冒号,成为::before::after

代码输入问题

function Parent() {    this.a = 1;    this.b = [1, 2, this.a];    this.c = { demo: 5 };    this.show = function () {        console.log(this.a , this.b , this.c.demo );    }}function Child() {    this.a = 2;    this.change = function () {        this.b.push(this.a);        this.a = this.b.length;        this.c.demo = this.a++;    }}Child.prototype = new Parent();var parent = new Parent();var child1 = new Child();var child2 = new Child();child1.a = 11;child2.a = 12;parent.show();child1.show();child2.show();child1.change();child2.change();parent.show();child1.show();child2.show();

输入后果:

parent.show(); // 1  [1,2,1] 5child1.show(); // 11 [1,2,1] 5child2.show(); // 12 [1,2,1] 5parent.show(); // 1 [1,2,1] 5child1.show(); // 5 [1,2,1,11,12] 5child2.show(); // 6 [1,2,1,11,12] 5

这道题目值得神帝,他波及到的知识点很多,例如this的指向、原型、原型链、类的继承、数据类型等。

解析:

  1. parent.show(),能够间接取得所需的值,没啥好说的;
  2. child1.show(),Child的构造函数本来是指向Child的,题目显式将Child类的原型对象指向了Parent类的一个实例,须要留神Child.prototype指向的是Parent的实例parent,而不是指向Parent这个类。
  3. child2.show(),这个也没啥好说的;
  4. parent.show(),parent是一个Parent类的实例,Child.prorotype指向的是Parent类的另一个实例,两者在堆内存中互不影响,所以上述操作不影响parent实例,所以输入后果不变;
  5. child1.show(),child1执行了change()办法后,产生了怎么的变动呢?
  6. this.b.push(this.a),因为this的动静指向个性,this.b会指向Child.prototype上的b数组,this.a会指向child1a属性,所以Child.prototype.b变成了[1,2,1,11];
  7. this.a = this.b.length,这条语句中this.athis.b的指向与上一句统一,故后果为child1.a变为4;
  8. this.c.demo = this.a++,因为child1本身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.cthis.a值为4,为原始类型,故赋值操作时会间接赋值,Child.prototype.c.demo的后果为4,而this.a随后自增为5(4 + 1 = 5)。
  9. child2执行了change()办法, 而child2child1均是Child类的实例,所以他们的原型链指向同一个原型对象Child.prototype,也就是同一个parent实例,所以child2.change()中所有影响到原型对象的语句都会影响child1的最终输入后果。
  10. this.b.push(this.a),因为this的动静指向个性,this.b会指向Child.prototype上的b数组,this.a会指向child2a属性,所以Child.prototype.b变成了[1,2,1,11,12];
  11. this.a = this.b.length,这条语句中this.athis.b的指向与上一句统一,故后果为child2.a变为5;
  12. this.c.demo = this.a++,因为child2本身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.c,故执行后果为Child.prototype.c.demo的值变为child2.a的值5,而child2.a最终自增为6(5 + 1 = 6)。

代码输入后果

function runAsync(x) {  const p = new Promise(r =>    setTimeout(() => r(x, console.log(x)), 1000)  );  return p;}function runReject(x) {  const p = new Promise((res, rej) =>    setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)  );  return p;}Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])  .then(res => console.log("result: ", res))  .catch(err => console.log(err));

输入后果如下:

0Error: 0123

能够看到在catch捕捉到第一个谬误之后,前面的代码还不执行,不过不会再被捕捉了。

留神:allrace传入的数组中如果有会抛出异样的异步工作,那么只有最先抛出的谬误会被捕捉,并且是被then的第二个参数或者前面的catch捕捉;但并不会影响数组中其它的异步工作的执行。

let、const、var的区别

(1)块级作用域: 块作用域由 { }包含,let和const具备块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:

  • 内层变量可能笼罩外层变量
  • 用来计数的循环变量泄露为全局变量

(2)变量晋升: var存在变量晋升,let和const不存在变量晋升,即在变量只能在申明之后应用,否在会报错。

(3)给全局增加属性: 浏览器的全局对象是window,Node的全局对象是global。var申明的变量为全局变量,并且会将该变量增加为全局对象的属性,然而let和const不会。

(4)反复申明: var申明变量时,能够反复申明变量,后申明的同名变量会笼罩之前申明的遍历。const和let不容许反复申明变量。

(5)暂时性死区: 在应用let、const命令申明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。应用var申明的变量不存在暂时性死区。

(6)初始值设置: 在变量申明时,var 和 let 能够不必设置初始值。而const申明变量必须设置初始值。

(7)指针指向: let和const都是ES6新增的用于创立变量的语法。 let创立的变量是能够更改指针指向(能够从新赋值)。但const申明的变量是不容许扭转指针的指向。

区别varletconst
是否有块级作用域×✔️✔️
是否存在变量晋升✔️××
是否增加全局属性✔️××
是否反复申明变量✔️××
是否存在暂时性死区×✔️✔️
是否必须设置初始值××✔️
是否扭转指针指向✔️✔️×

Cookie、LocalStorage、SessionStorage区别

浏览器端罕用的存储技术是 cookie 、localStorage 和 sessionStorage。

  • cookie: 其实最开始是服务器端用于记录用户状态的一种形式,由服务器设置,在客户端存储,而后每次发动同源申请时,发送给服务器端。cookie 最多能存储 4 k 数据,它的生存工夫由 expires 属性指定,并且 cookie 只能被同源的页面访问共享。
  • sessionStorage: html5 提供的一种浏览器本地存储的办法,它借鉴了服务器端 session 的概念,代表的是一次会话中所保留的数据。它个别可能存储 5M 或者更大的数据,它在以后窗口敞开后就生效了,并且 sessionStorage 只能被同一个窗口的同源页面所访问共享。
  • localStorage: html5 提供的一种浏览器本地存储的办法,它个别也可能存储 5M 或者更大的数据。它和 sessionStorage 不同的是,除非手动删除它,否则它不会生效,并且 localStorage 也只能被同源页面所访问共享。

下面几种形式都是存储大量数据的时候的存储形式,当须要在本地存储大量数据的时候,咱们能够应用浏览器的 indexDB 这是浏览器提供的一种本地的数据库存储机制。它不是关系型数据库,它外部采纳对象仓库的模式存储数据,它更靠近 NoSQL 数据库。

TCP和UDP的应用场景

  • TCP利用场景: 效率要求绝对低,但对准确性要求绝对高的场景。因为传输中须要对数据确认、重发、排序等操作,相比之下效率没有UDP高。例如:文件传输(精确高要求高、然而速度能够绝对慢)、承受邮件、近程登录。
  • UDP利用场景: 效率要求绝对高,对准确性要求绝对低的场景。例如:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,然而呈现偶然断续不是太大问题,并且此处齐全不能够应用重发机制)、播送通信(播送、多播)。

对浏览器内核的了解

浏览器内核次要分成两局部:

  • 渲染引擎的职责就是渲染,即在浏览器窗口中显示所申请的内容。默认状况下,渲染引擎能够显示 html、xml 文档及图片,它也能够借助插件显示其余类型数据,例如应用 PDF 阅读器插件,能够显示 PDF 格局。
  • JS 引擎:解析和执行 javascript 来实现网页的动态效果。

最开始渲染引擎和 JS 引擎并没有辨别的很明确,起初 JS 引擎越来越独立,内核就偏向于只指渲染引擎。

new操作符的实现原理

new操作符的执行过程:

(1)首先创立了一个新的空对象

(2)设置原型,将对象的原型设置为函数的 prototype 对象。

(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象增加属性)

(4)判断函数的返回值类型,如果是值类型,返回创立的对象。如果是援用类型,就返回这个援用类型的对象。

具体实现:

function objectFactory() {  let newObject = null;  let constructor = Array.prototype.shift.call(arguments);  let result = null;  // 判断参数是否是一个函数  if (typeof constructor !== "function") {    console.error("type error");    return;  }  // 新建一个空对象,对象的原型为构造函数的 prototype 对象  newObject = Object.create(constructor.prototype);  // 将 this 指向新建对象,并执行函数  result = constructor.apply(newObject, arguments);  // 判断返回对象  let flag = result && (typeof result === "object" || typeof result === "function");  // 判断返回后果  return flag ? result : newObject;}// 应用办法objectFactory(构造函数, 初始化参数);

对JSON的了解

JSON 是一种基于文本的轻量级的数据交换格局。它能够被任何的编程语言读取和作为数据格式来传递。

在我的项目开发中,应用 JSON 作为前后端数据交换的形式。在前端通过将一个合乎 JSON 格局的数据结构序列化为
JSON 字符串,而后将它传递到后端,后端通过 JSON 格局的字符串解析后生成对应的数据结构,以此来实现前后端数据的一个传递。

因为 JSON 的语法是基于 js 的,因而很容易将 JSON 和 js 中的对象弄混,然而应该留神的是 JSON 和 js 中的对象不是一回事,JSON 中对象格局更加严格,比如说在 JSON 中属性值不能为函数,不能呈现 NaN 这样的属性值等,因而大多数的 js 对象是不合乎 JSON 对象的格局的。

在 js 中提供了两个函数来实现 js 数据结构和 JSON 格局的转换解决,

  • JSON.stringify 函数,通过传入一个合乎 JSON 格局的数据结构,将其转换为一个 JSON 字符串。如果传入的数据结构不合乎 JSON 格局,那么在序列化的时候会对这些值进行对应的非凡解决,使其符合规范。在前端向后端发送数据时,能够调用这个函数将数据对象转化为 JSON 格局的字符串。
  • JSON.parse() 函数,这个函数用来将 JSON 格局的字符串转换为一个 js 数据结构,如果传入的字符串不是规范的 JSON 格局的字符串的话,将会抛出谬误。当从后端接管到 JSON 格局的字符串时,能够通过这个办法来将其解析为一个 js 数据结构,以此来进行数据的拜访。

实现有并行限度的 Promise 调度器

题目形容:JS 实现一个带并发限度的异步调度器 Scheduler,保障同时运行的工作最多有两个

 addTask(1000,"1"); addTask(500,"2"); addTask(300,"3"); addTask(400,"4"); 的输入程序是:2 3 1 4 整个的残缺执行流程:一开始1、2两个工作开始执行500ms时,2工作执行结束,输入2,工作3开始执行800ms时,3工作执行结束,输入3,工作4开始执行1000ms时,1工作执行结束,输入1,此时只剩下4工作在执行1200ms时,4工作执行结束,输入4

实现代码如下:

class Scheduler {  constructor(limit) {    this.queue = [];    this.maxCount = limit;    this.runCounts = 0;  }  add(time, order) {    const promiseCreator = () => {      return new Promise((resolve, reject) => {        setTimeout(() => {          console.log(order);          resolve();        }, time);      });    };    this.queue.push(promiseCreator);  }  taskStart() {    for (let i = 0; i < this.maxCount; i++) {      this.request();    }  }  request() {    if (!this.queue || !this.queue.length || this.runCounts >= this.maxCount) {      return;    }    this.runCounts++;    this.queue      .shift()()      .then(() => {        this.runCounts--;        this.request();      });  }}const scheduler = new Scheduler(2);const addTask = (time, order) => {  scheduler.add(time, order);};addTask(1000, "1");addTask(500, "2");addTask(300, "3");addTask(400, "4");scheduler.taskStart();

TCP/IP五层协定

TCP/IP五层协定和OSI的七层协定对应关系如下:

  • 应用层 (application layer):间接为利用过程提供服务。应用层协定定义的是利用过程间通信和交互的规定,不同的利用有着不同的应用层协定,如 HTTP协定(万维网服务)、FTP协定(文件传输)、SMTP协定(电子邮件)、DNS(域名查问)等。
  • 传输层 (transport layer):有时也译为运输层,它负责为两台主机中的过程提供通信服务。该层次要有以下两种协定:

    • 传输控制协议 (Transmission Control Protocol,TCP):提供面向连贯的、牢靠的数据传输服务,数据传输的根本单位是报文段(segment);
    • 用户数据报协定 (User Datagram Protocol,UDP):提供无连贯的、尽最大致力的数据传输服务,但不保障数据传输的可靠性,数据传输的根本单位是用户数据报。
  • 网络层 (internet layer):有时也译为网际层,它负责为两台主机提供通信服务,并通过抉择适合的路由将数据传递到指标主机。
  • 数据链路层 (data link layer):负责将网络层交下来的 IP 数据报封装成帧,并在链路的两个相邻节点间传送帧,每一帧都蕴含数据和必要的管制信息(如同步信息、地址信息、差错控制等)。
  • 物理层 (physical Layer):确保数据能够在各种物理媒介上进行传输,为数据的传输提供牢靠的环境。

从上图中能够看出,TCP/IP模型比OSI模型更加简洁,它把应用层/表示层/会话层全副整合为了应用层

在每一层都工作着不同的设施,比方咱们罕用的交换机就工作在数据链路层的,个别的路由器是工作在网络层的。 在每一层实现的协定也各不同,即每一层的服务也不同,下图列出了每层次要的传输协定:

同样,TCP/IP五层协定的通信形式也是对等通信: