• Javascript 之 作用域和闭包


    执行上下文

    1、在一段 <script>...</script> 标签里面会有一个全局执行上下文

      变量声明、函数声明提前

    2、在一个函数 function fn(arguments){...} 内部会有一个函数执行上下文

      变量声明、函数声明、 this 、 arguments 提前

    函数声明: function fn () {...} 

    函数表达式: var fn = function () {...} 

    this            

     this 要在执行时才能确认值,定义时无法确认   js是单线程解释性语言(另一种是编译性语言),定义时不会报错,执行时才会报错

    var o = {
      name: 'A',
      fn: function () {
        console.log(this.name);
      } }

    o.fn();  // this === o
    o.fn.call({name: 'B'});  // this === {name: 'B'}
    var fn1 = o.fn;
    f1();  // this === window

    作为构造函数执行  this指向新创建的空对象

    作为对象属性执行  this指向对象

    作为普通函数执行  this指向window

     call() 、 apply() 、 bind() 

    function fn (name, age) {
      alert(name);
      console.log(this);
    }
    fn.call({x: 100}, 'joffe');  // this === {x: 100}
    fn.apply({x: 100}, ['joffe', 21]);  // this === {x: 100}

    var fn = function (name, age) {
      alert(name);
      console.log(this);
    }.bind({x: 200});
    fn('joffe', 21);  // this === {x: 200}

     

    作用域

      js没有块级作用域,只有全局作用域、函数作用域(函数内部变量,外部无法访问)

    针对函数作用域

      自由变量是指在当前作用域中没有定义的变量

      在函数执行时,如果一个变量在当前函数作用域没有找到,就会去函数的父级作用域寻找(函数哪里定义,哪里就是函数的父级作用域,跟在哪里执行函数没有关系)

    var a = 100;
    function f1 () {
      var b = 200;
      function f2 () {
        var c = 300;
        console.log(a);  // a 是自由变量
        console.log(b);  // b 是自由变量
        console.log(c);
      }
      f2();
    }
    f1();

    一个变量通过父级作用域一层层往上找,直到找到变量定义的作用域,这叫作用域链

    实例: 创建十个 a 标签,点击弹出序列号

    var i;
    for (i=0; i<10; i++) {
      (function (i) {
        var a = document.createElement('a');
        a.innerHTML = i + '<br />';
        a.addEventListener('click', function (e) {
          e.preventDefault();
          alert(i);  // i 是一个自由变量,需要到函数父级作用域寻找
        })
        document.body.appendChild(a);
      })(i);
    }

    闭包

     1、函数作为返回值

    function fn () {
      var a = 100;
      // 返回一个函数(函数作为返回值)
      return function () {
        console.log(a);  // a 是一个自由变量,父级作用域寻找
      }
    }
    var f1 = fn();
    var a = 200;
    f1();  // 100

     2、函数作为参数传递

    function f1 () {
      var a = 100;
      return function (){
        console.log(a);
      }
    }
    var f2 = f1();
    function f3 (fn){
      var a = 200;
      fn();
    }
    f3(f2);  // 100

     实际开发中闭包的应用 主要用于封装变量,收敛权限

    //防止在 isFirstLoad 函数外修改 _list 的值
    function isFirstLoad () {
      var _list = [];
      return function (num) {
        if(_list.indexOf(num) >= 0) {
          return false;
        } else {
          _list.push(num);
          return true;
        }
      }
    }

    var firstLoad = isFirstLoad();
    firstLoad(10);  // true
    firstLoad(10);  // false
    firstLoad(20);  // true
    firstLoad(20);  // false
  • 相关阅读:
    关于手机号码输入验证
    关于table参数的一些问题
    关于video.js
    Yeoman官方教程:用Yeoman和AngularJS做Web应用
    IE11中的F12无效的问题
    当网站中嵌入视频中,总是弹出迅雷的下载框,或者视频无法播放的情况
    JS window.onload 和模拟document.ready.
    VB6 Access 事务(Transaction)
    ASP 读写文件FSO,adodb.stream
    【转】Win10/UWP新特性系列—Web
  • 原文地址:https://www.cnblogs.com/joffe/p/7668667.html
Copyright © 2020-2023  润新知