zoukankan      html  css  js  c++  java
  • this与bind(this) (es5新增)

    this与bind(this)

    this

    this指向的是当前函数的作用域(对象实例),有如下的例子

    const app = {
        name: 'xiaoming',
        log() {
          console.log(this.name);
        },
        child() {
          return {
            name: 'b',
            log() {
              console.log(this.name);
            },
          };
        },
      };
      app.log(); // xiaoming
      app.child().log(); // b

    this详细

    - 全局环境

    无论是否在严格模式(‘use strict’)下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。

    console.log(this === window); // true
    
    this.name = 'react';
    console.log(name); // react
    console.log(window.name); // react

    - 函数内

    在函数内部,this的值取决于函数被调用的方式。

    1. 普通函数

    非严格模式下,this默认指向全局对象。

    function f() {
      return this;
    }
    
    // brower
    f() === window;
    // node
    f() === global;

    严格模式下,this默认指向调用函数的对象实例。

    function f() {
      'use strict'
      return this;
    }
    f() === undefined;
    因为这里的f()是直接调用的,而不是作为对象的属性或方法调用的,如window.f(),所以这里的this为undefined。

    如果要想把 this 的值从一个环境传到另一个,就要用 call 或者apply 方法

    var obj = {a: 'Custom'};
    
    // 这个属性是在global对象定义的。
    var a = 'Global';
    
    function whatsThis(arg) {
      return this.a;  // this的值取决于函数的调用方式
    }
    
    whatsThis();          // 'Global'
    whatsThis.call(obj);  // 'Custom'
    whatsThis.apply(obj); // 'Custom'

    在JavaScript定义的函数都继承自Function,我们可以通过Function.prototype属性里的call或apply方法将 this 值绑定到调用中的特定对象。

    function add(c, d) {
      return this.a + this.b + c + d;
    }
    
    var o = {a: 1, b: 3};
    
    // 第一个参数是作为‘this’使用的对象
    // 后续参数作为参数传递给函数调用
    add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
    // 第一个参数也是作为‘this’使用的对象
    // 第二个参数是一个数组,数组里的元素用作函数调用中的参数
    add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

    使用 call 和 apply 函数的时候要注意,如果传递给 this 的值不是一个对象,JavaScript 会尝试使用内部 ToObject 操作将其转换为对象。因此,如果传递的值是一个原始值比如 7 或 ‘foo’,那么就会使用相关构造函数将它转换为对象,所以原始值 7 会被转换为对象,像 new Number(7) 这样,而字符串 ‘foo’ 转化成 new String(‘foo’) 这样,例如:

    function bar() {
      console.log(Object.prototype.toString.call(this));
    }
    
    //原始值 7 被隐式转换为对象
    bar.call(7); // [object Number]

    2. 箭头函数

    箭头函数没有自己的this指针。通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this)。在封闭的词法环境中,箭头函数的this和普通函数的this一致;在全局代码里,箭头函数的this被设置为全局对象。

    var obj = {
      bar: function() {
        var x = (()=> this);
        return x;
      }
    }
    // 以obj为对象来调用bar(),所以this绑定的是obj
    var fn = obj.bar();
    console.log(fn() === obj); // true
    
    // 这里并没有调用bar(),只是引用bar赋给fn2
    var fn2 = obj.bar;
    // 使用全局变量来调用bar(),所以这里的this绑定全局
    console.log(fn2()() == window);

    3. 对象中的函数

    当函数在对象中被调用时,this指向的是调用该函数的对象。

    const app = {
      name: 'xiaohong',
      f: function() {
        console.log(this.name);
      }
    }

    f() 函数里的this指向的是app对象。

    this 的绑定只受最靠近的成员引用的影响。例如:

    var o = {prop: 37};
    
    function independent() {
      return this.prop;
    }
    
    o.f = independent;
    
    console.log(o.f()); // logs 37
    
    o.b = {g: independent, prop: 42};
    console.log(o.b.g()); // 42

    事实证明,这与他是对象 o 的成员没有多大关系,最靠近的引用才是最重要的。

    原型链中的this

    如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,就像该方法在对象上一样。

    var o = {
      f: function() { 
        return this.a + this.b; 
      }
    };
    var p = Object.create(o);
    p.a = 1;
    p.b = 4;
    
    console.log(p.f()); // 5

    在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。虽然在对 f 的查找过程中,最终是在 o 中找到 f 属性的,这并没有关系;查找过程首先从 p.f 的引用开始,所以函数中的 this 指向p。也就是说,因为f是作为p的方法调用的,所以它的this指向了p。

    getter 与 setter 中的 this
    用作 getter 或 setter 的函数都会把 this 绑定到设置或获取属性的对象。

    bind(this)
    ES5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。bind绑定的参数只生效一次

    function f(){
      return this.a;
    }
    
    var g = f.bind({a:"azerty"});
    console.log(g()); // azerty
    
    var h = g.bind({a:'yoo'}); // bind只生效一次!
    console.log(h()); // azerty

    传入bind的第二个参数以及后面的,依照先后顺序构成绑定函数的参数。

    var foo = {
        x: 3
    } 
    var bar = function(){
        console.log(this.x);
    } 
    bar(); // undefined
    
    var boundFunc = bar.bind(foo);
    
    boundFunc(); // 3

    有时候,我们须要保持this的上下文,也就是在一个运行环境中,想要訪问到的this值。在什么时候须要这么做呢?

    比方说将一个对象的方法赋值给了一个全局变量,然后在全局变量中调用这种方法,那么this值就不再是原来的对象而是window对象了。但是我们还需要依照对象的方法来调用。

    又比方说一个方法中包括了闭包,闭包是无法訪问到其外部函数的this对象的,由于this对象是在调用方法的时候自己主动生成,内部函数在搜索这两个变量的时候仅仅会搜索到其自身的活动对象。而不会沿着作用域链往外搜索,所以闭包訪问不到外部函数的this值。

    在react中,常看到

    export default class App extends Component {
      constructor(props) {
        super(props);
        this.foo = this.foo.bind(this);
      }
      
      foo() {
        // todo something
      }
      
      render() {
        return (
          <View>
            <Button onPress={this.foo()}/>
          </View>
        )
      }
    }

    如果你传递一个函数名给一个变量,然后通过在变量后加括号’()'来调用这个方法,此时方法内部的this的指向就会丢失。这就会出现外部的foo方法内部的this会丢失指向。

    为了解决这个问题,我们需要在实例化对象的时候,需要在构造函数中绑定this,使得无论事件处理函数如何传递,它的this的指向都是固定的,固定指向我们所实例化的对象。

    原文链接:https://blog.csdn.net/u013003052/article/details/87894194

  • 相关阅读:
    植物大战僵尸游戏内存地址
    Win7如何取消用户登陆界面
    Adobe PS CS6安装详解
    MVC 支持同名路由,不同命名空间
    Session阻塞 读写锁引发的小问题
    GZipStream 压缩和解压
    IIS 工作原理之非托管代码旅程(一)
    Http协议(一)
    Css学习笔记 (一)
    Linq二 LinqToSql
  • 原文地址:https://www.cnblogs.com/yangwenbo/p/11447333.html
Copyright © 2011-2022 走看看