JavaScript基础面试题总结04

1. JavaScript 中的作用域、预解析与变量声明提升?

作用域

作用域就是变量的有效范围。 在一定的空间里可以对数据进行读写操作,这个空间就是数据的作用域。

1、全局作用域: 最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的。

2、局部作用域: 局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的,最常见的例如函数内部。在 ES6 之前,只有函数可以划分变量的作用域,所以 在函数的外面无法访问函数内的变量。

3、块级作用域:凡是代码块就可以划分变量的作用域,这种作用域的规则就叫块级作用域。

块级作用域、函数作用域和词法作用域之间的区别:

  1. 块级作用域和函数作用域描述的是,什么东西可以划分变量的作用域

  1. 词法作用域描述的是,变量的查找规则之间的关系

  1. 块级作用域 包含 函数作用域

  1. 词法作用域 与 块级作用域、函数作用域之间没有任何交集, 他们从两个角度描述了作用域的规则。

ES6 之前 JavaScript 采用的是函数作用域+词法作用域,ES6 js 采用的是块级作用域+词法作用域。

预解析

JavaScript 代码的执行是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器 执行 JavaScript 代码的时候,分为两个过程:预解析过程代码执行过程

预解析过程:

1.把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值

2.把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用

3.先提升 function,在提升 var

JavaScript 的执行过程:

    // 案例 1
    var a = 25
    function abc() {
      alert(a) // undefined
      var a = 10
    }
    abc()
    // 案例 2
    console.log(a) // 25
    function a() {
      console.log('aaaaa') // 不会执行, 没人调用 a()
    }
    var a = 1
    console.log(a) // 1

变量提升

变量提升:定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升。

函数提升:JavaScript 解析器首先会把当前作用域的函数声明提前到整个作用域的最前面。

    // 1、-----------------------------------
    var num = 10
    fun()
    function fun() {
      console.log(num) // undefined
      var num = 20
    }
    //2、-----------------------------------
    var a = 18
    f1() // 后者覆盖前者 f1 函数
    function f1() {
      var b = 9
      console.log(a)
      console.log(b)
      var a = '123'
    }
    // 3、-----------------------------------
    f1() // 再次调用下面的 f1 执行
    console.log(c) // 9
    console.log(b) // 9
    console.log(a) // 18
    function f1() {
      var a = b = c = 9 // 这里相当于 var a = 9; b = 9; c = 9, 所以后 2 个隐藏转换为全局变量了
      console.log(a) // 9
      console.log(b) // 9
      console.log(c) // 9
    }

变量声明提升: 使用 var 关键字定义的变量,被称为变量声明;函数声明提升的特点是,在函数声明的前面,可以调用这个函数。

2. 变量提升与函数提升的区别?

变量提升

简单说就是在 JavaScript 代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端函数内声明的变量只会提升至该函数作用域最顶层当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被上升到最顶端

    console.log(a) // undefined
    var a = 3 // 预编译后的代码结构可以看做如下运行顺序
    var a // 将变量 a 的声明提升至最顶端,赋值逻辑不提升。
    console.log(a) // undefined
    a = 3 // 代码执行到原位置即执行原赋值逻辑

函数提升

函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升

函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上

3. 什么是作用域链?

作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链,由子级作用域返回父级作用域中寻找变量,就叫做作用域链。

作用域链中的下一个变量对象来自包含环境,也叫外部环境。而再下一个变量对象则来自下一个包含环境,一直延续到全局执行环境。全局执行环境的变量对象始终都是作用域链中的最后一个对象。

作用域链前端始终都是当前执行的代码所在环境的变量对象,如果环境是函数,则将 其活动对象作为变量对象。

4. 如何延长作用域链?

作用域链是可以延长的。

延长作用域链: 执行环境的类型只有两种,全局和局部(函数)。但是有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。

具体来说就是执行这两个语句时,作用域链都会得到加强

  1. try - catch 语句的 catch 块:会创建一个新的变量对象,包含的是被抛出的错误对 象的声明。

  2. with 语句:with 语句会将指定的对象添加到作用域链中。

5. src 和 href 的区别是?

src(source)指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置。在请求 src 资源时会将其指向的资源下载并应用到文档中,如 JavaScript 脚本,img 图片和 iframe 等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,类似于将所指向资源嵌入当前标签内。

href(hypertext reference/超文本引用)指向网络资源所在位置,建立和当前元素(锚点)或当前文档( 链 接 )之间的链接 ,如果我们在文档中添加<link href="common.css" rel="stylesheet"/>那么浏览器会识别该文档为 CSS 文件,就会并行下载资源并且不会停止对当前文档的处理。

猜你喜欢

转载自blog.csdn.net/m0_64526818/article/details/122884217