zoukankan      html  css  js  c++  java
  • 你不知道的JavaScript(作用域和闭包)

    作用域和闭包

    ・作用域

      引擎:从头到尾负责整个JavaScript的编译及执行过程。

      编译器:负责语法分析及代码生成等。

      作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

      作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。

      如果查找的目的是对变量进行赋值,那么就会使用LHS查询;

      如果目的是获取变量的值,就会使用RHS查询。

    ・词法作用域

      无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定。

      欺骗词法:两种机制。欺骗词法作用域会导致性能下降。

      eval():

      function foo(str, a) {

        eval(str);

        console.log(a, b);

      }

      var b = 2;

      foo(“var b = 3; ”, 1);

      // 1, 3

      with():

      function foo(obj) {

        with(obj) {

      a = 2;

      }

     }

      var o1 = { a: 3};

      var o2 = { b: 3};

      foo(o1);

      console.log(o1.a); // 2

      foo(o2);

      console.log(o2.a); // undefined

      console.log(a); // 2

    ・函数作用域和块作用域

      隐藏内部实现:可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来隐藏它们。

      最小特权原则(最小授权或最小暴露原则):最小限度地暴露必要内容,而将其他内容都隐藏起来。

      规避冲突:隐藏作用域中的变量和函数,可以避免同名标识符之间的冲突。

      包装函数:

      (function foo() {

        var a = 3;

        console.log(a);

      })();

      匿名函数:

      setTimeout(function() {…}, 1000);

      缺点:

      匿名函数在栈追踪中不会显示出有意义的函数名,使得调试困难;

      如果没有函数名,当需要引用自身时只能使用已过期的arguments.callee引用;

      匿名函数省略了对于代码可读性/可理解性很重要的函数名。

      给函数表达式指定一个函数名可以有效解决以上问题:

      setTimeout(function timeoutHandler() {…}, 1000);

      块作用域:

        let关键字可以将变量绑定到所在的任意作用域中;

        使用let进行的声明不会在块作用域中进行提升;

      提升:

        只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。

        如果提升改变了代码执行的顺序,会造成非常严重的破坏;

      函数声明和变量声明都会被提升,但是函数会首先被提升;

      foo(); // 1

      var foo;

      function foo() {

            console.log(1);

      }

      foo = function() {

            console.log(2);

      }

      ・作用域闭包

        只要使用了回调函数,实际上就是在使用闭包;

      模块模式具备的两个必要条件:

      必须有外部的封闭函数,该函数必须至少被调用一次;

      封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态;

      function CoolModule() {

        var something = “cool”;

          var another = [1, 2, 3];

          function doSomething() {

          console.log(something);

      }

      function doAnother() {

        console.log(another.join(“!”));

      }

      return {

        doSomething: doSomething,

        doAnother: doAnother

      };

     }

      var foo = CoolModule();

      foo.doSomething();

  • 相关阅读:
    CMake 用法导览
    Irrlicht 1.8.4 + Win7 + VC2015 + x64 +OpenGL编译
    VirtualBox 5.1.14 获取VirtualBox COM对象错误
    CGAL Manual/tutorial_hello_world.html
    CGAL 介绍
    Open CASCADE 基础类(Foundation Classes)
    OpenCASCADE 基础
    Nginx 反向代理详解
    修改docker容器中的hosts文件
    Jmeter 设置连接oracle数据库
  • 原文地址:https://www.cnblogs.com/dreamerjdw/p/6265471.html
Copyright © 2011-2022 走看看