面试题

总结一些平时在电脑上写的很溜,但是在面试白班测试总是写不好的一些面试题吧!个人不喜欢白板测试,没有那种敲代码的感觉,并且一些细节也不好把控。

1 编写函数sum(2,3)和sum(2)(3)都能得到5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function sum(){
var cache = arguments[0];
if(!arguments){
return ;
}else if(arguments.length === 1){
return function(num){
return cache+num
};
}else if(arguments.length === 2 ){
return arguments[0]+arguments[1];
}
}
console.log(sum(2,3));
console.log(sum(2)(3));

2 url地址的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var url =' http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e';
function getJson (url){
var flag = url.indexOf('?')+1;
console.log(flag);
var res = url.slice(flag);
console.log(res);
var arr = res.split('&');
var Json = {};
for(var i = 0 ; i <arr.length ;i++){
var temp = arr[i].split('=');
console.log(temp);
console.log(temp[0]);
console.log(temp[1]);
Json[temp[0]] = temp[1];
}
return Json ;
}
getJson(url);
console.log(getJson(url));

3 运算符的操作,主要是 + ++ - && || 以及运算符的优先级的问题(感兴趣可以看看我这篇总结)

这里在回顾一下

+ 运算符

  • 如果一个运算数是字符串,那么这个运算环境就是字符串环境,另外一个运算数,不论是布尔类型,数字类型,undefined null NaN 以及数组,对象都会转化为字符串,然后进行字符串拼接
  • 如果一个运算数是数字,另外一个运算数是布尔类型,会将布尔类型转化为数字
  • 如果一个运算数是数组或者对象,会将数组或者对象转化为原始数据类型(调用toString方法),然后进行运算(一般也就是将数组或者对象转化为字符串,所以后续也是进行的字符串的拼接)

- 运算符

  • -运算符提供的是一个数字运行环境,会将字符串,布尔类型的值转化为数字(Number和parseInt方法),如果转化失败则返回NaN
  • 如果有运算数是对象或者数组,会先调用对象或者数组的toString方法,然后调用Number和parseInt方法转化为数字,进行数字的运算,如果转化失败则返回NaN
1
2
3
4
5
6
7
8
9
10
11
12
console.log(true + false);//1
console.log({}+true);//[object Object]true
console.log([]+true);//true
console.log(true + []);//true
console.log(1 + [] + 1 );//11
console.log(typeof(1 + []));//string
console.log([].valueOf());//[]
console.log([] - true);//-1
console.log({} - true);//NaN
console.log(1 - [] - 1 );//0
console.log('2' - false);//2
console.log("2" - undefined);//NaN

4 有关闭包的一个测试 如何实现点击每个 li 输出其 index 值,注册事件之后,触发事件,然后事件监听器函数就会执行

1
2
3
4
5
<ul id = 'test'>
<li>ee</li>
<li>ee</li>
<li>ee</li>
</ul>
1
2
3
4
5
6
7
8
var liObj = document.getElementById('test').children;
console.log(liObj);
for(var i = 0 ; i < liObj.length ; i++){
liObj[i].onclick = function(){
console.log(i);
}
}
//这个是不行的 注册事件之后,当点击的时候,i的值已经是 3 的,所以每次输出都是3

利用闭包 返回一个函数作为listener

1
2
3
4
5
6
7
for(var i = 0 ; i < liObj.length ; i++){
liObj[i].onclick = (function(n){
return function(){
console.log(n);
}
})(i+1)
}

还有一个简单的实现思路就是 给每一个li设置一个属性即可

1
2
3
4
5
6
7
for(var i = 0 ; i < liObj.length ; i++){
liObj[i].setAttribute('index',i+1);
liObj[i].onclick = function(){
console.log(this);
console.log(this.getAttribute('index'));
}
}

5 类数组转化为数组 apply,call 第一个参数改变函数的this指向,第二个参数表示传入函数的参数

1
2
3
4
5
6
7
8
var arrayLike = {
0 : "hai",
1 : "Jhon",
2 : "nam",
length : 3
}
var ret = Array.prototype.slice.call(arrayLike,0);
console.log(ret);

