最近遇到的问题总结(数组去重、扁平化处理、sort 以及Promise等等)

开头,首先谈一谈前几天去 携程 的面试吧,刚开始笔试的题目,坦白说都是比较简单的,开始大概是十道选择题,都是基础的理论题,通常基础还能够的人确定都会写!接下来是几道程序的运行题,主要考一些变量提高,闭包形式的运行结果,this指向问题,随便举几个例子吧:面试

1. 首先说的这个题目其实至关经典的,不少地方都遇到过:

function Foo() {
    var i = 0;
    retunr function() {
        console.log(i++);
    }
}
var f1 = Foo(), f2 = Foo();
f1(); f1(); f2();
复制代码

其实这一题感受就是考虑变量提高吧,输出结果依此就是 0 1 0;简单来讲就是,第一次执行f1() 函数后,函数内部的 i 值就发生了改变,下一次执行f1(), i在原来的基础上作了++ , 因此就输出了 1,当执行f2函数的时候,从新执行了一次函数,因此输出仍是原来的0, 我就是这么理解的,因此很少作解释啦....数组

2. 函数内部的变量问题:

var bb = 5;
function aa(bb) {
    bb = 10;
    alert(bb);
}
aa(bb);
alert (bb);
输出的结果分别就是 10 和 5;
复制代码

刚开始其实我考虑了一下,函数执行输出结果在函数内部改变,因此输出为10 确定没问题,其实不少人在这个地方考虑的是函数内部的值改变,会不会将外部的值也改变,参考一下函数变量的做用域,你就会发现其实并无改变!因此alert 的仍是 bb = 5;promise

3. 记忆中还考了一个obj 中的 this 指向问题,也很经典其实!简单写一个相似的吧:

var name =  'john';
var obj = {
    name: 'Bob',
    prop:{
        name: 'joyjoy',
        getName:function() {
            return this.name;
        }
    }
}
console.log(obj.prop.getName());         // joyjoy
var test = obj.prop.getName;
console.log(test());           //   john;
复制代码

其实,对this 指向去研究过的童鞋,应该很好理解这个问题,第一次去直接访问obj.prop.getName,那么做用域很显然就是在obj.prop 这个对象中,那么确定会直接访问这个对象中的name,因此打印的是joyjoy; 当实例化一个新的function的时候,test只表明对象中的一个函数,因此执行的时候会直接去需找所定义的name这个变量,因此确定是全局变量john 了;bash

二轮的时候,我一脸懵逼的去了,他们的CTO吧应该是,写了一堆原生的问题,如下面两个常常碰见的举例:

一. 数组去重:

1.首先最简单的写法:

Array.from(new Set()); 
    可是这种方法通常面试官都不会买帐的,而后我想了另一种方法去实现,以下:
复制代码

2. 新建一个对象,去判断:

例如:闭包

let arr = [1,2,3,4,'4',5,5,6];
let obj = {};
let newArr = [];
for(let i = 0;i<arr.length;i++) {
    if(!obj[arr[i]]) {
        newArr.push(arr[i]);
        obj[arr[i]] = true;
    }
}
// 输出的newArr 为 [1,2,3,4,5,6]
复制代码

经过键值对的形式,也能够实现这个问题,当时面试官质疑了我这种方法,说万一里面number类型,字符串类型都存在,会被默认去重,就像上述数组中的 4 和 '4' 同样;回来想一想确实是的,再仔细想了想,仍是不知道咋解决,因而便再从新想了一个方法: (ps: 下面这个想法,高度紧张,卡住了,由于他依旧没有解决这个问题啊);app

3.双重for 循环去实现:

var arr=[1,2,3,4,4,4,5,5,5,5,5,6];
var resultArr = [];
for(var i = 0;i< arr.length;i++) {
	for(var j = i+1;j<arr.length;j++) {
		if(arr[i] == arr[j]) {
			j = ++i;
		}
	}
	resultArr.push(arr[i]);
}
// 输出 [1,2,3,4,5,6]
复制代码

这个方法内部判断条件,其实能够换成splice 在 原数组上直接修改的,具体的就不介绍啦;dom

想了不少,好像就只有 new Set() 能够区分上面的数值和字符串问题,但我又不了解new Set() 的具体机制和个人第二种方法有啥区别,就很尴尬了;异步

二: 数组的扁平化处理

刚开始说这个的时候,其实我不懂啥意思,而后试探性的问了一下,是否是就是降维,可能脑海深处忽然蹦出来这个思惟逻辑吧,但并无啥卵用,我这个大菜鸟大概都忘了这些东西了,哈哈。。。而后随便写了几行代码,一团糟呢,如今想起来。下面给几个思路:函数

1. 回来想到最简单的方法,用arr.join() 方法去实现这玩意儿;

