2019前端面试题总结

常考的数组方法:
(1)、arr.join():将数组元素串起来组成字符串
(2)、arr.sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。
(3)、arr.reverse():反转数组项的顺序。
(4)、arr.concat():将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。
(5)、arr.slice():
返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。 如果有参数是负数,则把负数项加数组的长度。 例如:arr.slice(-1,-4)==arr.slice(arr.length-1,arr.length-4);
(6)、arr.splice():
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。

插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。

splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。(不会生成一个副本,而是会直接改变原数组,并且会返回一个新的数组)

(7)、indexOf()和 lastIndexOf():(返回索引值)
indexOf(从左向右):
一个参数:要查找项
两个参数:第一个参数表示要查找的项,第二个表示要查找的开始索引。查询不到会返回-1
lastIndexOf(从右向左):但是数索引的时候还是要从左往右数
(8)、forEach():
对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x,index,b){
console.log(x,index,b);
})
(9)、map():
指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。这个方法有返回值。
(10)、filter():
“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
(11)、every()和some()
every:对数组的每一项都满足条件才返回true;
some:对数组的其中一项满足条件就返回true;
详情参考:js数组方法大全

1、随机打乱一个字符串

//随机打乱一个字符串
    var  str="idfjdifndi";
    function suffle(str) {
        var arr=str.split("");//把字符串变成数组
        var len=arr.length;
        for(var i=0;i<len;i++){
            var randomIndex=Math.floor(Math.random()*len);//随机生成一个下标
            var itemIndex=arr[randomIndex];
            arr[randomIndex]=arr[i];
            arr[i]=itemIndex;
        }
        return arr.join().replace(/,/g,"");//替换掉生成的字符串中的逗号。
    }

    console.log(suffle(str)); //typeof:string

二、递归实现1x2+3x4+5x6+…+(n-1)n

//注意审题是递归实现,而不是用for循环
 function digui(n) {
        if(n==1){
            return 1;
        }
        return n*digui(n-1);
    }

    console.log(digui(5));

三、打印题:

var arr1=new Array(6);//[ , , , , , ]长度为6的空字符串
var arr2=new Array(6,6);//[6,6]

 for(var i=0;i<10;i++){
        setTimeout(function () {
            console.log(i)
        },i*1000)
    }//10个10

for(let i=0;i<10;i++){
        setTimeout(function () {
            console.log(i)
        },i*1000)
    }//0,1,2,3,4,5,6,7,8,9

 var foo=1;
    (function () {
        foo=2;
        function foo() {
        }
        console.log(foo);//2

    })();
    console.log(foo);//1

Array.isArray(Array.prototype)//true
console.log(Array.prototype)//typeOf:Object
==只有Array.prototype是数组,其他是对象==


   [1,2,3].map(parseInt)//[1, NaN, NaN]

四、逆序一个字符串

  function reserveStr(str) {
        return str.split('').reverse().join('');
    }
    console.log(reserveStr("nice"));

五、输出字符串中没有重复的项

//比较愚蠢的办法
  var str='abcabagmmfd'//输出cgfd
    function noRepeatString(str){
        var arr=str.split('');
        var arr1=[];
        var arr2=[];
        var arr3=[];
        var arr4=[];
     /*   arr.forEach(function (obj,n,m) {
            //console.log(obj);
            if(arr1.indexOf(obj)==-1){
                t++;
                console.log(t);
                arr1.push(obj);
            }
        });*/
        for(var i=0;i<arr.length;i++){
           if(arr1.indexOf(arr[i])==-1){
               arr1.push(arr[i]);
           }
        }

        for(var i=0;i<arr1.length;i++) {
            var t=0;
            for (var j = 0; j< arr.length; j++) {
                if (arr1[i] == arr[j]) {
                    t++;
                    if(t>1){
                        arr2.push(arr1[i])
                    }
                }
            }
        }

        for(var i=0;i<arr2.length;i++){
            if(arr3.indexOf(arr2[i])==-1){
                arr3.push(arr2[i]);
            }
        }
        console.log(arr3);

        for(var i=0;i<arr1.length;i++){
            if(arr3.indexOf(arr1[i])==-1){
                arr4.push(arr1[i]);
            }
        }

        return arr4.join('');
    }
    console.log(noRepeatString(str));
//比较优秀的方法
var str='abcabagmmfd';
function noRepeatStr2(str){
	var json={};
	var arrBase=str.split('');
	var result='';
	for(var x in arrBase){
	    if(json[arrBase[x]]){
	        json[arrBase[x]]++;
	    }else{
	        json[arrBase[x]]=1;
	    }
	}
	for(var s in json){
	    if(json[s]==1){
	        result+=s
	    }
	}
}
console.log(noRepeatStr2(str));

