js基础面试必考的知识点

63 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

数据类型与栈堆

基础数据类型都是按值访问,因为我们可以直接操作保存在变量中的实际的值。 引用类型的值都是按引用访问的。在操作对象时,实际上是在操作对象的引用而不是实际的对象。 图片

内存空间与垃圾回收机制

标记清除和引用计数。

执行上下文

运行环境

  • 全局环境:JavaScript代码运行起来会首先进入该环境
  • 函数环境:当函数被调用执行时,会进入当前函数中执行代码
  • eval(不建议使用,可忽略)

变量对象(VO)

变量提升 function声明会比var声明优先级更高一点。

 function test() {
     function foo() {
         return 2;
     }
     var a;
     console.log(a);
     console.log(foo());
     a = 1;
 }
 ​
 test();

活动对象(AO)

进入执行阶段之前,变量对象中的属性都不能访问!但是进入执行阶段之后,变量对象转变为了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。

区别:他们其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。

暂时性死区

 console.log(a);
 let a = 10;

变量定义了,但是没有初始化。.let/const声明的变量,仍然会提前被收集到变量对象中,但和var不同的是,let/const定义的变量,不会在这个时候给他赋值undefined。

作用域与作用域链

作用域是一套规则。而作用域链,则是作用域的具体实现。

作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

词法环境

通俗来说,词法环境就是一套约定好的规则。我们写代码,应该按照这个规则来。JS引擎对JS源码进行词法分析,也是按照这个规则来。

V8引擎是如何工作的

闭包

闭包是一种特殊的对象。

它由两部分组成。执行上下文(代号A),以及在该执行上下文中创建的函数(代号B)。

当B执行时,如果访问了A中变量对象中的值,那么闭包就会产生。

this指向

this的指向,是在函数被调用的时候确定的。 也就是执行上下文被创建时确定的。

在函数执行过程中,this一旦被确定,就不可更改了。

函数中this的指向

在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。如果函数独立调用,那么该函数内部的this,则指向undefined。但是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。

函数

  1. 函数表达式

  2. 函数生命

  3. 匿名函数

  4. 自执行函数

    1.  !function(){}()`,`+function(){}()
      

函数传参

实际上结论仍然是按值传递,只不过当我们期望传递一个引用类型时,真正传递的,只是这个引用类型保存在变量对象中的引用而已。

 var person = {
     name: 'Nicholas',
     age: 20
 }
 ​
 function setName(obj) {  // 传入一个引用
     obj = {};   // 将传入的引用指向另外的值
     obj.name = 'Greg';  // 修改引用的name属性
 }
 ​
 setName(person);
 console.log(person.name);  // Nicholas 未被改变

函数式编程

函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。

纯函数

只要是同样的参数传入,返回的结果一定是相等的。

函数的隐式转换

当我们没有重新定义toString与valueOf时,函数的隐式转换会调用默认的toString方法,它会将函数的定义内容作为字符串返回。

而当我们主动定义了toString/vauleOf方法时,那么隐式转换的返回结果则由我们自己控制了。

其中valueOf的优先级会toString高一点。

柯里化

柯里化是指这样一个函数(假设叫做createCurry),他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数。

 // 简单实现,参数只能从右到左传递
 function createCurry(func, args) {
 ​
     var arity = func.length;
     var args = args || [];
 ​
     return function() {
         var _args = [].slice.call(arguments);
         [].push.apply(_args, args);
 ​
         // 如果参数个数小于最初的func.length,则递归调用,继续收集参数
         if (_args.length < arity) {
             return createCurry.call(this, func, _args);
         }
 ​
         // 参数收集完毕,则执行func
         return func.apply(this, _args);
     }
 }

做函数的收集。最后统一调用。

总结

js入门的基础知识,也是面试必考的,从基本数据类型的区别、到执行上下的输出,变量对象和活动对象,作用域和作用域链,闭包的概念以及应用。this的指向问题,这些都是我们在面试中必不可少的。