• JavaScript中改变context上下文的方法


    序言:

            作为一名合格的前端开发者,大家都应该知道改变js作用域中上下文的方法有:call、apply和bind。思考一个问题:还有没有更好的实现方式呢?

    1、call和apply

    call和apply是最简单实现改变函数体内部this指向的方法,他们的区别仅仅是第二个参数不同。语法示例:

    obj.call(thisObj,arg1,agr2,...)
    obj.apply(thisObj,[arg1,agr2])

    代码示例(Math.max)

    Math.max(1, 3, 2)
    

     如输入参数是数组呢?

    Math.max.apply(null,[1,2,3,4,2,3])

    说明:上面示例代码中,第一个参数为null,也可以为其他(空字符串,对象),仅仅是“借用”Math的max方法而已。

    2、bind

    bind方法是创建一个新方法,当函数调用时将this设置为提供的值。与call类似,除第一个参数外是可变参数,语法示例:

    obj.bind(thisObj,arg1,agr2,...)

    这时thisObj就有了obj方法和属性。

    bind与call和apply不同的是,bind之后返回一个函数,不会立即执行。需要再显示执行一次才能完成函数的调用。如:

    let m = test.bind(obj,3)
    m()

    另外,bind也常用在ES6的Class绑定上下文。

    class Dog {
      constructor() {
        this.name = 'adong';
      }
    
      start() {
        this.p().then(this.say);
      }
    
      p() {
        return new Promise((resolve, reject)=>{
          resolve('good');
        })
      }
      
      say(str) {
        console.log(this);
        console.log(this.name + str);
      }
    }
    
    let dog = new Dog();
    dog.start();

    上述代码会显示:

     即在Promise的then方法参数是一个匿名函数,匿名函数的this指向是:undefined。

    这里有2种方案:

    (1)箭头函数

    class Dog {
      constructor() {
        this.name = 'adong';
      }
    
      start() {
        this.p().then(this.say);
      }
    
      p() {
        return new Promise((resolve, reject)=>{
          resolve('good');
        })
      }
      
      say= (str) => {
        console.log(this);
        console.log(this.name + str);
      }
    }
    
    let dog = new Dog();
    dog.start();

     即,使用箭头函数,this执行函数定义时作用域,即Dog对象

    (2)使用bind绑定this指向

    class Dog {
      constructor() {
        this.name = 'adong';
      }
    
      start() {
        this.p().then(this.say.bind(this));
      }
    
      p() {
        return new Promise((resolve, reject)=>{
          resolve('good');
        })
      }
      
      say(str) {
        console.log(this);
        console.log(this.name + str);
      }
    }
    
    let dog = new Dog();
    dog.start();

    3、使用ES7的Decorators

    使用autobind-decorator库,实现自动this绑定。

    import autobind from 'autobind-decorator'
    class MathTest {
        constructor(val) {
            this.val = val
        }
        @autobind
        show() {
            return this.val
        }
    }
    let mathTest = new mathTest(42);
    let show = mathTest.show;
    show()

     当然@autobind也可以在整个类上进行this上下文的绑定。

    4、双冒号运算符

    双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

    示例代码:

    [1,2,3]::Array.prototype.map(x=>{return x*3})

    经过babel编译后:

    "use strict";
    
    var _context;
    
    (_context = [1, 2, 3], Array.prototype.map).call(_context, function (x) {
      return x * 3;
    });

    即对象[1,2,3]作为this绑定到了Array的map方法上。

    5、总结

    以上即是js中绑定this上下文的方法,助力源码阅读。

  • 相关阅读:
    centos 安装 Lamp(Linux + Apache + PHP) 并安装 phpmyadmin
    mysql常用内置函数-查询语句中不能使用strtotime()函数!
    Windows下 wamp下Apache配置虚拟域名
    thinkphp ajax调用demo
    phpMailer 手册
    wampServer2.2 You don't have permission to access /phpmyadmin/ on this server.
    打印对象
    最全的CSS浏览器兼容问题
    html 视频播放器
    C语言入门-结构类型
  • 原文地址:https://www.cnblogs.com/mengfangui/p/12380954.html
Copyright © 2020-2023  润新知