前端基础八股文—疑难点

109 阅读2分钟

1.Javascript篇

1.let、const、var的区别

  1. 块级作用域:let与const有块级作用域,即变量的作用域只会在{}内。
  2. 变量提升:let、const定义的变量不会有变量提升现象,在声明前使用会报错;而var声明的变量会发生变量提升现象(如果是在全局作用域下,var声明的变量会被挂载到window下),所以即使在声明前使用也不会报错。

2.箭头函数和普通函数的区别

  1. 箭头函数是没有自己的this的,这也是它为什么无法被当作构造函数的原因,因为在new一个新对象的时候,需要将构造函数的this指向新对象(这个过程是将构造函数的属性和方法赋给新对象),它的this是继承它当前上下文且不会被call、apply、bind函数更改。
  2. 普通函数中的this会首先从自己当前作用域中寻找指定变量,如果没找到则,根据作用域链的规则,将指针指向向上级作用域中,重复上述流程,直到知道指定变量或者指针移到全局作用域链。

例题1:

var id = "GLOBAL!!!";
var obj = {
  id: "TOP",
  a: () => {
    return this.id;
  },
  b: function () {
    return this.id;
  },
  objj: {
    id: "MIDDEL",
    a: () => {
      return this.id;
    },
    b: function () {
      return this.id;
    },
  },
};
console.log(1, obj.a());
console.log(2, obj.b());
console.log(3, obj.objj.a());
console.log(4, obj.objj.b());

例题2: 修改了全局作用于下id的声明关键字。

const id = "GLOBAL!!!";
var obj = { 
    id: "TOP", 
    a: () => {
      return this.id;
    },
    b: function () {
      return this.id;
    }, 
    objj: {
      id: "MIDDEL",
      a: () => {
        return this.id;
      },
      b: function () {
        return this.id;
      }
  }
}; 

console.log(1, obj.a());
console.log(2, obj.b());
console.log(3, obj.objj.a());
console.log(4, obj.objj.b());

例题1的答案: image.png

首先,调用obj.a()方法,obj.a是箭头函数,所以一旦声明,this固定指向为全局作用域,而当前作用域声明并挂载了id,所以返回值GLOBAL!!!。其次,调用obj.b(),obj.b是普通函数,所以会在自己的作用域中寻找id,发现值TOP,返回TOP。再然后,同理调用箭头函数obj.objj.c(),从全局作用域找到id,返回值GLOBAL!!!,最后调用普通函数obj.objj.c(),从当前作用域链中寻找变量id,发现并返回值MIDDLE

例题2的答案: image.png

2和4的原理和例题1相同,其中1和3返回undefined的原因是因为const声明的变量不会发生变量提升,不会挂载到全局作用域中,所以this无法从全局作用域中找到指定变量。需要注意的是,定义对象的大括号{}是无法行程一个单独的执行环境的,它依旧是处于全局执行环境中。