作用域与提升

    xiaoxiao2022-07-05  160

    (一)词法作用域,动态作用域的区别

    因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。 而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。

    function foo() { console.log( a ); } function bar() { var a = 3; //2 该处是函数调用,词法作用域会进入函数foo中,foo的上级作用域为全局作用域,因此为2; //javascript采用词法作用域,故此处输出为2,若是采用动态作用域,此处则应该为3. foo(); (function foo2() { console.log( a ); //3 该处是函数表达式,词法作用域会进入函数foo2中,foo2的上级作用域为bar(),因此为3; })(); } var a = 2; bar();

    词法作用域查找只会查找一级标识符,比如 a、b 和 c。如果代码中引用了 foo.bar.baz, 词法作用域查找只会试图查找 foo标识符,找到这个变量后,对象属性访问规则会分别接 管对 bar 和 baz 属性的访问,因此存在重名变量是相当不安全的。

    注意:

    //由于浏览器演进的历史遗留问题,在创建带有 id 属性 //的 DOM 元素时也会创建同名的全局变量。例如:页面上有 <div id="foo"></div> if (typeof foo == "undefined") {//foo已经被Dom声明为全局变量了 foo = 42; // 永远也不会运行 } console.log( foo ); // HTML元素 //你可能认为只有 JavaScript 代码才能创建全局变量,并且习惯使用 typeof 或 .. in window来检测全局变量。 //但是如上例所示,HTML 页面中的内容也会产生全局变量,并且稍不注意就很容易让全局变量检查错误百出。

    (二)函数作用域,块级作用域

    javascript中function中才有函数作用域,if与for语句是没有块级作用域的。 块作用域只有在let,try…catch, const, with(不推荐使用)中。(’{}'进行块级显式操作,例如let a=1; => {let a=1;})

    if与for代码串是没有私有作用域的 "use strict"; //if语句 var foo = true, baz = 10; if (foo) { var bar = 3; } if (baz > bar) {//10 > 3 console.log( baz );//10 } //for循环同样会污染全局变量 for (var i=0; i<10; i++) { console.log( i );//1 2 ... 9 } console.log( i );//10 函数表达式与函数声明 区分函数声明和表达式最简单的方法是看 function 关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。 如果 function 是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。 var a = 2; (function IIFE() {//立即执行函数表达式 var a = 3; console.log( a ); // 3 })();//IIFE的另一种写法(function IIFE(){}()); 依据个人习惯即可 console.log( a ); // 2 块级作用域 { let a = 2; console.log( a ); } console.log( a ); // ReferenceError //try..catch语句在目前javascript环境中效率十分低下,日后有望提升执行效率 try{ throw 2; }catch(a){ console.log( a ); // 2 } console.log( a ); // ReferenceError

    (三)提升

    函数优先 函数声明和变量声明都会被提升。但是一个值得注意的细节是函数会首先被提升,然后才是变量。函数声明会被提升,但是函数表达式却不会被提升 foo(); // 1 var foo; function foo() { console.log( 1 ); } foo = function() { console.log( 2 ); }; foo();//2 重复声明同名函数,会以后声明的为准 foo(); // 3 function foo() { console.log( 1 ); } var foo = function() { console.log( 2 ); }; function foo() { console.log( 3 ); }
    最新回复(0)