最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript深入之从ECMAScript规范解读this

    正文概述 掘金(齐铭)   2021-03-03   841

    JavaScript深入之从ECMAScript规范解读this

    (深入js系列读后感> github.com/mqyqingfeng…)

    Types

    ECMAScript 有两种类型,语言类型和规范类型

    语言类型 就是常说的数据类型,比如 Undefined、Null、String 等等

    规范类型 是用来用算法描述 ECMAScript 语言结构和 ECMAScript 语言类型的。规范类型包括:Reference, List, Completion, Property Descriptor, Property Identifier, Lexical Environment, 和 Environment Record。

    总结:这些都不重要,只需要知道 ECMAScript 还有一种只存在与规范中的类型,用来描述语言底层行为逻辑

    Reference

    Reference 是规范类型的一种,用来解释语言的底层行为逻辑才存在的,比如 delete、typeof 以及复制等操作行为。

    (上面这句话有点难以理解,只需要知道有这么回事就行,记住 Reference 是规范类型的一种)

    Reference 的构成:

    • base value (base):属性所在的对象或者 EnvironmentRecord,它的值只可能是 undefined, an Object, a Boolean, a String, a Number, or an environment record 其中的一种。
    • referenced name (name): 属性名
    • strict reference (strict): 是否是严格模式

    举个例子:

    var foo = 1
    
    // 对应的 Reference :
    var fooReference = {
    	base: EnviromentRecord,
    	name: 'foo',
    	strict: false
    }
    

    再举个例子

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

    介绍几个和 Reference 相关的方法:GetBase、IsPropertyReference、GetValue

    1. GetBase: 获取 Reference 中 base 的值

    2. IsPropertyReference: 判断 Reference 中 base 是否为对象,是 返回 true, 否 返回 false

    3. GetValue: 返回的将是属性具体的值,而不是一个 Reference ,这个很关键

      简单模拟 GetValue 的使用

      var foo = 1
         
      // 对应的 Reference :
      var fooReference = {
      	base: EnviromentRecord,
      	name: 'foo',
      	strict: false
      }
      GetValue(fooReference) // 1
      

    重点记忆一下这三个方法,后面判断 this 时,会用到!!!

    确定 this 的值

    ES5 的规范中讲了当函数调用当时候,如何确定 this 的值。主要看1、6、7点。

    主要意思:

    1. 计算 MemberExpression 的结果赋值给 ref

    什么是 MemberExpression ?举个例子:

    function foo() {
    	console.log(this)
    }
    foo()  // MemberExpression 是 foo
    
    function foo() {
    	return function() {
    		console.log(this)
    	}
    }
    
    foo()() // MemberExpression 是 foo()
    
    var foo = {
        bar: function () {
            return this;
        }
    }
    
    foo.bar(); // MemberExpression 是 foo.bar
    

    简单来说,函数调用的时候,() 左边的部分就是 MemberExpression 的值

    1. 根据 ES5 规范,判断 ref 是不是一个 Reference 类型

    2. 如果 ref 是 Reference,并且 IsPropertyReference(ref) (判断 Reference 中 base 是否为对象,上面有解释) 是 true,那么 this 的值为 GetBase(ref) (获取 Reference 中 base 的值,上面有解释)

    3. 如果 ref 是 Reference,并且 GetBase(ref)EnvironmentRecord,那么 this 的值为 ImplicitThisValue(ref) (查看规范 10.2.1.2.6,ImplicitThisValue 方法的介绍:该函数始终返回 undefined)

    4. 如果 ref 不是 Reference,那么 this 的值为 undefined

    小试牛刀

    var value = 1;
    
    var foo = {
      value: 2,
      bar: function () {
        return this.value;
      }
    }
    
    function foo1() {
    	console.log(this)
    }
    
    // 示例1
    console.log(foo.bar())
    // 示例2
    console.log((foo.bar)())
    // 示例3
    console.log((foo.bar = foo.bar)())
    // 示例4
    console.log((false || foo.bar)())
    // 示例5
    console.log((foo.bar, foo.bar)())
    // 示例6
    foo1()
    
    1. 示例1

      1. ref = foo.bar

      2. 判断 ref 是否为 Reference,根据 ES5 规范 11.2.1 (Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.) 判断,当以 . 的方式访问属性时,返回 Reference。结论 ref 是 Reference 类型

        var Reference = {
          base: foo,
          name: 'bar',
          strict: false
        }
        
      3. this 的值为 GetBase(ref) 就是 foo

    2. 示例2

      1. ref = (foo.bar)
      2. 根据 ES5 规范 11.1.6 (Return the result of evaluating Expression. This may be of type Reference.) 判断,() 并没有对 ref 进行计算,所以和 示例1 的结果一致
    3. 示例3

      1. ref = (foo.bar = foo.bar)
      2. 根据 ES5 规范 11.13.1 判断,等号操作返回值为 GetValue('等号右边属性') ,根据上面 GetValue 介绍,调用 GetValue 返回的将是属性具体的值,而不是 Reference
      3. 按照判断 this 的逻辑,ref 不是 Reference ,那么 this 的值为 undefined,在非严格模式下,this 的值为 undefined 的时候,其值会被隐式转换为全局对象
    4. 示例4

      1. ref = (foo.bar || foo.bar)
      2. 根据ES5规范 11.11 判断,二元逻辑操作返回值会调用 GetValue,所以和 示例三 一致
    5. 示例5

      1. ref = (foo.bar, foo.bar)
      2. 根据ES5规范 11.14 判断,逗号操作返回值会调用 GetValue,所以和 示例三 一致
    6. 示例6

      1. ref = foo1

      2. 根据ES5规范 10.3.1 判断,标识符的引用,返回一个 Reference 类型的值

        var foo1Reference = {
        	base: EnvironmentRecord,
        	name: 'foo',
        	strict: false
        }
        
      3. 按照判断 this 的逻辑,ref 是 Reference,判断 IsPropertyReference(ref) 是 true 还是 false,根据 IsPropertyReference 的描述 (判断 Reference 中 base 是否为对象),这里的 base 为 EnvironmentRecord,不是 Object 类型

      4. 因为 IsPropertyReference(ref) 为 false,再判断 GetBase(ref) 的值,正是 environment record ,所以 this 的值为 ImplicitThisValue(ref),根据上面介绍,该函数返回 undefined


    起源地下载网 » JavaScript深入之从ECMAScript规范解读this

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元