var arr = [1,2,3,4,[5,6],[7,8,]];
var newArr = Array.from(arr.join());
for (var i = 0;i<newArr.length;i++) {
	if(isNaN(newArr[i])){
		newArr.splice(i,1);
	} 
}
<!--emmm....这就是我想到的最简单的办法啦。。。嘿嘿!-->
复制代码

2. 其实可能面试官更想要的就是网上的那循规蹈矩的三种方法吧: 简单提一下吧

第一种: 双重 for 循环: 
var result = [];
for(var i=0;i<arr.length;i++){
    for(var j=0;j<arr[i].length;j++){
        result.push(arr[i][j]);
    }
}

第二种: 用concat代替内层循环
var result = [];
for(var i=0;i<arr.length;i++){
    result = result.concat(arr[i]);
}

第三种:用apply代替外层遍历
var result = [].concat.apply([],arr);

复制代码

固然了,上面这三个方法就初步实现了简单的二维数组降维,多重数组降维,还须要经过递归的方法去实现的:

一个简单的实现思路:

var arr = [2, 3, [2, 2],
    [3, 'f', ['w', 3]], { "name": 'Tom' }
];
let result = [];
arr.forEach(function(val, index) {
    if(Array.isArray(val)) {
        val.forEach(arguments.callee);
    } else {
        result.push(val);
    }
})
console.log(result);   // 这个就解决了多重数组得降维了....
复制代码

ps: 稍微解释一下 arguments.callee, 首先显而易见得就是 callee 就是arguments 中得一个属性,他是一个指针, 指向拥有arguments 这个对象得函数,经常使用于递归函数,不过如今通常不使用啦!!!!ui

在携程得这段面试,除了这些,还有一些较为原理得原型链啊,闭包啥的,比较底层得知识,显而易见得就是凉凉了啊.... 感受携程常年招人,也不缺人呢!

再说一些别的地方遇到得面试题吧,首先数组和字符串得一大堆用法,就不一一细说了,最想说得就是 sort 排序得功能了:

一: sort 排序:

1. 首先,sort() 方法会对数组元素进行排序,并返回这个数组;可是sort() 在默认不传比较函数的时候,会将数组中得全部元素经过toString() 方法 转化,在进行字符串比较,因此在默认对数字数组进行排序的时候,会出现问题,因此引入了比较函数:

var arr = [22,1,12,45,36]; arr.sort(function(a, b){ return a - b; }) // 默认为升序;相反得若是return b - a; 就是相反得降序;

2.数组得多条件排序,实例以下:
var array = [{id:10,age:2},{id:5,age:4},{id:6,age:10},{id:9,age:6},{id:2,age:8},{id:10,age:9}]; array.sort(function(a,b){
    if(a.id === b.id){
        return b.age - a.age  // 若是id的值相等,按照age的值降序 
    }else{ 
        return a.id - b.id  // 若是id的值不相等,按照id的值升序
    }   
    }) 
    输出结果:
    [{"id":2,"age":8},{"id":5,"age":4},{"id":6,"age":10},{"id":9,"age":6},{"id":10,"age":9},{"id":10,"age":2}]

##### 3. sort 实现乱序(这个方法不太好,就随口提一下): 
    Array.sort(function(){
        return 0.5 - Math.random();
    })

复制代码

二: 在简单的说一下 Promise 操做吧,反正去哪都会被问到.....

promise这个 构造函数 简单的 resolve 、 reject 以及 .all 和 .catch 这几个方法就不详细说了额,写一个简单得demo 去实现图片得资源加载吧...

ps: 首先咱们都知道 .all 和 .race 的区别就 .all 就是判断哪个异步函数执行得慢,就以哪个函数为准去执行回调, 而.race 偏偏相反, 谁执行得快,就以哪个函数为准执行回调!因此咱们就能够写两个函数分别去实现加载图片和显示延时,具体代码以下:
//请求某个图片资源
    function requestImg(){
        var p = new Promise(function(resolve, reject){
            var img = new Image();
            img.onload = function(){
                resolve(img);
            }
            img.src = 'xxxxxx';
        });
        return p;
    }
    //延时函数,用于给请求计时
    function timeout(){
        var p = new Promise(function(resolve, reject){
            setTimeout(function(){
                reject('图片请求超时');
            }, 5000);
        });
        return p;
    }
    
    Promise
    .race([requestImg(), timeout()])
    .then(function(results){
        console.log(results);
    })
    .catch(function(reason){
        console.log(reason);
    });
    
复制代码

遇到得问题还有不少不少啊... 在这条求坑之路中摸索前行,其实蛮难的,加油吧!!!但愿有大神指点额......

相关文章
相关标签/搜索