js 常犯错误

总结自己常犯错误的点,后续常常改正,让自己的基础知识更扎实

一、 数据类型

'' || null || 3 || 4 // 3
4 && 5 && null && '0'// null  过程为:5 && null && '0' -> null && '0' -> null
[1] + [2] // "12"
1 + {} // "1[object Object]"
'1' + [] // "1"
2 + null // 2


1
2
3
4
5
6
7
8
  1. 请指出下面题目是否会输出内容
if([]){console.log(1)}//1
if([] == false){console.log(1)}//1
if({} == false){console.log(1)}//无
if([1] == [1]){console.log(1)}//无
1
2
3
4

【分析】

  • if(x) 判断x是否为空,如果为空,则为false,否则为true
  • if([] == false) 首先将x与k都转成相同的类型,[] -> 0 false -> 0 因此为true
  • [1] == [1] 不相等,因为指针不同
const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}
if (a == 1 && a == 2 && a == 3) {
  console.log('hello world!');
}

// 会输出hello world!
1
2
3
4
5
6
7
8
9
10
11

分析:详解关于隐式转换

  1. 函数与变量声明提升
(function(){
  //变量提升,function 比 var 优先级更高
  function a(){var a = 1;}
  console.log(a);
  a();
  var a = function(){var a = 2;};//已声明过的变量再次声明会被忽略,不会再提升了
  console.log(a);
  a();
})();
1
2
3
4
5
6
7
8
9
  1. 箭头函数this
this.a = 20;
var test = {
    a: 40,
    init: () => {
      console.log(this.a);
      function go(){
        this.a = 60;
        console.log(this.a);
      }
      go.prototype.a = 50;
    return go;
  }
};
var p = test.init();//20
p();//60
new (test.init());//60 60
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

二、 递归

  1. 如果数组列表太大,以下递归代码将导致堆栈溢出。你如何解决这个问题,仍然保留递归模式
var nextListItem = function() {
  var item = list.pop();
  if (item) {
    nextListItem();
  }
};
1
2
3
4
5
6

解决:

var nextListItem = function(){
var item = list.pop();
if (item) {
     setTimeout( nextListItem, 0);
  }
}
1
2
3
4
5
6

分析:

首先浏览器处理js为单线程,程序执行在主队列中,主队列同时还要处理UI及其他操作;本题为递归调用,它占用了内存中的堆栈,这样,直到item为undefined时,才会释放内存,因此会造成内存溢出,

而使用setTimeout,是将递归调用通过事件循环来处理,而不是调用堆栈

三、 作用域

function foo(a){
  a = {v:5};
};
var a = {k:30};
foo(a);
alert(a.v); // undefined

foo(a){
  a.v = 5
}
var a = {k:30}
foo(a)
alert(a.v) // 5
1
2
3
4
5
6
7
8
9
10
11
12
13

分析:

第一个题目,为按值传递 第二个题目,为按引用传递, 注意点,foo(a) 这里面的a为一个作用域

【思考题】请简述参数传递一共几种方式,分别是什么,并简述它们的区别?

分为2种,按值传递,按引用传递

按值: 可以理解为克隆的副本,在函数内部对其操作,与外部无关

按引用: 因为公用的是同一个引用地址(指针),因此函数内部对其操作,会影响外部