开头,首先谈一谈前几天去 携程 的面试吧,刚开始笔试的题目,坦白说都是比较简单的,开始大概是十道选择题,都是基础的理论题,通常基础还能够的人确定都会写!接下来是几道程序的运行题,主要考一些变量提高,闭包形式的运行结果,this指向问题,随便举几个例子吧:面试
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, 我就是这么理解的,因此很少作解释啦....数组
var bb = 5;
function aa(bb) {
bb = 10;
alert(bb);
}
aa(bb);
alert (bb);
输出的结果分别就是 10 和 5;
复制代码
刚开始其实我考虑了一下,函数执行输出结果在函数内部改变,因此输出为10 确定没问题,其实不少人在这个地方考虑的是函数内部的值改变,会不会将外部的值也改变,参考一下函数变量的做用域,你就会发现其实并无改变!因此alert 的仍是 bb = 5;promise
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
Array.from(new Set());
可是这种方法通常面试官都不会买帐的,而后我想了另一种方法去实现,以下:
复制代码
例如:闭包
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
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() 的具体机制和个人第二种方法有啥区别,就很尴尬了;异步
刚开始说这个的时候,其实我不懂啥意思,而后试探性的问了一下,是否是就是降维,可能脑海深处忽然蹦出来这个思惟逻辑吧,但并无啥卵用,我这个大菜鸟大概都忘了这些东西了,哈哈。。。而后随便写了几行代码,一团糟呢,如今想起来。下面给几个思路:函数
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....这就是我想到的最简单的办法啦。。。嘿嘿!-->
复制代码
第一种: 双重 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
在携程得这段面试,除了这些,还有一些较为原理得原型链啊,闭包啥的,比较底层得知识,显而易见得就是凉凉了啊.... 感受携程常年招人,也不缺人呢!
var arr = [22,1,12,45,36]; arr.sort(function(a, b){ return a - b; }) // 默认为升序;相反得若是return b - a; 就是相反得降序;
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();
})
复制代码
//请求某个图片资源
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);
});
复制代码