至简·this

雨中莫听哀曲,悲歌莫过童声。

规范抽象类型
Reference类型——只存在于规范里一种抽象类型,描述语言底层的行为逻辑,存在于规范类型中,不存在于语言类型中,不存在于实际的js代码中。

Reference的三个组成部分

  • base value
    (属性所存在的对象或者EnviromentRecord)(值:Undefined\Object\Boolean\String\Number\EnviromentRecord)

  • referenced name (属性的名称)

  • strict refernce (严格标志)

    例如:

      var foo = 1;
      //对应的Reference类型
      var fooRefrence = {
          base:EviromentRecord,
          name:'foo',
          strict:false
      };
	  var foo = {
	      bar:function(){
	          return this;
	      }
	  }
	  foo.bar();
	  //对应的Reference类型
	  var BarReference = {
	      base:foo,
	      name:'bar',
	      strict:false
	  }

获取规范抽象类型
1、GetBase–返回Reference的base value
2、IsPropertyRefernce,判断base value的类型,如果base value是一个对象返回true

GetValue 返回对象属性真正的值,调用了GetValue将返回一个具体的值,执行过GetValue,依据执行结果是否为Object就会返回Reference类型,若不是,不返回Reference类型

函数调用时如何确定this的取值

1、计算属性访问表达式MemberExpression的结果,赋给ref

    MemberExpression 分5种:
        PrimaryExpression // 原始表达式 
        FunctionExpression // 函数定义表达式
        MemberExpression [ Expression ] // 属性访问表达式
        MemberExpression.IdentifierName // 属性访问表达式
        new MemberExpression Arguments // 对象创建表达式

例子1:

    function foo(){
        console.log(this);
    }
    foo();  //MemberExpression是foo()

例子2:

    function foo(){
        return function(){
            console.log(this);  
        }
    }
    foo()();  //MemberExpression是foo()

例子3:

    var foo = {
        bar:function(){
            return this;
        }
    }
    foo.bar();  //MemberExpression是foo.bar
    //简单理解 MemberExpression 其实就是()左边的部分。

2、判断ref是否是一个Reference类型
2.1 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true(即Reference是Object), 那么 thisValue 的值为 GetBase(ref),也就是Reference中的base value
2.2 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么thisValue的值为 ImplicitThisValue(ref),它的返回结果,而ImplicitThisValue函数始终返回undefined
2.3 如果 ref 不是 Reference,那么 this 的值为 undefined

//解析
var value = 1;
var foo = {
    value : 2,
    bar : function(){
        console.log(this.value);
    }
}

console.log(foo.bar());
console.log((foo.bar)());
console.log((foo.bar = foo.bar)());
console.log((false || foo.bar)());
console.log((foo.bar,foo.bar)());

分析
//第一条:
/*
*   1.获取对应的Reference,即:
        var Reference = {
            base:foo,
            name:'bar',
            strict:false
        };
*   2.--2.1 获取MemberExpression的结果,即foo.bar,赋给ref
            baseValue 等于 GetValue(baseReference) 。
       --2.2 通过IsPropertyReference检查ref的类型,IsPropertyReference判断base value,base value是对象,返回true,因此thisValue的值为GetBaseValue(ref),即base value的值,所以this为foo,那么访问的value就是2
        
*/

//第二条
/*
*    1.获取对应的Reference,即:
        var Reference = {
            base:foo,
            name:'bar',
            strict:false
        };

*   2.获取的MemberExpression也为foo.bar,()并没有对MemExpression进行计算,所以,后续的分析均与第一条相同,结果也相同
        
*/

//第三条
/*
*   1.获取对应的Reference,即:
        var Reference = {
            base:foo,
            name:'bar',
            strict:false
        };
        
*   2.获取的MemberExpression为(foo.bar == foo.bar),存在赋值操作,调用GetValue方法,调用了GetValue方法后返回[Object Function]类型,不是Reference类型,
    那么thisValue将为undefined,默认指向window

    注意:简单赋值语句返回的是对等于号右边进行GetValue之后的结果,GetValue会返回js的类型,此处会返回 foo.bar的类型也就是一个 [Object Function] 类型,即不是一个Reference类型,所以this就为undefined,
    规范中 if thisArg is null or undefined, set the ThisBinding to the global object.
    所以this指向window
*/

//第四条
/*
*    1.获取对应的Reference,即:
        var Reference = {
            base:foo,
            name:'bar',
            strict:false
        };

*   2.获取的MemberExpression为(flase || foo.bar),逻辑运算,同样调用GetValue方法,结果与第三条一致
*/


//第五条
/*
*   1.获取对应的Reference,即:
        var Reference = {
            base:foo,
            name:'bar',
            strict:false
        };

*   2.获取的MemberExpression为(foo.bar , foo.bar),逗号操作符,同样调用GetValue方法,结果与第三条一致
*/

普通函数调用

 function foo(){
        console.log(this);
    }
 foo();
//分析:
/*
    1.获取Reference:
        var Reference = {
            base:EnviromentRecord,
            name:'foo',
            strict:false
        }
    2.获取MemberExpression即foo,IsPropertyReference判断base value类型,base value是EnviromentRecord,此处会调用ImplicitThisValue(),这个函数始终返回undefined,所以thisValue为undefined,那么this指向window

*/

//对直接this理解的推翻:
//简单的理解this就是调用函数的对象的问题

  var value = 1;
    var foo = {
        value : 2,
        bar : function(){
            console.log(this.value);
        }
    }
    console.log((false || foo.bar)());

在这个函数调用的情况下,不能确定调用函数的对象,又如何判定this的指向呢?所以还是看规范吧!

最后附一张this速查表,这张表是对一般情况的一些总结。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值