zoukankan      html  css  js  c++  java
  • 深入理解JS:执行上下文中的this(二)

    目录

    • 序言
    • Function.prototype.bind() 方法
    • 箭头函数
    • 参考

    1.序言

    深入理解JS:执行上下文中的this(一) 中,我们主要深入分析全局环境和函数环境中函数调用的 this,还留下 bind 方法以及箭头函数的 this 尚未分析,因此我们将在这篇文章进行讲解。


    2.Function.prototype.bind() 方法

    bind() 方法将会创建返回一个新的函数。在 bind() 被调用时,这个新函数的 this 将被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

    ES5 引入了 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。

    这里给出一种 bind() 的实现算法:

    var slice = Array.prototype.slice;
    Function.prototype.bind = function() {
      var thatFunc = this, thatArg = arguments[0];
      var args = slice.call(arguments, 1);
      if (typeof thatFunc !== 'function') {
        throw new TypeError('Function.prototype.bind called on incompatible ' + thatFunc);
      }
      return function(){
        var funcArgs = args.concat(slice.call(arguments))
        return thatFunc.apply(thatArg, funcArgs);
      };
    };
    

    注:上述代码并没有完全按照ES5规范实现,只是作为一种实现参考,更加完善的解决方案可以参考 function-bind

    但不论哪种实现,其实质上都是通过使用类似 Function.prototype.apply(thisArg, argArray) 方法来实现指定调用函数 this 的。


    3.箭头函数

    箭头函数表达式的语法比函数表达式更简洁,并且没有自己的 this,arguments,super 或 new.target。它很适合用作匿名函数,并且不能用作构造函数(为什么呢?详情点击查看)。

    ES6 引入了支持 this 词法解析的箭头函数(它在闭合的执行环境内设置 this 的值)。

    如何理解箭头函数在闭合的执行环境内设置 this 的值?

    简单理解,箭头函数不会创建自己的 this,它的 this 与封闭词法环境的 this 保持一致,即如果箭头函数在全局环境中,那么它的 this 就指向全局对象,如果箭头函数在某一个函数中,那么它的 this 就指向所在函数的 this。


    我们来看几个示例:

    (1)全局环境

    var global = this
    
    var foo = () => { return this }
    
    var value = 1
    
    var bar = {
      value: 2,
      getValueByArrowFunc: () => {
        return this.value
      },
      getValue: function (){
        return this.value
      },
    }
    
    console.log(foo() === global) // true
    
    // 箭头函数 this => global
    console.log(bar.getValueByArrowFunc()) // 1
    
    // 普通函数 this => bar
    console.log(bar.getValue()) // 2
    

    (2)函数环境

    ES6的语法:

    function foo() {
      this.value = 1
      
      // 箭头函数表达式
      var arr = () => {
        console.log(this.value)
      }
      
      arr()
    }
    

    转化为ES5:

    function foo() {
      var _this = this;
    
      this.value = 1;
    
      // 转化为普通函数表达式
      var arr = function arr() {
        console.log(_this.value);
      };
    
      arr();
    }
    

    对比转化前后的代码可以看出:箭头函数会转化为一个普通函数,通过一个临时变量 _this 来传递,它之前的 this 就是所在函数的 this


    (3)call() 、 apply() 或 bind() 方法

    var global = this
    
    var foo = {
    	bar: () => {
        return this
      }
    }
    
    var obj = { value : 1 }
    
    console.log(foo.bar() === global) // true
    console.log(foo.bar.call(obj) === global) // true
    console.log(foo.bar.apply(obj) === global) // true
    
    var bind = foo.bar.bind(obj)
    console.log(bind() === global) // true
    

    由于箭头函数不会创建自己的 this,那么通过 call() 、 apply() 或 bind() 方法调用一个箭头函数时,只能传递参数,第一个参数会被忽略。


    4.参考

    this 关键字 - JavaScript | MDN - Mozilla

    Function.prototype.bind() - JavaScript - MDN - Mozilla

    箭头函数- JavaScript | MDN

    ECMAScript5.1中文版

    ES6 - Arrow functions

  • 相关阅读:
    bzoj4321
    bzoj1800
    codeforces396C
    codeforces400C
    codeforces271D
    关于jsp中jstl-core标签循环遍历的使用
    hibernate坑边闲话2
    hibernate坑边闲话
    hibernate中实体与数据库中属性对应的类型
    MySQL的常用命令:添加外键,修改字段名称,增加字段 设置主键自增长等
  • 原文地址:https://www.cnblogs.com/forcheng/p/12977048.html
Copyright © 2011-2022 走看看