zoukankan      html  css  js  c++  java
  • js绑定 this 的方法 call 、apply、bind 方法

    前言:上一篇简单说了this的飘忽不定,有时,需要把this固定下来,避免出现意想不到的情况。JavaScript 提供了callapplybind这三个方法,来切换/固定this的指向。(出来混总是要还的)。

    1、call()

    函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。

    var obj = {};
    
    var f = function () {
      return this;
    };
    
    f() === window // true
    f.call(obj) === obj // true

      

    call方法的参数,应该是一个对象。如果参数为空、nullundefined,则默认传入全局对象。

    var n = 123;
    var obj = { n: 456 };
    
    function a() {
      console.log(this.n);
    }
    
    a.call() // 123
    a.call(null) // 123
    a.call(undefined) // 123
    a.call(window) // 123
    a.call(obj) // 456
    

      

    call方法的参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入call方法。

    var f = function () {
      return this;
    };
    
    f.call(5)
    // Number {[[PrimitiveValue]]: 5}
    

      

    call方法还可以接受多个参数。

    function add(a, b) {
      return a + b;
    }
    
    add.call(this, 1, 2) // 3
    

      

    call方法的一个应用是调用对象的原生方法。(这也是call()方法实现继承的原因)

    var obj = {};
    obj.hasOwnProperty('toString') // false
    
    // 覆盖掉继承的 hasOwnProperty 方法
    obj.hasOwnProperty = function () {
      return true;
    };
    obj.hasOwnProperty('toString') // true
    
    Object.prototype.hasOwnProperty.call(obj, 'toString') // false
    

      上面代码中,hasOwnPropertyobj对象继承的方法,如果这个方法一旦被覆盖,就不会得到正确结果。call方法可以解决这个问题,它将hasOwnProperty方法的原始定义放到obj对象上执行,这样无论obj上有没有同名方法,都不会影响结果。

    2、apply()

    apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数。

    func.apply(thisValue, [arg1, arg2, ...])//apply()格式
    
    //例子对比
    function f(x, y){
      console.log(x + y);
    }
    
    f.call(null, 1, 1) // 2
    f.apply(null, [1, 1]) // 
    

      

      (1)找出数组最大元素

      JavaScript 不提供找出数组最大元素的函数。结合使用apply方法和Math.max方法,就可以返回数组的最大元素。

    var a = [10, 2, 4, 15, 9];
    Math.max.apply(null, a) // 1
    

      

      (2)将数组的空元素变为undefined

      通过apply方法,利用Array构造函数将数组的空元素变成undefined

    Array.apply(null, ['a', ,'b'])
    // [ 'a', undefined, 'b' ]
    
    
    var a = ['a', , 'b'];
    
    function print(i) {
      console.log(i);
    }
    
    a.forEach(print)
    // a
    // b
    
    Array.apply(null, a).forEach(print)
    // a
    // undefined
    // b
    

      

      (3)转换类似数组的对象

      另外,利用数组对象的slice方法,可以将一个类似数组的对象(比如arguments对象)转为真正的数组。

    Array.prototype.slice.apply({0: 1, length: 1}) // [1]
    Array.prototype.slice.apply({0: 1}) // []
    Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
    Array.prototype.slice.apply({length: 1}) // [undefined]
    

      

    3、bind()

      bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数

    var counter = {
      count: 0,
      inc: function () {
        this.count++;
      }
    };
    
    var func = counter.inc.bind(counter);
    func();
    counter.count // 1
    
    
    
    var counter = {
      count: 0,
      inc: function () {
        this.count++;
      }
    };
    
    var obj = {
      count: 100
    };
    var func = counter.inc.bind(obj);
    func();
    obj.count // 101
    

      

     bind()还可以接受更多的参数,将这些参数绑定原函数的参数。

    var add = function (x, y) {
      return x * this.m + y * this.n;
    }
    
    var obj = {
      m: 2,
      n: 2
    };
    
    var newAdd = add.bind(obj, 5);
    newAdd(5) // 20
    

      

    bind()方法每运行一次,就返回一个新函数,这会产生一些问题。比如,监听事件的时候,不能写成下面这样。

    element.addEventListener('click', o.m.bind(o));
    正确的方法是写成下面这样:
    var listener = o.m.bind(o);
    element.addEventListener('click', listener);
    //  ...
    element.removeEventListener('click', listener);
    

      


     
  • 相关阅读:
    0808 HTML 基础
    2016.8.3 C#基础 结构体,枚举类型
    2016.8.1 C#基础 传值
    2016.7.22
    2016.7.20
    2016.7.31C#基础 函数
    2016.07.30C#基础 特殊集合
    2016.7.28C#基础 集合
    个人项目网页3
    个人项目网页2
  • 原文地址:https://www.cnblogs.com/xuwupiaomiao/p/12781322.html
Copyright © 2011-2022 走看看