1. 实用js写红绿灯的成果?

<ul id="traffic" class=""> <li id="green"></li> <li id="yellow"></li> <li id="red"></li></ul>
ul { position: absolute; width: 200px; height: 200px; top: 50%; left: 50%; transform: translate(-50%,-50%);} /*画3个圆代表红绿灯*/ ul >li {  width: 40px;  height: 40px;  border-radius:50%;  opacity: 0.2;  display: inline-block; } /*执行时扭转透明度*/ ul.red >#red,  ul.green >#green, ul.yellow >#yellow{  opacity: 1.0; } /*红绿灯的三个色彩*/ #red {background: red;} #yellow {background: yellow;} #green {background: green;}
function timeout(timer){  return function(){    return new Promise(function(resolve,reject){   setTimeout(resolve,timer)    })    }  } var green = timeout(3000); var yellow = timeout(4000); var red = timeout(5000); var traffic = document.getElementById("traffic"); (function restart(){  'use strict'      //严格模式  console.log("绿灯"+new Date().getSeconds()) //绿灯执行三秒   traffic.className = 'green';  green()  .then(function(){   console.log("黄灯"+new Date().getSeconds()) //黄灯执行四秒   traffic.className = 'yellow';   return yellow();  })  .then(function(){   console.log("红灯"+new Date().getSeconds()) //红灯执行五秒   traffic.className = 'red';   return red();  }).then(function(){   restart()  })  })();

2. axios是否须要promise封装?

须要

import axios from 'axios'const http = ({    url,method,params,headers}) => {return new Promise ( (resolve,reject) => {    axios({        url,        method,        params,        headers    })    .then( res => {        resolve(res)    })    .catch( error => {        throw error    })    })}export default http

3. Promise外部产生谬误,如果同时.then办法有第二个参数,也有.catch会调用哪个

.catch

4. 宏工作 微工作

setTimeout(function(){            console.log('1')        });         new Promise(function(resolve){            console.log('2');                    resolve();        }).then(function(){            console.log('3')        });         console.log('4')

settimeout必定是异步的。 我也晓得有一个event队列,你settimeout没设置工夫应该间接就进入这个队列了吧,而后就是Promise的回掉函数进入event队列。 过后我二话不说给了个答案 2,4,1,3.并且很自信。而后面试官就问你不想想了?我说不想了。而后后半段他全程开始皱眉头了。我也凉凉。最初他让我回去看一下宏工作和微工作。

首先说一下一般的异步函数的执行过程吧

同步和异步工作别离进入不同的执行"场合",同步的进入主线程,异步的进入Event Table并注册函数。当指定的事件实现时,Event Table会将这个函数移入Event Queue。主线程内的工作执行结束为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会一直反复,也就是常说的Event Loop(事件循环)。

那么如此看来我给的答案还是对的。然而js异步有一个机制,就是遇到宏工作,先执行宏工作,将宏工作放入eventqueue,而后在执行微工作,将微工作放入eventqueue最骚的是,这两个queue不是一个queue。当你往外拿的时候先从微工作里拿这个回掉函数,而后再从宏工作的queue上拿宏工作的回掉函数。 我过后看到这我就服了还有这种骚操作。

而宏工作个别是:包含整体代码script,setTimeout,setInterval。

微工作:Promise,process.nextTick。

记住就行了。

而后回到结尾的代码。因为settimeout是宏工作,尽管先执行的他,然而他被放到了宏工作的eventqueue外面,而后代码持续往下查看看有没有微工作,检测到Promise的then函数把他放入了微工作序列。等到主线过程的所有代码执行完结后。先从微工作queue里拿回掉函数,而后微工作queue空了后再从宏工作的queue拿函数。

所以正确的执行后果当然是:2,4,3,1。

https://juejin.im/post/59e85e...

5. Js 原型和原型链

原型链的设计是js的精华所在,比拟形象。须要从外部设计原理去了解这种设计思维,在纸上画画其中的关系会帮忙了解。

prototype对象

prototype对象的引入:所有实例对象须要共享的属性和办法,都放在这个对象中,那些不须要共享的属性和办法,就放在构造函数中。以此来模仿类。

function Animal(name) {    this.name = name}Animal.prototype.getName = function() {    console.log(this.name)}var animal1 = new Animal('Kate')var animal2 = new Animal('Lucy')//对象animal1 和 animal2共享方法getNameanimal1.getName()animal2.getName()

原型链

在javascript中,每个对象都有一个指向它的原型(prototype)对象的外部链接。每个原型对象又有本人的原型,直到某个对象的原型为null为止,组成这条链的最初一环。

*proto写入es6规范

当一个对象被创立时,它的__protp__属性和外部属性[[prototype]]指向雷同的对象(也就是它的构造函数的prototype属性)。扭转__proto__属性的值同时也会扭转外部属性[[prototype]]的值,除非该对象是不可扩大的。
在ES5中,所有构造函数的__proto__都指向Function.prototype
**在ES6中,构造函数的__proto__指向它的父类构造函数

obj.__proto__ === obj.[[prototype]]// ES5Cat.__proto__ === Function.prototype// ES6Cat.__proto__ === Animal

构造函数继承

有四种形式能够实现构造函数的继承
1.调用apply办法

function Animal() {    this.species = '动物'}Animal.prototype.getName = function() {    console.log('我是动物')}function Cat() {    Animal.apply(this, arguments)}var cat = new Cat()cat.species    // 动物cat.getName()  // undefined

这种办法能够继承父类构造函数的属性,然而无奈继承prototype属性,即父类中共享的办法和属性

2.改写prototype对象

Cat.prototype = new Animal()Cat.prototype.constructor = Cat

这是最罕用的办法来模仿单继承,毛病是始终要保留Animal的对象,如果Animal对象比拟大时,会耗费局部内存(其实很少),并且没有实现多继承

3.间接继承prototype

Cat.prototype = Animal.prototypeCat.prototype.constructor = Cat

毛病是当批改了Cat.prototype上的办法时会影响Animal.prototype

4.利用空对象作中介

var F = function(){}F.prototype = Animal.prototypeCat.prototype = new F()Cat.prototype.constructor = Cat

6. js的事件循环机制是什么

过程、线程

  • 过程是零碎调配的独立资源,是 CPU 资源分配的根本单位,过程是由一个或者多个线程组成的。
  • 线程是过程的执行流,是CPU调度和分派的根本单位,同个过程之中的多个线程之间是共享该过程的资源的。

浏览器内核

  • 浏览器是多过程的,浏览器每一个 tab 标签都代表一个独立的过程(也不肯定,因为多个空白 tab 标签会合并成一个过程),浏览器内核(浏览器渲染过程)属于浏览器多过程中的一种。
  • 浏览器内核有多种线程在工作。

    • GUI 渲染线程:

      • 负责渲染页面,解析 HTML,CSS 形成 DOM 树等,当页面重绘或者因为某种操作引起回流都会调起该线程。
      • 和 JS 引擎线程是互斥的,当 JS 引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI 更新被放入在 JS 工作队列中,期待 JS 引擎线程闲暇的时候继续执行。
    • JS 引擎线程:

      • 单线程工作,负责解析运行 JavaScript 脚本。
      • 和 GUI 渲染线程互斥,JS 运行耗时过长就会导致页面阻塞。
    • 事件触发线程:

      • 当事件合乎触发条件被触发时,该线程会把对应的事件回调函数增加到工作队列的队尾,期待 JS 引擎解决。
    • 定时器触发线程:

      • 浏览器定时计数器并不是由 JS 引擎计数的,阻塞会导致计时不精确。
      • 开启定时器触发线程来计时并触发计时,计时实现后会被增加到工作队列中,期待 JS 引擎解决。
    • http 申请线程:

      • http 申请的时候会开启一条申请线程。
      • 申请实现有后果了之后,将申请的回调函数增加到工作队列中,期待 JS 引擎解决。
      • JavaScript 引擎是单线程

        JavaScript 引擎是单线程,也就是说每次只能执行一项工作,其余工作都得依照程序排队期待被执行,只有以后的工作执行实现之后才会往下执行下一个工作。

        HTML5 中提出了 Web-Worker API,次要是为了解决页面阻塞问题,然而并没有扭转 JavaScript 是单线程的实质。理解 Web-Worker。

        JavaScript 事件循环机制

        JavaScript 事件循环机制分为浏览器和 Node 事件循环机制,两者的实现技术不一样,浏览器 Event Loop 是 HTML 中定义的标准,Node Event Loop 是由 libuv 库实现。这里次要讲的是浏览器局部。

        Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的工作都会被放到调用栈期待主线程执行。

        • JS 调用栈

          JS 调用栈是一种后进先出的数据结构。当函数被调用时,会被增加到栈中的顶部,执行实现之后就从栈顶部移出该函数,直到栈内被清空。

        • 同步工作、异步工作

          JavaScript 单线程中的工作分为同步工作和异步工作。同步工作会在调用栈中依照程序排队期待主线程执行,异步工作则会在异步有了后果后将注册的回调函数增加到工作队列(音讯队列)中期待主线程闲暇的时候,也就是栈内被清空的时候,被读取到栈中期待主线程执行。工作队列是先进先出的数据结构。

        • Event Loop

          调用栈中的同步工作都执行结束,栈内被清空了,就代表主线程闲暇了,这个时候就会去工作队列中依照程序读取一个工作放入到栈中执行。每次栈内被清空,都会去读取工作队列有没有工作,有就读取执行,始终循环读取-执行的操作,就造成了事件循环。

7.前端跨域的形式

前端跨域的计划:1、通过jsonp跨域2、postMessage跨域3、跨域资源共享(CORS)4、nginx代理跨域5、nodejs中间件代理跨域6、WebSocket协定跨域7.反向代理<u>https://segmentfault.com/a/1190000011145364</u>

8.Promise的了解,和promise都有哪些办法

Promise,就是一个对象,用来传递异步操作的音讯,防止了层层嵌套的回调函数。它代表了某个将来才会晓得后果的事件(通常是一个异步操作),并且这个事件提供对立的API,可供进一步解决。 (1)对象的状态不受外界影响。有三种状态:Pending(进行中)、Resolved(已实现,又称Fulfilled)和Rejected(已失败)。 (2)一旦状态扭转,就不会再变,任何时候都能够失去这个后果。Promise对象的状态扭转,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只有这两种状况产生,状态就凝固了,不会再变了,会始终放弃这个后果

9.原型和原型链的了解

咱们发明的每一个函数都有一个prototype(原型)属性。这个属性是一个指针,指向原型对 象。在默认状况下,所有的原型对象都会有一个constructor(构造函数)属性,这个属性蕴含一个指向prototype属相所在的指针。当调用构造函数创立一个新实例之后,该实例外部将蕴含一个指针(外部属性),指向构造函数的原型对象。<u>https://juejin.im/post/5ae95290518825672c00c0a4</u>

10:异步形式

1. Promise2. Generator 3. Async-await4. Node.js 中的nextTick()和setimmediate()5. async库

11:修复bug或增加新性能的常见工作流(git命令)是什么?空和未定义的javascript有什么区别?

git flow feature start f1 增加新个性,这个操作创立了一个基于develop的个性分支,并切换到这个分支之下。git flow feature finish f1 实现新个性,这个操作会合并f1分支到develop分支,并删除个性分支,切换回develop分支。git flow feature publish f1 公布新分支,公布新个性分支到近程服务器,其它用户也能够应用这分支。修复bug:git flow hotfix start VERSION [BASENAME] 创立hotfix分支,VERSION 参数标记着修改版本,[BASENAME]为finish release时填写的版本号。

12:您应用什么框架来编写单元测试,写下一个案例来验证调用的函数

一、问题形容: 在一个升序数组中,应用折半查找失去要查问的值的索引地位。如:
var a=[1,2,3,4,5,6,7,8,9];search(a,3);//返回2search(a,1);//左边界,返回0search(a,9);//右边界,返回8search(a,0);//比最小的值还小,返回"您查找的数值不存在"search(a,10);//比最大的值还大,返回"您查找的数值不存在"

注:折半查找必须在有序数组中才无效,无序的数组不能实现查找性能。比方:在[10,5,6,7,8,9,20]中查找10,两头索引地位的值为7,比拟得出7比10小,因此应该在右子数组中查找,实际上不可能找到10;
二、我的实现

  function search(arr,num) {            var l=arr.length;            var left=0;            var right=l-1;            var center=Math.floor((left+right)/2);            while(left<=l-1&&right>=0){                if (arr[center]==num) return center;                if (left==right) return "您查找的数不存在";                if (arr[center]>num) {                    right=center-1;                    center=Math.floor((left+right)/2);                }else if (arr[center]<num) {                    left=center+1;                    center=Math.floor((left+right)/2);                }            }        }        var a=[1,2,3,4,5,6,7,8,9];        console.log(search(a,-2));
阐明: 1、基本思路: 每次比拟,如果数组两头索引地位的值比要查找的值大,就转而在数组两头地位之前的子数组中查找;相同,如果数组两头索引地位的值比要查找的值大,就转而在数组两头地位之后的子数组中查找;如果数组两头索引地位的值恰好等于要查找的值,就返回该索引地位。2、left定义查找范畴的起始地位,right定义查找范畴的完结地位,center定义查找范畴的两头地位。3、while中的逻辑阐明: (1)因为不晓得具体查找查找多少次,while是比拟好的抉择; (2)循环完结条件: a、一旦当right小于0时,就不再查找,再纠缠也不会有后果。例如:在a=[1,2,3,4,5,6,7,8,9]中查找0,当查找范畴变为left=0,right=0,center=0时,进入while语句,因为arr[center]>0,故执行 right=center-1;center=Math.floor((left+right)/2); 失去right=-1此时应不再进入循环; b、一旦当left>l-1时,就不再查找,同样再纠缠也不会有后果。例如:在a=[1,2,3,4,5,6,7,8,9]中查找10,当查找范畴变为left=8,right=8,center=8时,进入while语句,因为arr[center]<10,故执行 left=center;center=Math.floor((left+right)/2); 失去left=9,此时应不再进入循环;4、始终是通过center匹配到要查找的值;5、Math.floor解决了查找范畴长度为偶数的状况;6、当left==right了,而arr[center]==num却没执行,能够得出结论查找不到的;7、当arr[center]==num时,整个函数都完结了,前面语句是不会执行的。

13.编写一个regex表达式以查找内容,内容以2个数字结尾,以结尾

var reg = /^0-9$/

14.push 增加数组后, 是怎么响应的

push() 办法可向数组的开端增加一个或多个元素,并返回新的长度

正文:该办法会扭转数组的长度。

语法:

arrayObject.push(newelement1,newelement2,....,newelementX)

参数形容

newelement1 必须。要增加到数组的第一个元素。

newelement2 可选。要增加到数组的第二个元素。

newelementX 可选。可增加多个元素。

push() 办法可把它的参数程序增加到 arrayObject 的尾部。它间接批改 arrayObject,而不是创立一个新的数组。push() 办法和 pop() 办法应用数组提供的先进后出栈的性能。

15.js根本数据类型

Undefined、Null、Bollean、Number、String

16.js中==和===的区别是什么

前者会主动转换类型

后者不会

17.for和for in 区别

语法结构上不同,

for 个别用来遍历数组的,是比较简单的操作

for in 个别用来遍历对象,尽管for in 也能遍历数组,然而会存在

以下几个问题:

1、index索引为字符串型数字,不能间接进行几何运算

2、遍历程序有可能不是依照理论数组的外部程序

3、应用for in会遍历数组所有的可枚举属性,包含原型。例如上栗

的原型办法method和name属性

这也是为什么用for不必for in的区别,如果是遍历一般数组的话,

用for是最好的抉择,然而如果是对象,用for in就好了。

18.js中==和===的区别是什么

操作数1 == 操作数2,  操作数1 === 操作数2双等号==:   (1)如果两个值类型雷同,再进行三个等号(===)的比拟  (2)如果两个值类型不同,也有可能相等,需依据以下规定进行类型转换在比拟:   1)如果一个是null,一个是undefined,那么相等    2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比拟三等号===:  (1)如果类型不同,就肯定不相等  (2)如果两个都是数值,并且是同一个值,那么相等;如果其中至多一个是NaN,那么不相      等。(判断一个值是否是NaN,只能应用isNaN( ) 来判断)  (3)如果两个都是字符串,每个地位的字符都一样,那么相等,否则不相等。  (4)如果两个值都是true,或是false,那么相等  (5)如果两个值都援用同一个对象或是函数,那么相等,否则不相等  (6)如果两个值都是null,或是undefined,那么相等

19:for和for in 区别

for in:1.for...in 语句用于对数组或者对象的属性进行循环操作。2.for ... in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。3.for...in语句以任意程序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。for :1.for循环是对数组的元素进行循环,而不能引用于非数组对象。

20:数组去重的办法

第一种:function uniq(array){   var temp = []; //一个新的长期数组   for(var i = 0; i < array.length; i++){       if(temp.indexOf(array[i]) == -1){           temp.push(array[i]);       }   }   return temp;}var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];console.log(uniq(aa));
第二种:对象键值法去重function uniq(array){    var temp = {}, r = [], len = array.length, val, type;    for (var i = 0; i < len; i++) {        val = array[i];        type = typeof val;        if (!temp[val]) {            temp[val] = [type];            r.push(val);        } else if (temp[val].indexOf(type) < 0) {            temp[val].push(type);            r.push(val);        }    }    return r;}var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];console.log(uniq(aa));
第三种:排序后相邻去除法function uniq(array){    array.sort();    var temp=[array[0]];    for(var i = 1; i < array.length; i++){        if( array[i] !== temp[temp.length-1]){            temp.push(array[i]);        }    }    return temp;}var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];console.log(uniq(aa));
第四种:数组下标法function uniq(array){    var temp = [];    for(var i = 0; i < array.length; i++) {        //如果以后数组的第i项在以后数组中第一次呈现的地位是i,才存入数组;否则代表是反复的        if(array.indexOf(array[i]) == i){            temp.push(array[i])        }    }    return temp;}var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];console.log(uniq(aa));
第五种:优化遍历数组法function uniq(array){    var temp = [];    var index = [];    var l = array.length;    for(var i = 0; i < l; i++) {        for(var j = i + 1; j < l; j++){            if (array[i] === array[j]){                i++;                j = i;            }        }        temp.push(array[i]);        index.push(i);    }    console.log(index);    return temp;}var aa = [1,2,2,3,5,3,6,5];console.log(uniq(aa));

21:排序的办法

第一种:冒泡排序:var arr = [1,4,-8,-3,6,12,9,8];function bubbleSort(arr){        for (var i = 0; i < arr.length; i++) {            for (var j = 0; j < arr.length-i-1; j++) {                if(arr[j] > arr[j+1]){                    var c = arr[j];                    arr[j] = arr[j+1];                    arr[j+1] = c;                }            }        }        return arr;    }        console.log(bubbleSort(arr));
疾速排序:var arr = [1,4,-8,-3,6,12,9,8];function quicksort(arr){   if(arr.length <= 1){              return arr;              }              var middleIndex = Math.floor(arr.length/2);              var middleNum = arr.splice(middleIndex,1);              var left = [], right = [];              for (var i = 0; i < arr.length; i++) {                          if(arr[i] < middleNum){                                 left.push(arr[i]);                             } else {                                   right.push(arr[i]);                                }                      }                       return quicksort(left).concat(middleNum, quicksort(right));     }       console.log(quicksort(arr));
抉择排序:var arr = [1,4,-8,-3,6,12,9,8];function selectSort(arr){           for(var i=0;i<arr.length;i++){               //设置以后范畴最小值和索引               var min = arr[i];               var minIndex = i;              //在该范畴选出最小值              for(var j=i+1;j<arr.length;j++){                      if(min>arr[j]){                                  min = arr[j];                                  minIndex = j;                        }               }               //将最小值插入,并将原来地位的最小值删除                arr.splice(i,0,min);               arr.splice(minIndex+1,1);           }           return arr;       }            console.log(selectSort(arr));
插入排序:var array = [1,4,-8,-3,6,12,9,8]; function selectSort(arr){    for(var i=0;i<arr.length;i++){    //设置以后范畴最小值和索引             var min = arr[i];            var minIndex = i;             //在该范畴选出最小值             for(var j=i+1;j<arr.length;j++){                if(min>arr[j]){                     min = arr[j];                     minIndex = j;                 }            }            //将最小值插入,并将原来地位的最小值删除             arr.splice(i,0,min);             arr.splice(minIndex+1,1);       }  }            selectSort(array);            document.write(array);

22:冒泡排序

var arr = [1,4,-8,-3,6,12,9,8];function bubbleSort(arr){        for (var i = 0; i < arr.length; i++) {            for (var j = 0; j < arr.length-i-1; j++) {                if(arr[j] > arr[j+1]){                    var c = arr[j];                    arr[j] = arr[j+1];                    arr[j+1] = c;                }            }        }        return arr;    }        console.log(bubbleSort(arr));

23:原型链的了解:

 在谈原型链之前,咱们首先要理解自定义函数与 Function 之间是什么关系,而构造函数、原型和实例之间又存在什么千头万绪的关系呢?其实,所有的函数都是 Function 的实例。在构造函数上都有一个原型属性 prototype,该属性也是一个对象;那么在原型对象上有一个 constructor 属性,该属性指向的就是构造函数;而实例对象上有一个 _proto_  属性,该属性也指向原型对象,并且该属性不是规范属性,不能够用在编程中,该属性用于浏览器外部应用。

[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-QqhVpWo7-1630416218424)(en-resource://database/450:1)]
[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-8tp8hnPS-1630416218430)(en-resource://database/452:1)]

1、原型链 1)构造函数、原型和实例的关系         ①构造函数都有一个属性prototype,这个属性是一个对象(Object的实例) ②原型对象prototype外面有一个constructor属性,该属性指向原型对象所属的构造函数 ③实例对象都有一个_proto_属性,该属性也指向构造函数的原型对象,它是一个非标准属性, 不能够用于编程,它是用于浏览器本人应用的2)prototype与_proto_的关系    ①prototype是构造函数的属性            ②_proto_是实例对象的属性                    ——这两者都指向同一个对象        【总结】    i)函数也是对象,对象不肯定是函数;               ii)对象的实质:无序的键值对汇合;键值对当中的值能够是任意数据类型的值               iii)对象就是一个容器,这个容器当中放的是(属性和办法)   3)属性搜寻      ①在拜访对象的某个成员的时候会先在对象中找是否存在      ②如果以后对象中没有就在构造函数的原型对象中找      ③如果原型对象中没有找到就到原型对象的原型上找      ④晓得Object的原型对象的原型是null为止2、Function——所有函数都是Function的实例     `①本地对象:独立于宿主环境(浏览器)的对象——包含Object、Array、Date、RegExp、       Function、Error、Number、String、Boolean      ②内置对象——包含Math、Global(window,在js中就是全局变量),应用的时候不须要          new      ③宿主对象——包含自定义对象、DOM、BOM

24:扭转this指向的办法

第一种: new关键字扭转this指向function Fn(){    this.user = "追梦子"; } var a = new Fn(); console.log(a.user); //追梦子  用变量a创立了一个Fn的实例(相当于复制了一份Fn到对象a外面),此时仅仅只是创立,并没有执行,而调用这个函数Fn的是对象a,那么this指向的天然是对象a,那么为什么对象a中会有user,因为你曾经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份第二种: call()
第二种: call()var a = {      user:"追梦子",     fn:function(){             console.log(this.user); //追梦子     }}var b = a.fn;b.call(a); //若不必call,则b()执行后this指的是Window对象把b增加到第一个参数的环境中,简略来说,this就会指向那个对象。
第三种:apply()var a = {      user:"追梦子",      fn:function(){            console.log(this.user); //追梦子      }}var b = a.fn;b.apply(a);
第四种:bind()var a = {     user:"追梦子",    fn:function(){             console.log(this.user);    }} var b = a.fn; b.bind(a); //代码没有被打印咱们发现代码没有被打印,对,这就是bind和call、apply办法的不同,实际上bind办法返回的是一个批改过后的函数。

25:es6新个性

1. 变量申明let 与 const:能够把let看成var,只是它定义的变量被限定在了特定范畴内能力应用,而来到这个范畴则有效。const则很直观,用来定义常量,即无奈被更改值的变量。for (let i=0;i<2;i++)console.log(i);//输入: 0,1console.log(i);//输入:undefined,严格模式下会报错
2.类的反对 ES6中增加了对类的反对,引入了class关键字(其实class在JavaScript中始终是保留字,目标就是思考到可能在当前的新版本中会用到,当初终于派上用场了)。JS自身就是面向对象的,ES6中提供的类实际上只是JS原型模式的包装。当初提供原生的class反对后,对象的创立,继承更加直观了,并且父类办法的调用,实例化,静态方法和构造函数等概念都更加形象化。   //类的定义class Animal {    //ES6中新型结构器    constructor(name) {        this.name = name;    }    //实例办法    sayName() {        console.log('My name is '+this.name);    }}//类的继承class Programmer extends Animal {    constructor(name) {        //间接调用父类结构器进行初始化        super(name);    }    program() {        console.log("I'm coding...");    }}//测试咱们的类var animal=new Animal('dummy'),wayou=new Programmer('wayou');animal.sayName();//输入 ‘My name is dummy’wayou.sayName();//输入 ‘My name is wayou’wayou.program();//输入 ‘I'm coding...’
3.字符串模板  字符串模板绝对简略易懂些。ES6中容许应用反引号 ` 来创立字符串,此种办法创立的字符串外面能够蕴含由美元符号加花括号包裹的变量${vraible}。如果你应用过像C#等后端强类型语言的话,对此性能应该不会生疏。  
//产生一个随机数var num=Math.random();//将这个数字输入到consoleconsole.log(`your num is ${num}`);
4.解构:主动解析数组或对象中的值。比方若一个函数要返回多个值,惯例的做法是返回一个对象,将每个值做为这个对象的属性返回。但在ES6中,利用解构这一个性,能够间接返回一个数组,而后数组中的值会主动被解析到对应接管该值的变量中。var [x,y]=getVal(),//函数返回值的解构    [name,,age]=['wayou','male','secrect'];//数组解构 function getVal() {    return [ 1, 2 ];} console.log('x:'+x+', y:'+y);//输入:x:1, y:2 console.log('name:'+name+', age:'+age);//输入: name:wayou, age:secrect 
5.Promise:Promises是解决异步操作的一种模式,之前在很多三方库中有实现,比方jQuery的deferred 对象。当你发动一个异步申请,并绑定了.when(), .done()等事件处理程序时,其实就是在利用promise模式。//创立promisevar promise = new Promise(function(resolve, reject) {    // 进行一些异步或耗时操作    if ( /*如果胜利 */ ) {        resolve("Stuff worked!");    } else {        reject(Error("It broke"));    }});//绑定处理程序promise.then(function(result) {    //promise胜利的话会执行这里    console.log(result); // "Stuff worked!"}, function(err) {    //promise失败会执行这里    console.log(err); // Error: "It broke"});

26.promise的了解

ES6提供的解决异步解决办法

有两个长处

1.promise对象的状态不受外界影响

-pending 初始状态

-fulfilled 胜利状态

-rejected 失败状态

2.promise的状态一旦扭转,就不会再变,状态不可逆,只能由pending变成pending变成fulfilled或者由pending变成rejected

三个毛病

1.无奈勾销promise,一旦新建它就会立刻执行,无奈中途勾销

2.如果不设置回调函数,promise外部抛出的谬误,不会反映到内部

3.当处于pending状态时,无奈得悉目前停顿到哪一个阶段

用法

 const promise = new Promise(function(resolve, reject) {      // ... some code      if (/* 异步操作胜利 */){        resolve(value);      } else {        reject(error);      }    });

27.同源策略

同源策略是浏览器的一个平安性能,不同源的客户端脚本在没有明确受权的状况下,不能读写对方资源。同源指的是协定,域名和端口号均雷同则属于同源

28.前端跨域的形式

应用jsonp跨域,因为script标签引入的js是不受同源策略的限度,通过script标签引入一个js或者是一个其余后缀模式(如php,jsp等)的文件,此时文件返回一个JS函数的调用

通过cors跨域,实现cors通信的要害是服务器,只有服务器实现cors接口,就能够跨域

<script type="text/javascript">    var xhr = new XMLHttpRequest();    xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);    xhr.send();</script>

反向代理跨域,反向代理指的是在前端的服务器环境中, 短暂的开启一个后端服务器, 由后端服务器进行数据申请, 而后在将后果返回给前端

29.AMD,CMD模块化

模块化的开发方式能够进步代码复用率,不便进行代码的治理。通常一个文件就是一个模块,有本人的作用域,只向外裸露特定的变量和函数。目前风行的js模块化标准有CommonJS、AMD、CMD以及ES6的模块零碎

1、AMD推崇依赖前置,在定义模块的时候就要申明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都反对对方的写法

AMD和CMD最大的区别是对依赖模块的执行机会解决不同,留神不是加载的机会或者形式不同

30.报表绘图类的框架

highcharts http://www.highcharts.com/

jscharts http://www.jscharts.com/

AdminLTE http://adminlte.la998.com/

31.库和插件的源代码

库和框架都是一种有别于软件、面向程序开发者的产品模式。

库是将代码汇合成的一个产品,供程序员调用。面向对象的代码组织模式而成的库也叫类库。框架则是为解决一个(一类)问题而开发的产品,框架用户个别只须要应用框架提供的类或函数,即可实现全副性能。

32.函数柯里化是什么 ?

    柯里化(英语:Currying),又称为局部求值,是把承受多个参数的函数变换成承受一个繁多参数(最后函数的第一个参数)的函数,并且返回一个新的函数的技术,新函数承受余下参数并返回运算后果。    具体内容见 https://juejin.im/entry/58b316d78d6d810058678579

33.哪些状况下会造成内存透露 ?

    1)意外的全局变量引起的内存泄露```javascript    function leak () {        leak="xxx"; //leak成为一个全局变量,不会被回收 相当于  window.leak = 'XXX'    }```    2. 闭包能够维持函数内局部变量,使其得不到开释。    3. 没有清理的DOM元素援用    4. 被忘记的定时器或者回调

34.性能优化 ?

1. 定义局部变量.查找局部变量比全局变量要快。2. 不滥用闭包。3. 合并js文件,缩小http申请4. 防止应用for-in循环5. 尽量不必with,eval语句,try-catch的catch子句要审慎应用

35.工作中闭包的应用案例?应用过什么闭包工具库嘛

1. 闭包经典应用场景一:通过循环给页面上多个dom节点绑定事件```javascript        <!DOCTYPE html>    <html>        <head>        <meta charset="UTF-8">        </head>    <body>        <button>Button0</button>        <button>Button1</button>        <button>Button2</button>        <button>Button3</button>        <button>Button4</button>    </body>    </html>    for(var i = 0, len = btns.length; i < len; i++) {        (function(i) {    btns[i].onclick = function() {        alert(i);        }    }(i))    }```2. 封装变量 闭包能够将一些不心愿裸露在全局的变量封装成“公有变量”。3. 闭包应用场景三:连续局部变量的寿命闭包工具库:???

36.301 302如何重定向 ?

    301 redirect: 301 代表永久性转移(Permanently Moved)    302 redirect: 302 代表暂时性转移(Temporarily Moved )     具体来说,301和302状态码都示意重定向,就是说浏览器在拿到服务器返回的这个状态码后会主动跳转到一个新的URL地址,这个地址能够从响应的Location首部中获取(用户看到的成果就是他输出的地址A霎时变成了另一个地址B)——这是它们的共同点。他们的不同在于。301示意旧地址A的资源曾经被永恒地移除(这个资源不可拜访了),搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址;302示意旧地址A的资源还在(依然能够拜访),这个重定向只是长期地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保留旧的网址。

37.暂时性死区 ?

    举例:```javascript    console.log (a)   //因为变量晋升,输入undefined    var a``````javascript    console.log(a)    //报错 ReferenceError: a is not defined    let a```        ES6规定,let/const 命令会使区块造成关闭的作用域。若在申明之前应用变量,就会报错。总之,在代码块内,应用 let 命令申明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。

38.堆和栈

  • 栈(stack):为主动调配的内存空间,他由零碎主动开释。寄存在栈内存中的简略数据段,数据大小确定,内存空间大小能够调配,是间接按值寄存的,所以能够间接拜访。根本的数据类型放在栈中
  • 堆(heap):则是动态分配的内存,大小不定也不会主动开释。援用类型(object)是寄存在堆内存中的,变量实际上是一个寄存在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要依据状况进行特定的调配。

39.箭头函数的this指向

  • 箭头函数默认不会应用本人的this,而是会和外层的this保持一致,最外层的this就是window对象。在多层对像嵌套里箭头函数里this是和最最外层保持一致的

40.深拷贝和浅拷贝的区别

  • 浅拷贝:只复制指向某个对象的指针,而不复制对象自身,新旧对象共享一块内存
  • 深拷贝:复制并创立一个截然不同的对象,不共享内存,批改新对象,旧对象放弃不变。

41.手写一个promise,采纳es5的方面。promise的源码了解

  • var fn=function(resolve, reject){  console.log('begin to execute!');  var number=Math.random();  if(number<=0.5){    resolve('less than 0.5');  }else{    reject('greater than 0.5');  }}var p=new Promise(fn);p.then(function(data){  console.log('resolve: ', data);}, function(data){  console.log('reject: ', data);})对promise源码的了解:   当咱们运行 var p=new Promise(fn) 这条语句的时候,fn函数就曾经执行了,然而,p.then这个办法是在前面才定义了resolve和reject,那么为何fn函数可能晓得resolve和reject函数是什么呢?换句话说,resolve和reject函数是如何回到过来,呈现在先执行的fn函数当中的呢?要解决这个问题,次要使用的就是setTimeout这个办法,来提早fn当中resolve和reject的执行。咱们晓得js是单线程+音讯队列,必须等主线程代码执行结束能力开始执行音讯队列当中的代码。因而,会首先执行then这个办法,给外面两个参数赋值。    退出状态:pending, resolved, rejected在Promise标准当中,规定Promise只能从初始pending状态变到resolved或者rejected状态,是单向变动的,也就是说执行了resolve就不会再执行reject,反之亦然。并在必要的中央进行判断,避免反复执行。function MyPromise(fn) {  this.value;  this.status = 'pending';  this.resolveFunc = function() {};  this.rejectFunc = function() {};  fn(this.resolve.bind(this), this.reject.bind(this));}MyPromise.prototype.resolve = function(val) {  var self = this;  if (this.status == 'pending') {  //判断状态    this.status = 'resolved';    this.value=val;    setTimeout(function() {      self.resolveFunc(self.value);    }, 0);  }}MyPromise.prototype.reject = function(val) {  //判断状态  var self = this;  if (this.status == 'pending') {    this.status = 'rejected';    this.value=val;    setTimeout(function() {      self.rejectFunc(self.value);    }, 0);  }}MyPromise.prototype.then = function(resolveFunc, rejectFunc) {  this.resolveFunc = resolveFunc;  this.rejectFunc = rejectFunc;}    链式调用:要实现链式调用,then办法的返回值也必须是一个Promise对象,这样能力再次在前面调用then。
## 42.async与promise的区别:- 在函数前有一个关键字`async`,`await`关键字只能在应用`async`定义的函数中应用。任何一个`async`函数都会隐式返回一个`promise`,并且promise resolve 的值就是 return 返回的值 - 不能在函数结尾应用`await`- Async 函数的实现最简洁,最合乎语义,简直没有语义不相干的代码。- Promise 的写法比回调函数的写法大大改良,然而一眼看上去,代码齐全都是 Promise 的 API(`then`、`catch`等等),操作自身的语义反而不容易看进去。## 43.async是promise裸露进去的语法糖?- async函数就是generator函数的语法糖## 44.箭头函数与function的区别?**(1) 箭头函数与function定义函数的写法:**

//function

function fn(a, b){    return a + b;}//arrow functionvar foo = (a, b)=>{ return a + b };
**(2) this的指向:**应用function定义的函数,this的指向随着调用环境的变动而变动的,而箭头函数中的this指向是固定不变的,始终指向的是定义函数的环境。**(3) 构造函数**function是能够定义构造函数的,而箭头函数是不行的。**(4) 变量晋升**因为js的内存机制,function的级别最高,而用箭头函数定义函数的时候,须要var(let const定义的时候更不用说)关键词,而var所定义的变量不能失去变量晋升,故箭头函数肯定要定义于调用之前!## 45.箭头函数中没有this对象,this是最近的this(1) 因为箭头函数不绑定this, 它会捕捉其所在(即定义的地位)上下文的this值, 作为本人的this值(2)办法的箭头函数this指向全局window对象,而一般函数则指向调用它的对象,箭头函数没有this## 46.箭头函数能够作为构造函数吗?因为箭头函数没有本人的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而扭转,所以箭头函数不能作为构造函数应用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!## 47.箭头函数代替arguments的办法?箭头函数没有本人的arguments对象。在箭头函数中拜访arguments实际上取得的是外层部分(函数)执行环境中的值。能够在箭头函数中应用rest参数代替arguments对象,来拜访箭头函数的参数列表## 48.解构和负载的场景?1. **解构赋值**,即对某种构造进行解析,而后将解析进去的值赋值给相干的变量,常见的有数组、对象、字符串的解构赋值等   - 数组解构     只有等号两边的模式雷同,右边的变量就会被赋予对应的值。
 let [foo, [[bar], baz]] = [1, [[2], 3]]; foo // 1 bar // 2 baz // 3  ```
  • 对象构造

    对象的解构与数组有一个重要的不同。数组的元素是按秩序排列的,变量的取值由它的地位决定;而对象的属性没有秩序,变量必须与属性同名,能力取到正确的值。

    let { bar, foo } = { foo: 'aaa', bar: 'bbb' };foo // "aaa"bar // "bbb"
  • 字符串构造

    字符串被转换成了一个相似数组的对象

const [a, b, c, d, e] = 'hello';a // "h"b // "e"c // "l"d // "l"e // "o"
  1. 负载

49.扩大运算符理解?

  • 概念

    扩大运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。扩大运算符与失常的函数参数能够联合应用,前面也能够搁置表达式,但如果前面是一个空数组,则不产生任何成果。

            let arr = [];        arr.push(...[1,2,3,4,5]);        console.log(arr); //[1,2,3,4,5]        console.log(1, ...[2, 3, 4], 5) //1 2 3 4 5        console.log(...(1 > 0 ? ['a'] : [])); //a        console.log([...[], 1]); //[1]
  • 利用

    1 代替函数的apply办法
    因为扩大运算符能够开展数组,所以不再须要apply办法,将数组转为函数的参数了。

    // ES5 的写法 Math.max.apply(null, [14, 3, 77]) // ES6 的写法 Math.max(...[14, 3, 77])

    2 复制数组

    // ES5 的写法 const a1 = [1, 2]; const a2 = a1.concat();// ES6 的写法 const a1 = [1, 2]; onst a2 = [...a1]; //或 const [...a2] = a1;

    3 合并数组

    // ES5 的写法 [1, 2].concat(more); arr1.concat(arr2, arr3); // ES6 的写法 [1, 2, ...more];[...arr1, ...arr2, ...arr3]

    4 与构造赋值联合

    // ES5 的写法 a = list[0], rest = list.slice(1) // ES6 的写法 [a, ...rest] = list

50.深拷贝的办法?

答:对数组进行深拷贝:

  • for循环
  • slice办法
  • concat办法
  • ES6扩大运算符
    对对象进行深拷贝:
  • for循环
  • 先转换成json在转换成对象
  • ES6扩大运算符

51.扩大运算符的办法进行拷贝,是深拷贝还是浅拷贝?

答:深拷贝

52.set的用法:数组去重。

答:有两种办法:

办法一: Set + Array.from()

var set1 = Array.from(new Set([1,1,2,2,33,'33',44,'44']))

办法二: …[拓展运算符] + Set

var tt  = [...new Set([5,5,6,6,8,])] // 5,6,8

53.es6判断是否是数组:isArray,以及其余判断数组的办法?typeof 检测数组返回值

答:
判断数组办法:

  • 1.用instanceof判断

    应用instanceof运算符能够分辨数组和对象,能够判断数组是数组。

  • 2.用constructor判断

    实例化的数组领有一个constructor属性,这个属性指向生成这个数组的办法。
    当constructor属性被批改之后,就无奈用这个办法判断数组是数组了

  • 3.用Object的toString办法判断

    toString办法将会返回"[object type]",其中的type代表的是对象的类型,依据type的值,咱们就能够判断这个疑似数组的对象到底是不是数组了

  • 4.用Array对象的isArray办法判断
    isArray办法返回true,当参数不为数组的时候,isArray办法返回false
typeof 检测数组返回值typeof是javascript原生提供的判断数据类型的运算符,它会返回一个示意参数的数据类型的字符串

54.数组去重的办法?

答:

  • 利用ES6中的Set
  • 利用for嵌套for,而后splice去重(ES5中最罕用)
  • 利用indexOf去重
  • 利用sort()
  • 利用includes
  • 利用hasOwnProperty
  • 利用filter
  • 利用递归去重
  • 利用Map数据结构去重
  • 利用reduce+includes

55.数组中呈现反复数字的反复统计?

思路:

    //统计一个数组中有多少个不反复的单词:    // 不必reduce时:     var arr = ["apple","orange","apple","orange","pear","orange"];     function getWordCnt(){         var obj = {};         for(var i= 0, l = arr.length; i< l; i++){             var item = arr[i];             obj[item] = (obj[item] +1 ) || 1;         }         return obj;     }    console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}    // 用reduce时:     var arr = ["apple","orange","apple","orange","pear","orange"];     function getWordCnt(){         return arr.reduce(function(prev,next){             prev[next] = (prev[next] + 1) || 1;             return prev;         },{});     }     console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}

56.数组常见的api

  • 数组api又叫利用程序接口,函数办法
  • 常见api

    1. arr.push():数据增加 - 在数组尾部增加元素
      push办法一次可增加单个或多个元素到数组末端,也能够增加数组
      数组名.push("元素1","元素2",...)
    2. arr.pop():数据更新 - 删除数组的最初一个元素
      pop办法的作用是移除数组开端的一个元素。把数组长度减1,并且返回它的删除值,如果数组为空,则pop()不扭转数组,返回undefind
      数组名.pop()
    3. arr.concat():连贯两个或更多的数组,并返回后果。
    4. arr.join():字符连贯
      若不想要任何连接符,则括号中用空字符即可。
      数组名.join("连接符")
    5. arr.reverse():颠倒数组中元素的程序。
    6. arr.shift():删除数据 - 移除数组顶端的元素
      shift办法与pop相同,移除数组的第一个元素并将其返回。该办法执行后,数组剩下的元素向前挪动,下标索引号从新调整从0开始。
      数组名.shift()
    7. arr.unshift():增加数据 - 在数组头部增加元素
      nshift办法与push办法正好相同,是将元素插入数组的首部。一次能够插入单个或多个元素,所有元素按程序插入,操作实现后返回新数组的援用
      数组名.unshift("元素1","元素2",...)
    8. arr.slice():生成特定数据 - 获取数组中的一部分元素
      slice办法的作用是抽取数组的一段元素,抽取指定下标索引区间中的元素作为新数组返回
      数组名.slice(start,end)
      注:splice是间接批改原数组,而slice不会批改原数组。
    9. arr.sort():对数组的元素进行排序
    10. arr.splice():更新挪动数据 - 删除、替换或插入数组元素
      splice办法的作用是,从一个数组中移除一个或多个元素。剩下的元素组成一个数组,移除的元素组成另一个数组并返回它的援用。同时,原数组能够在移除的开始地位处顺带插入一个或多个新元素,达到批改替换数组元素的目标。这个操作成果通常称为接合
      数组名.splice(start,deleteCount,item1,item2,...)
      参数阐明:
      start:必选项,示意从数组中剪切的起始地位下标索引号。
      deteleCount:必选项,示意从数组中切取的元素个数。
      item:可选项,示意切取时插入原数组切入点开始出的一个或多个元素。
    11. arr.indexof():查找元素对应下标
    12. arr.forEach():数组遍历
    13. arr.filter():数组遍历,将返回的值新建成一个新数组
    14. arr.map():遍历数组,间接操作数组,返回一个新数组
    15. arr.reduce():数组归并

57.数组中sort的用法。sort的返回值?没有传比拟函数的比拟?

用法:对数组的元素进行排序
arr.sort()间接操作原有数组,返回原有数组,当没有传比拟函数的话不会按大小排序,而是按程序排序

    var arr = [22,12,3,43,56,47,4];    arr.sort();    console.log(arr); // [12, 22, 3, 4, 43, 47, 56]    arr.sort(function (m, n) {    if (m < n) return -1    else if (m > n) return 1    else return 0    });    console.log(arr); // [3, 4, 12, 22, 43, 47, 56]

58.canvas与webGL的区别

- 概要  Canvas 位图,是须要本人画点的白板;   WebGL 3D位图,是基于 Canvas 的 3D 框架。- 用处  Canvas 实用于位图,高数据量高绘制频率(帧率)的场景,如动画、游戏;  WebGL 次要用来做 3D 展现、动画、游戏。- canvas毛病:  - 只能绘制2D图像,临时不反对3D图像。  -canvas绘制图形出并非能够间接操作的dom对象。如果要对其进行相似dom的操作,例如增加属性等等,比拟麻烦(这就是为什么必须应用类库)。- canvas长处:  - 因为canvas绘图不会给每个点生成对象,所以绘制速度快,耗费内存少。(这点次要是绝对于SVG,VML技术而言)  - 兼容性较好。除了IE6,其余浏览器都能够反对。(IE7,8须要载入扩大JS,究竟还是能用的)- webGL   是一项应用JavaScript实现3D绘图的技术,浏览器无需插件反对,Web开发者间接应用js调用相干API就能借助零碎显卡(GPU)进行编写代码从而出现3D场景和对象。

59.BOM对象与DOM对象的区别?实现由BOM对象还是先有DOM对象

`BOM:浏览器对象模型(Brower Object Model),是用于操作浏览器而呈现的API,BOM对象则是Javascript对BOM接口的实现。BOM提供了独立于内容的、能够与浏览器窗口进行交互的对象构造。通过BOM对象能够拜访浏览器性能部件和属性。BOM中代表浏览器窗口的window对象是Javascript顶层对象,其余BOM对象均为window对象的子对象。被作为window对象的属性来援用。其余BOM对象都是在window对象中进行操作。DOM 是文档对象模型,比方 html 是树结构的,操作 dom 就是操作这颗树:DOM:文档对象模型(Document Object Model),是W3C定义的一套用于解决HTML和XML文档内容的规范编程接口API。javascript实现DOM接口的对象对应的是document对象,JS通过该对象来对HTML/XML文档进行增删改查。DOM定义了HTML和XML的逻辑构造,将整个页面划分成由档次节点形成的文档,以树的模式来展示,如下面那张图所示。在BOM和DOM构造档次图中,document对象属于window对象,所以DOM也能够看作是BOM的一部分`