• this的那些事


    this用法

    全局上下文

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

    // 在浏览器中, window 对象同时也是全局对象:
    console.log(this === window); // true
    
    a = 37;
    console.log(window.a); // 37
    
    this.b = "MDN";
    console.log(window.b)  // "MDN"
    console.log(b)         // "MDN"


    函数上下文

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

    因为下面的代码不在严格模式下,且 this 的值不是由该调用设置的,所以 this 的值默认指向全局对象,浏览器中就是 window。

    function f1(){
      return this;
    }
    //在浏览器中:
    f1() === window;   //在浏览器中,全局对象是window
    
    //在Node中:
    f1() === globalThis;
    function f2(){
      "use strict"; // 这里是严格模式
      return this;
    }
    
    f2() === undefined; // true

    在第二个例子中,this 应是 undefined,因为 f2 是被直接调用的,而不是作为对象的属性或方法调用的(如 window.f2())。有一些浏览器最初在支持严格模式时没有正确实现这个功能,于是它们错误地返回了window对象。

    类上下文

    this 在 类 中的表现与在函数中类似,因为类本质上也是函数,但也有一些区别和注意事项。
    在类的构造函数中,this 是一个常规对象。类中所有非静态的方法都会被添加到 this 的原型中:
    class Example {
      constructor() {
        console.log("Example--this", this)
        const proto = Object.getPrototypeOf(this);
        console.log(Object.getOwnPropertyNames(proto));
      }
      first(){}
      second(){}
      static third(){}
    }
    
    new Example(); // ['constructor', 'first', 'second']
    // 注意:静态方法不是 this 的属性,它们只是类自身的属性。
    // 对象可以作为 bind 或 apply 的第一个参数传递,并且该参数将绑定到该对象。
    var obj = {a: 'Custom'};
    
    // 声明一个变量,并将该变量作为全局对象 window 的属性。
    var a = 'Global';
    
    function whatsThis() {
      return this.a;  // this 的值取决于函数被调用的方式
    }
    
    whatsThis();          // 'Global' 因为在这个函数中 this 没有被设定,所以它默认为 全局/ window 对象
    whatsThis.call(obj);  // 'Custom' 因为函数中的 this 被设置为obj
    whatsThis.apply(obj); // 'Custom' 因为函数中的 this 被设置为obj

    显示的改变的指向 call、apply、bind方法

    this 和对象转换

    function add(c, d) {
      return this.a + this.b + c + d;
    }
    
    var o = {a: 1, b: 3};
    
    // 第一个参数是用作“this”的对象
    // 其余参数用作函数的参数
    add.call(o, 5, 7); // 16
    
    // 第一个参数是用作“this”的对象
    // 第二个参数是一个数组,数组中的两个成员用作函数参数
    add.apply(o, [10, 20]); // 34

    在非严格模式下使用 call 和 apply 时,如果用作 this 的值不是对象,则会被尝试转换为对象。null 和 undefined 被转换为全局对象。原始值如 7 或 'foo' 会使用相应构造函数转换为对象。因此 7 会被转换为 new Number(7) 生成的对象,字符串 'foo' 会转换为 new String('foo') 生成的对象。

    function bar() {
      console.log(Object.prototype.toString.call(this));
    }
    
    bar.call(7);     // [object Number]
    bar.call('foo'); // [object String]
    bar.call(undefined); // [object global]

    bind方法(返回的一个函数)

    ECMAScript 5 引入了 Function.prototype.bind()。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了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
    
    var o = {a:37, f:f, g:g, h:h};
    console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty

     隐式改变this指向

    function A(name){
      
      this.name=name
      console.log('A-->', this)
    }
    
    let a1 =new A('lucy')
    console.log('a1', a1.name, a1.__proto__, a1.__proto__==A.prototype)

    可以看到实例a1.  this指向构造函数

    一般谁调用this指向谁,对象调用指向对象,函数调用指向函数,如果函数有返回值返回值不是对象类型,this还是指向函数的实例

    箭头函数比较特殊

    箭头函数在箭头函数中,this与封闭词法环境的this保持一致。在全局代码中,它将被设置为全局对象:

    var globalObject = this;
    var foo = (() => this);
    console.log(foo() === globalObject); // true

    注意:如果将this传递给call、bind、或者apply来调用箭头函数,它将被忽略。不过你仍然可以为调用添加参数,不过第一个参数(thisArg)应该设置为null。

    // 接着上面的代码
    // 作为对象的一个方法调用
    var obj = {foo: foo};
    console.log(obj.foo() === globalObject); // true
    
    // 尝试使用call来设定this
    console.log(foo.call(obj) === globalObject); // true
    
    // 尝试使用bind来设定this
    foo = foo.bind(obj);
    console.log(foo() === globalObject); // true

     来几个例子

    let name="globalname"
    const obj = {
      name: 'lily',
      age: ()=>{
        console.log("obj-age", this, '--', this.name, '--name--',name)
        function demo(){
          console.log("obj-demo", this, '--',this.name, '--name--',name)
        }
        demo()
        
      },
      bar: function() {
        console.log('obj--bar>', this, '--',this.name)
        const x = (() =>  this.name);
        console.log('obj--x>', this, '--', x())
        
      }
    };
    obj.age()
    obj.bar()

    在来几个例子

    function fn1()
    {
        this.name = 'hello1';
        return {};
    }
    var a = new fn1();
    console.log(a.name); //undefined
    
    function fn2()  
    {  
        this.age = 18;  
        return function(){};
    }
    var a = new fn2();  
    console.log(a.age); //undefined
    
    function fn3()
    {
      this.name = 'hello3';
        return 1;
    }
    var a = new fn3;
    console.log(a.name); //hello3

    obj={
      name: 'hi',
      fn: function(){
        setTimeout(() => {
          console.log(this, this.name)
        }, 200);
      }
    }
    obj.fn()

    待更新

  • 相关阅读:
    链表与顺序表
    js对table的动态操作
    关于float的内部结构
    spring bean的生命周期
    浅谈(吐槽)自己
    java缓存机制(上)
    Verilog经典输入控制/激励信号模板1
    verilog中的for循环问题
    2015,welcome!!!
    (转)Quartus II和Modelsim的联合仿真(详细)
  • 原文地址:https://www.cnblogs.com/pikachuworld/p/15067248.html
Copyright © 2020-2023  润新知