6 数组的去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var arr = [1,2,3,4,5,5,3,1,8,9];
Array.prototype.unique = function(){
var arr = [this[0]];
for(var i = 0 ; i < this.length ; i++){
//如果新数组中没有当前比较项,则将当前比较项加入新数组
var flag = true ;
for(var j = 0 ; j < arr.length ; j++){
if(this[i] === arr[j]){
flag = false;
break ;
}
}
if(flag == true){
arr.push(this[i]);
}
}
return arr ;
}
console.log(arr.unique());

7 字符串的去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Array.prototype.unique = function(){
var arr = [this[0]];
for(var i = 0 ; i < this.length ; i++){
//如果新数组中没有当前比较项,则将当前比较项加入新数组
var flag = true ;
for(var j = 0 ; j < arr.length ; j++){
if(this[i] === arr[j]){
flag = false;
break ;
}
}
if(flag == true){
arr.push(this[i]);
}
}
return arr ;
}
var str = 'aaasdafafaasdddfggh';
function detRep(str){
var arr = str.split('');
var newArr = arr.unique();
var newStr = newArr.join('');
return newStr ;
}
console.log(detRep(str));

8 break和continue

1
2
3
4
5
6
7
8
9
//break会直接跳出循环
var iNum = 0;
for (var i=1; i<10; i++) {
if (i % 5 == 0) {
break;
}
iNum++;
}
alert(iNum);//4
1
2
3
4
5
6
7
8
9
//continue会退出当前这一次的循环,进行下一次循环,后面表达式都不会在执行
var iNum = 0;
for (var i=1; i<10; i++) {
if (i % 5 == 0) {
continue;
}
iNum++;
}
alert(iNum);//8

9 + - 运算符以及NaN undefined

1
2
3
4
5
6
7
8
9
var a;//undefined
var b = a * 0;//NaN
console.log(b * 2 + "2" - 0 + 4);
if (b == b) { //false
console.log(b * 2 + "2" - 0 + 4);
} else {
console.log(!b * 2 + "2" - 0 + 4);
}
//输出26

主要考察以下知识点

  • 带有undefined的基本运算结果返回NaN : undefined*2 undefined+2等
  • 带有NaN的比较运算符结果返回false; NaN == NaN 也是false
  • x 和+ 运算中数字和布尔类型的运算,会将布尔类型转化为数字在进行运算 !b*2 = 2
  • 带有字符串的 + 性环境中,会将另外一个运算数转化为字符串,然后进行字符串的拼接 !b*2+’2’ : ‘22’;
  • - 性环境中,会将字符串,如果一个是字符串,另外一个是数字会将字符串转化为数字(即使两个都是字符串也会将两个都转化为字符串) ‘22’-0 : 22 数字类型的22
  • 如果没有 - 0 这步运算,那么返回的结果将是 字符串 ‘224’;

10 日期操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//假设今天是 2017-4-12
var date = new Date();
console.log(date.getFullYear());//2017
console.log(date.getMonth());//3 注意Month获取的月份是从0开始的
console.log(date.getDate());//12
var year = date.getFullYear();
var Month = date.getMonth()+1 ;
var day = date.getDate();
Month = Month < 10 ? '0'+Month : Month ;
day = day < 10 ? '0'+day : day ;
var res = year + '-'+ Month + '-'+day;
console.log(res);

11 实时获取页面中的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ul>
<li>Item</li>
<li>1</li>
<li>1</li>
<li>Item</li>
<li>Item</li>
</ul>
<script>
var items = document.getElementsByTagName('li');
for(var i = 0; i < items.length; i++){
if(items[i].innerHTML == '1'){
console.log(i);
items[i].parentNode.removeChild(items[i]);
console.dir(items);//items已经剩下四个了而此时的索引值并没有改变
}
}
</script>

执行后

1
2
3
4
Item
1
Item
Item

这里需要注意的一点是 DOM获取的元素 items是实时更新的;

12 变量声明提升 函数声明优先于变量声明

1
2
3
4
console.log(a);//是一个函数
var a = 3;
function a(){}
console.log(a);////3