this

作者: 撕心裂肺1232 | 来源:发表于2019-03-09 16:21 被阅读0次

    2019年3月9日 中雨 14°C~17°C
    广州持续下来很久很久的雨,一个星期?两个星期?忘了,又加上回南天,衣服不干,emmmm...

    一、this的用法

    this是函数运行时,在函数体内自动生成的一个对象,只有在函数体内部使用。

    function test(){
       this.x = 1;
    }
    //函数test运行时,内部会自动生成一个this对象可以使用
    

    函数的不同使用场合,this有不同的值。总的来说,this是函数运行时所在的环境对象

    this的用法

    1. 纯粹的函数调用

    全局调用,函数最常用的方法,此时this代表全局对象。

    var x = 1;
    function test(){
      console.log(this.x);
    }
    test();    //1
    
    2.作为对象的调用方法

    函数可以作为对象的方法来被调用,此时this指向这个对象。

    function test(){
      console.log(this.x)
    }
    var obj = {};
    obj.x = 1;
    obj.m = test;
    obj.m();         //1
    
    3.作为构造函数调用

    通过构造函数,可以生成一个新的对象。这是,this指向这个新的对象。

    var x = 2;
    function test(){
      this.x = 1;
    }
    var obj = new test();
    x   // 2
    obj.x  //1;
    
    4. apply调用

    apply()是函数的一个方法,作用是改变函数的调用对象,它的第一个函数就表示改变后调用这个函数的对象。此时this指的就是这第一个参数。

    var x = 0;
    function test() {
      console.log(this.x);
    }
    var obj = {};
    obj.x = 1;
    obj.m = test;
    obj.m.apply();   //0
    

    apply()的参数为空时,默认调用全局对象,因此,运行结果为0,this指向全局对象。
    如果:

    obj.m.apply(obj);    //1
    

    运行结果变成了1,this指向对象obj;

    二、this的原理

    1. 由来
    var obj = {
      foo: function() { console.log(this.bar)},
    bar: 1
    }
    
    var foo = obj.foo;
    var bar = 2;
    
    //写法一
    obj.foo();  // 1
    
    //写法二
    foo();    // 2
    

    **this指的是函数运行时所在的环境,对于obj.foo,foo运行在obj环境,所以this指向obj,对于foo()来说,foo运行在全局环境,所以this指向全局环境。
    函数的运行环境是怎么决定的?

    2. 内存的数据结构
    var obj = { foo: 5};
    

    上面代码将一个对象赋值给变量obj,①JavaScript引擎会先在内存里面生成一个对象{ foo: 5},② 然后把这个对象的内存地址赋值给变量obj。

    所以,变量obj是一个地址,如果要读取obj.foo,引擎会先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

    原始的对象以字典结构保存,每一个属性名称都对应一个属性描写对象。如上例子foo属性,实际上是以下面的形式保存:

    {
      foo: {
        [[value]]: 5
        [[writable]]: true
        [[enumerable]]: true
        [[configurable]]: true
      }
    }
    

    foo属性的值保存在属性貌似对象的value属性里面。

    3. 函数

    上面讲到对象的属性的值是一个值,二属性的值也可能是一个函数。

    var obj = { foo: 5};
    
    var obj = { foo: function(){} };
    

    这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。
    其实思路和上面的一样,只不过多了一个步骤:①引擎会将函数单独保存在内存中,②然后在内存里生成一个对象,对象的foo属性的value值是函数的内存地址,③将对象赋值给obj

    var f = function() {};
    var obj = {f : f};
    
    f();   //单独执行
    
    obj.f();    //obj环境执行
    
    4. 环境变量

    在函数体内部,可以引用当前环境的其他变量

    var f = function() {
      console.log(x);
    }
    
    //函数体的变量x,由运行环境提供
    

    由于函数可以在不同的运行环境中执行,this被设计于在函数体内部,指代函数当前的运行环境(context)。

    var f = function() {
      console.log(this.x);
    }
    
    //this.x 指当前运行环境的x
    
    var f = function() {
      console.log(this.x);
    }
    var x = 1;
    var obj = {
      f: f,
      x: 2
    }
    
    
    f()   // 1, f()在全局环境执行
    
    obj.f()   //2
    

    三、this的指向形式(4种)

    (1)一般函数,this指向全局对象window;
    (2)在严格模式下“use strict”,为undefined;
    (3)对象的方法里调用,指向该方法的对象;
    (4)构造函数里的this,指向创建出来的实例

    四、改变this的指向形式

    .call()

    call(thisScope,arg1,arg2,arg3...)
    thisScope为新的指向

    .apply()

    .apply(thisScope,[arg1,arg2,arg3...])
    两个参数,thisScope为新的指向

    bind()

    bind(thisScope,arg1,arg2,arg3...)
    改变this的指向,返回的是函数,还需调用,而call()和apply()是改变this的指向并执行调用该函数

    2019年3月8日 小雨
    准备换工作之际,在几乎毫无准备的情况下,去面试了一家公司,面试官提到了怎样改变this的指向,我答不出。
    于是去翻了阮一峰大神的博客,
    JavaScript的this用法http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
    JavaScript的this原理http://www.ruanyifeng.com/blog/2018/06/javascript-this.html
    还有看了一篇简洁的总结
    https://www.jianshu.com/p/c415530030a9

    相关文章

      网友评论

          本文标题:this

          本文链接:https://www.haomeiwen.com/subject/cxpspqtx.html