六、斐波那契数列的前n项

一个数列:1、1、2、3、5、8、13、21、34、……求出第100个数是多少?

    function fib(num) {
        var arr = [];
        if(num == 1){
            return arr = [1];
        }else if(num == 2){
            return arr = [1,1];
        }else{
            arr = [1,1];
            var a=1;
            var b=1;
            var c=2;
            var arrlen =arr.length;
            for(var i=2;i<num;i++){
                arr.push(c);
                a=b;
                b=c;
                c=a+b;
            }
            return arr[num-1];

        }

    }

console.log(fib(100));

//2019/03/09再更!!!!

七、 ES6模块化如何使用?开发环境如何打包?

如何使用:
1:每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象;
2:每一个模块内声明的变量都是局部变量, 不会污染全局作用域;
3:模块内部的变量或者函数可以通过export导出;
4:一个模块可以导入别的模块
如何打包:
首先生成项目目录:- app -源代码目录

  • main.js -webpack的读取文件的主入口
  • source -存放需要webpack处理的文件和代码
  • build -webpack配置文件
  • node_modules -node模块安装目录
  • public -打包时,默认将文件生成到public目录
  • .babelrc -babel的配置文件
  • package.json -node配置文件

八、、Class和普通构造函数的区别:

  1. Class 在语法上更加贴合面向对象的写法
  2. Class在实现继承上更加易读、易理解
  3. 更易于写java等后端语言
    4.本质还是语法糖,使用prototype

九、 Promise的基本使用和原理:

基本使用(代码):
function 函数名(){
return new Promise(function(resolve, reject) {
// … some code
if (/* 异步操作成功 */){
resolve(value); // 异步操作成功时调用,把结果作为参数传递出去
} else {
reject(error); // 异步失败时调用,把错误作为参数传递出去
}

}).then();

}
原理:
构造函数Promise接受一个函数resolver,可以理解为传入一个异步任务,resolver接受两个参数,一个是成功时的回调,一个是失败时的回调,这两参数和通过then传入的参数是对等的。
其次是then的实现,由于Promise要求then必须返回一个promise,所以在then调用的时候会新生成一个promise,挂在当前promise的_next上,同一个promise多次调用都只会返回之前生成的_next。
由于then方法接受的两个参数都是可选的,而且类型也没限制,可以是函数,也可以是一个具体的值,还可以是另一个promise。

十、总结一下ES6其他常用功能:

  1. Default Parameters(默认参数):
    //运用ES6的默认参数
    function sayHello2(name=‘tom’){ //如果没有传这个参数,才会有默认值, console.log(Hello ${name}); //模板字符串
    }
  2. Template Literals (模板文本)
  3. Multi-line Strings (多行字符串)
  4. Destructuring Assignment (解构赋值):
    直接返回一个数组,然后数组中的值会自动被解析到对应接收该值的变量中:
    function getVal() {
    return [1, 2];
    }
    var [x,y] = getVal(); //函数返回值的解构
    console.log(‘x:’+x+’, y:’+y); //输出:x:1, y:2
  5. Enhanced Object Literals (增强的对象文本)
  6. Arrow Functions (箭头函数)
  7. Promise
  8. Block-Scoped Constructs Let and Const(块作用域构造Let and Const)
  9. Classes(类)
  10. Modules(模块)

十一、什么是单线程?和异步有什么关系?

单线程:单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
和异步的关系:js是单线程的,是因为他的宿主环境-浏览器是多线程的,通过事件驱动才使js有了异步属性,浏览器会为js创建一个主线程来执行任务(函数),但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行;但前端的某些任务是非常耗时的(网络请求,定时器等),所以浏览器维这些任务另外开辟了新的线程并且这些任务使异步的;所以单线程和异步是必然的关系。

十二、解决JS异步的方案有哪些?

1、callback
2、Promise’
3、Generator
4、async/await

十三、diff算法

JS在渲染页面的时候会先生成VNode(Js对象),这个js对象中包含节点的基本属性如标签名,属性,子元素,文本信息等,状态变更的时候会从新构建这个JavaScript对象,然后呢,用新渲染的对象和旧的对象去对比, 记录两棵树的差异(patches),记录下来的就是我们需要改变的地方。

十四、在一个字符串中中匹配网址

	var str="我就是喜欢https://www.httalk.top找出https://www.httalk.xin/blog/index.html来啊!";
    var reg=/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/g;
    console.log(str.match(reg));//返回一个所有匹配项的数组

你可能感兴趣的:(JavaScript)