词法作用域2 - 函数作用域和块作用域

  1. 隐藏内部实现

    1. 最小授权原则 -- 最小限度地暴露必要内容。
    2. 所以不会将变量和函数都声明在全局作用域中
      1. function doSomething(a) {
            b = a + doSomethingElse(a * 2);
        
            console.log(b * 3);
        }
        
        function doSomethingElse(a) {
            return a - 1;
        }
        
        var b;
        
        doSomething(2);    // 15

        变量b和函数doSomethingElse()是函数doSomething()的私有内容,外部作用域可以访问到是危险的,下面将私有内容隐藏在函数内部。

      2. function doSomething(a) {
            var b;
        
            function doSomethingElse(a) {
                return a - 1;
            }
        
            b = a + doSomethingElse(a * 2);
        
            console.log(b * 3);
        }
    3. 隐藏的作用
      1. 避免变量覆盖

        1. 第三方库中将需要暴露的功能加入命名空间
        2. 模块
  2. 函数作用域
    1. var c = ‘hey‘;
      
      function bo() {
          var c = ‘hi‘;
          console.log(c);
      
      }
      
      bo();    // hi
      console.log( c );    // hey

      上述代码的问题

      1. 函数bo()‘污染’了所在作用域,因为是一个具名函数
      2. 只能显式地通过函数名调用函数
    2. 期待能够不要函数的名字,并且没有名字也可以运行
      1. var c = ‘hey‘;
        
        (function bo() {
            var c = ‘hi‘;
            console.log(c);  // hi
        })();
        
        console.log(c);  // hey
      2. 区分函数和函数表达式就是看function关键字是否是声明的第一个词。
      3. 上面代码中,function前还有一个 ‘(‘ ,所以是函数表达式
      4. 所以 (function bo(){ .. }) 只能在 .. 中访问,不能被外部作用域访问。变量名bo被隐藏在自身中,最小授权
    3. 匿名和具名
      1. 匿名函数表达式的缺点

        1. 调试时,栈内并没有函数名
        2. 函数表达式递归时,只能用arguments.callee
        3. 可读性降低
      2. 行内函数表达式 -- 具名
      3. setTimeout( function() {
            console.log(‘等1秒!‘);
        }, 1000 );
        
        // 行内函数表达式
        setTimeout( function timeoutHandler() {
            console.log(‘等1秒!‘);
        }, 1000 );
    4. Immediately Invoked Function Expression --- 立即执行函数表达式
      1. var word = ‘hi‘;
        
        (function IIFE() {
            var word = ‘hey‘;
            console.log(word);    // hey
        })();
        
        console.log( word );    // hi

        函数IIFE中第一个括号将函数定义为函数表达式,第二个括号使函数立即运行

        下面是IIFE的另一种形式,将第二个括号写入第一个括号里

      2. var word = ‘hi‘;
        
        ( function IIFE() {
            var word = ‘hey‘;
            console.log(word);    // hey
        }() );
        
        console.log( word );    // hi
      3. 作用
        1. 匿名函数表达式
        2. 作为主调函数,传递参数
          1. var say = ‘hi‘;
            
            (function IIFE(global){
                var say = ‘hey‘;
                console.log(say);    // hey
                console.log(global.say);    // hi
            }(window));
            
            console.log(say);    // hi
          2. 避免undefined的默认值被错误覆盖导致的异常(我还没见过)

            undefined = true;
            
            (function IIFE( undefined ) {
                var a;
                if (a === undefined) {
                    console.log(‘Undefined is safe here!‘);
                }
            })();
          3. 倒置代码的运行顺序

            say = ‘hi‘;
            
            (function run1(func) {
                func(window);
            })( function run2(global) {
                var say = ‘hey‘;
                console.log(say);    // hey
                console.log(global.say);    // hi
            });

            函数run2在函数run1执行之后当作参数传进去

  3. 块作用域
    1. 为什么引入块作用域?

      var a = true;
      
      if (a) {
        var b = a * 2;
        console.log( b );
      }

      尽管变量b声明在块作用域内,但是var声明的变量不具有块作用域的特性,所以变量b被绑定在全局作用域内,污染了全局作用域,破坏了最小暴露原则。

      • 块作用域可以将隐藏在函数内的信息扩展为块中隐藏的信息。所以能提高代码的可维护性。
    2. with的块作用域(不懂)
    3. try...catch中catch的作用域,没遇到过,先放着

原文地址:https://www.cnblogs.com/wydumn/p/11577865.html

时间: 2024-11-05 18:57:11

词法作用域2 - 函数作用域和块作用域的相关文章

深入理解javascript作用域系列第四篇——块作用域

× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的代码,比如块作用域.随着ES6的推广,块作用域也将用得越来越广泛.本文是深入理解javascript作用域系列第四篇——块作用域 let for (var i= 0; i<10; i++) { console.log(i); } 上面这段是很熟

读书时间《JavaScript高级程序设计》三:函数,闭包,作用域

上一次看了第6章,面向对象.这里接着看第7章. 第7章:函数表达式 定义函数有两种方式:函数声明.函数表达式 //函数声明 function functionName(arg0,arg1,arg2){ //code... } //函数表达式 var functionName = function(arg0,arg1,arg2){ //code... }; 函数声明有个重要的特征是函数申明提升.就是在执行代码前会先读取函数声明,意味着可以把函数声明放在调用它的语句后面. //函数声明提升 sayH

python入门基础-三元表达式、命名空间、作用域、函数名本质、闭包

1.三元表达式(三目运算式) #1 三元表达式(三目运算法) #格式为: 为真时的结果 if 判定条件 else 为假时的结果 #另外三元表达式只适合较为简洁的条件判定,较为复杂的判定建议不要用这种方式写代码,因为比较让他人难以理解. a = 10 b = 15 compare = a if a > b else b #谁大返回谁 print(compare) 2.命名空间(namespace) #2 命名空间(namespace) #命名空间是名称和对象的印象,也可以将命名空间理解成一个字典,

《你不知道的javascript》一、函数作用域和块作用域

函数中的作用域 所谓函数作用域,就是属于这个函数的全部变量都可以在整个函数的范围内使用及复用. 1 function foo(a) { 2 var b=a; 3 function bar(c){ 4 var c=b*2; 5 console.log(c); 6 } 7 bar(); //4 8 } 9 foo(3); 1 function foo(a) { 2 var b=a; 3 function bar(c){ 4 var c=b*2; 5 console.log(c); 6 } 7 bar

[Effective JavaScript 笔记]第15条:当心局部块函数声明笨拙的作用域

嵌套函数声明.没有标准的方法在局部块里声明函数,但可以在另一个函数的顶部嵌套函数声明. function f(){return "global"} function test(x){ var result=[]; function f(){return "local";}//block-local if(x){ result.push(f()); } result.push(f()); return result; } test(true);//["loc

js没有块级作用域但有函数作用域

任何一对花括号中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域. 作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.首先我们理解两个概念:块级作用域与函数作用域. 什么是块级作用域呢? 任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域. 函数作用域就是定义在函数中的参数和变量在函数外部是不可见的. 大多数类C语言都拥有块级作用域,JS却没有.请看下文de

函数表达式-模仿块级作用域

模仿块级作用域 Javascript中没有块级作用域的概念,这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的 1 function outputNumbers(count){ 2 for (var i = 0; i < count; i++){ 3 console.log(i); 4 } 5 console.log(i); 6 } 在for循环中定义的局部变量i可以再for循环外访问,因为变量i是定义在outputNumbers()的活动对象中的,因此从它有定义开始,就可以在函

JS函数表达式 -- 模仿块级作用域

JavaScript没有块级作用域的概念.这意味着在语句中定义的变量,实际上是在包含函数中而非语句中创建的. 1 function outputNumbers(count){ 2 for(var i=0; i<count; i++){ 3 alert("In: " + i); 4 } 5 var i; 6 alert("Out: " + i); 7 } 8 outputNumbers(2); //In: 0 In: 1 Out:2 在这个函数中定义了一个for

块级作用域和函数的自我执行

看了好多地方讲这两个东西,我一直以为不一样,后来仔细体会发现这两个其实是一样的,没有什么不同.只是使用的位置不同. 函数的自执行: ----------------------------------------------------------------------------------------- // 下面2个括弧()都会立即执行(function () { /* code */ } ()); // 推荐使用这个(function () { /* code */ })(); //