JS 提升

作者: Cherry丶小丸子 | 来源:发表于2022-09-03 16:17 被阅读0次

变量提升即将变量声明提升到它所在作用域的最开始的部分

在 js 中只有两种作用域,全局作用域和函数作用域,在ES6之前,js 是没有块级作用域
JavaScript 代码的执行分为两个阶段,第一个阶段在当前词法环境中注册所有的变量和函数声明,简单说就是,解析完成之后,第二个阶段的 JavaScript 执行就开始了

变量提升
num = 6;
var num = 7;
var num;
console.log(num); // 7,也证明了同名变量只会声明一次,其他的会被忽略

// 浏览器引擎会编译为:
var num;
num = 6;
num = 7;
console.log(num); // 7
console.log(a);
var a = 1;

// 浏览器引擎会编译为:
var a;
console.log(a); // undefined
a = 1;
函数提升
1、函数声明提升
foo(); // js 在执行之前,会把 foo 函数提升到最前面,所以我们在 foo 函数定义之前就可以使用 foo 函数
function foo(){
    console.log(1)
}

// 浏览器引擎会编译为:
function foo(){
    console.log(1)
}
foo();
2、函数表达式提升
foo();
var foo = function(){
    console.log(1)
}

// 此种声明方式我们可以理解为一个普通变量的提升,
//在 js 代码执行之前会把 foo 提升带最前面,在函数赋值之前,foo 是 undefined,如果调用 foo(),将会报错

// 浏览器引擎会编译为:
var foo;
foo(); // Uncaught TypeError: foo is not a function
foo = function(){
    console.log(1)
}
在定义的函数名字和变量名相同的情况下,函数提升优先级高于变量的例子
func();
var func;
function func() {
    console.log(1);
}
func = function() {
    console.log(2);
}
// 函数声明和变量声明都会被提升,但是需要注意的是函数会先被提升,然后才是变量
// var func; 尽管出现在 function func() 之前,但它是重复的声明,会被忽略,因为函数声明会被提升到普通变量之前

// 浏览器引擎会编译为:
function func() {
    console.log(1);
}
func(); // 1
func = function() {
    console.log(2);
}

牢记这三点:

  • 只有声明本身会被提升,而赋值操作不会被提升
  • 变量会提升到其所在函数的最上面,而不是整个程序的最上面
  • 函数声明会被提升,但函数表达式不会被提升

面试题

第一题
var a = 4;
function fun(){
    console.log(a) // undefined
    var a = 5;
}
fun();

说明: 在上面这段代码中有两个作用域,window 全局作用域和 fun 函数作用域,
在打印变量 a 时,会先在 fun 函数作用域里面查找,因为在执行 fun 函数时,
在函数内部也会先进行变量提升,所以最终的打印结果为 undefined

// 浏览器引擎会编译为:
var a = 4;
function fun(){
    var a;
    console.log(a) // undefined
    a = 5;
}
fun();


这里涉及到一个查找的知识点
考虑以下代码:
function foo(a){
    var b = a * 2;
    function bar(c){
        console.log(a, b, c) // 2, 4, 12
    }
    bar(b * 3)
}
foo(2)

说明:引擎执行 console.log(...) 声明,并查找 a, b 和 c 三个变量的引用,它首先从最内部的作用域,也就是bar(...) 函数的作用域开始查找,
引擎无法在这里找到 a,因此会去上一级到所嵌套的 foo(...) 的作用域中继续查找,在这里找到了 a,因此引擎使用了这个引用,
对 b 来讲也是一样的,而对于 c 来说,引擎在 bar(...) 中就找到了它

如果 bar(...) 和 foo(...) 的内部都存在一个 c,console.log(...) 就可以直接使用 bar(...) 中的变量,而无需到外面的 foo(...) 中查找

`作用域查找会在找到第一个匹配的标识符时停止`。
在多层的嵌套作用域中可以定义同名的标识符,这叫做 “遮蔽效应”(内部的标识符 “遮蔽” 了外部的标识符)。
抛开遮蔽效应,`作用域查找始终从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见第一个匹配的标识符为止`。
第二题
function a(){}
var a;
console.log(typeof a) // function

var b = 1;
function b(){}
console.log(typeof b) // number

说明:函数名字和变量名相同的情况下,函数提升优先级高于变量,变量重复的声明,会被忽略

// 浏览器引擎会编译为:
function a(){}
console.log(typeof a) // function

function b(){}
b = 1;
console.log(typeof b) // number
第三题
console.log(typeof a) // function
function a(){}
var a = 1;

说明: 函数提升的优先级高于变量提升,忽略重复声明

// 浏览器引擎会编译为:
function a(){}
console.log(typeof a) // function
a = 1;
第四题
console.log(v1);
var v1 = 100;
function foo(){
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
foo();
console.log(v1);

// 浏览器引擎会编译为:
var v1;
console.log(v1); // undefined
v1 = 100;
function foo(){
    var v1; // undefined
    console.log(v1);
    v1 = 200;
    console.log(v1); // 200
}
foo();
console.log(v1); // 100

相关文章

  • 前端资料

    ES6新数据类型 Symbol . js变量提升函数提升 js this js 原型及原型链理解 new做了什么 ...

  • 变量声明提升

    变量声明提升是JS中一个基础的问题,同时也是对JS词法作用域认识的一个提升。在JS面试题中,关于变量声明提升的问题...

  • 变量提升和函数提升

    JS不像C语言,C语言是先声明后使用,否则会报错。但JS中,有变量提升现象,可以先使用后声明。 JS存在变量提升,...

  • 前端经典面试题合集(一)

    1.谈谈变量提升 考察点:js基础知识,js执行机制,变量的提升答:执行js代码时,会生成执行环境,在函数中的代码...

  • JS 提升

    变量提升即将变量声明提升到它所在作用域的最开始的部分 在 js 中只有两种作用域,全局作用域和函数作用域,在ES6...

  • js面试题

    1、js 数据类型 基本数据类型 引用数据类型 2、js 变量和函数声明的提升 在js中变量和函数的声明会提升到最...

  • 浏览器学习笔记-JS执行

    变量提升 变量提升原理浏览器对js是先编译后执行,在编译过程中,js中的变量声明会被提升到代码段落前面。函数声明和...

  • 变量提升

    参考信息:https://www.runoob.com/js/js-hoisting.html 对变量提升的解释:...

  • JS中的提升

    JS中包含两种提升,变量提升和函数提升。 变量提升 变量提升只能是var或者function声明的变量或者函数,l...

  • js中变量和函数声明的提升

    二 、 js中变量和函数声明的提升

网友评论

      本文标题:JS 提升

      本文链接:https://www.haomeiwen.com/subject/zkhmnrtx.html