IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【前端学习日记四】利用ECMAScript规范研究学习this指向 -> 正文阅读

[JavaScript知识库]【前端学习日记四】利用ECMAScript规范研究学习this指向

前言

在第二节,我们深入学习了一下当js代码执行了一段可执行代码时,就会创建对应的上下文。
对于每个上下文,都有:变量对象(Variable object,VO),作用域链(Scope chain)
this这三个属性。

在之前我们详细研究了变量对象作用域链
这一次我们着重看看this


正文内容

ECMAScript

在了解this之前,我们根据其他大佬们的思路,还需要先学习一下ECMAScript是什么。

通俗易懂的ECMAScript讲解,可以先看看(也可以跳过看下面链接)
这是一个讲解ECMAScript的文档
接下来结合这个文档进行学习

emmm看着这巨长无比的文档…(暴风哭泣)好吧,剩下的有机会再琢磨,看了好久,罗列一下我们需要知道,理解this可能会用到的几点。

  • ECMAScript是JavaScript的规范,JavaScript是ECMAScript的一种实例
  • ECMAScript 是一种开放的、国际上广为接受的脚本语言规范。 它本身并不是一种脚本语言。
  • 我们把视线挪到第八章,第一段就是告诉了我们在这个ECMAScript规范中有两种类型, ECMAScript 语言类型规范类型
  • ECMAScript 语言类型就是我们常见的js中的类型,未定义 (Undefined)、 空值 (Null)、 布尔值(Boolean)、 字符串 (String)、 数值 (Number)、 对象 (Object)。
  • 规范类型就很麻烦了…引用一下概念,我们就可以大概理解为这些东西就是各种抽象的工具人,不由我们编成直接操作,在执行时系统各种使用,保证我们的程序运行。

规范类型 是描述 ECMAScript 语言构造与 ECMAScript 语言类型语意的算法所用的元值对应的类型。规范类型包括 引用(Reference) 、 列表 (List)、 完结(Completion) 、 属性描述式(Property Descriptor) 、 属性标示(Property Identifier) 、 词法环境(Lexical Environment)、 环境纪录(Environment Record)。规范类型的值是不一定对应 ECMAScript 实现里任何实体的虚拟对象。规范类型可用来描述 ECMAScript 表式运算的中途结果,但是这些值不能存成对象的变量或是 ECMAScript 语言变量的值。

而引用(Reference)类型是我们要进行学习的,它与 this 的指向有着密切的关联。


Reference类型

看完了8.7中的概念,不愧是专业解释,依旧晦涩难懂,对于我这样的小白并不友好,只好继续寻找其他大佬通俗易懂的解释。
通过查找,于是我们知道了几点关键的东西:

  • Reference 类型用来说明 delete,typeof,赋值运算符这些运算符的行为。
  • 这里的 Reference 是一个 Specification Type,也就是 “只存在于规范里的抽象类型”。它们是为了更好地描述语言的底层行为逻辑才存在的,但并不存在于实际的 js 代码中。js 代码中存在的基本类型就只有 Undefined, Null, Boolean, String, Number 和 Object。

好的继续往下看,我们知道了Reference Type本身是一个三个值的组合(base(对象),reference name(属性名),strict mode flag(严格模式下为true)),举个例子:

var a= 1;

// 对应的Reference是:
var aReference = {
    base: EnvironmentRecord,
    name: 'a',
    strict: false
};

再来一个

var a= {
    b: function () {
        return this;
    }
};
 
a.b();

// b对应的Reference是:
var bReference = {
    base: a,
    propertyName: 'b',
    strict: false
};

而且规范中还提供了获取 Reference 组成部分的方法,比如 GetBaseIsPropertyReference

GetBase方法

返回 reference 的 base value

//模拟一下使用方式
var value = 666;

var valueReference = {
    base: EnvironmentRecord,
    name: 'value',
    strict: false
};

GetValue(valueReference) // 666;

调用 GetValue,返回的将是具体的值,而不再是一个 Reference

IsPropertyReference方法

如果 base value 是一个对象,就返回true


如何确定this的值

有了之前那些基础知识,我们现在正式的看看这个this
我们把目光挪到11.2.3的位置

高能部分!!这部分原理当时写博客也琢磨了好久

我们先引用一下文档里的东西
截图
看完只有一个感受,晕过去了。MemberExpression 是啥?一头雾水。只好先硬着头皮往下看。

具体分析

一步一步看

  • 1.执行 MemberExpression 的结果赋值给 ref

MemberExpression :
PrimaryExpression // 原始表达式 可以参见《JavaScript权威指南第四章》
FunctionExpression // 函数定义表达式
MemberExpression [ Expression ] // 属性访问表达式
MemberExpression . IdentifierName // 属性访问表达式
new MemberExpression Arguments // 对象创建表达式

function A() {
}

A(); // MemberExpression 是 A
function A() {
    return function() {
    }
}

A()(); // MemberExpression 是 A()
var A = {
    B: function () {
        return this;
    }
}

A.B(); // MemberExpression 是 A.B

东拼西凑之后稍微理解了一点。
所以简单理解 MemberExpression 其实就是()左边的部分。

  • 2.判断 ref 是不是 Reference 类型。
    把文档里的东西搬过来:

2.1 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true, 那么 this 的值为 GetBase(ref)

2.2 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么this的值为 ImplicitThisValue(ref)

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


举例说明

var value = 100;

var A = {
  value: 200,
  B : function () {
    return this.value;
  }
}
//示例0
function F() {
    console.log(this)
}
F(); 

//示例1
console.log(A.B());
//示例2
console.log((A.B)());
//示例3
console.log((A.bar = A.B)());
//示例4
console.log((false || A.B)());
//示例5
console.log((A.B, A.B)());

示例零:这种是最常见的情况,MemberExpression 结果为 F,是一个标识符,根据文档,返回值显然是一个 Reference 类型
结果

var FReference = {
    base: EnvironmentRecord,
    name: 'F',
    strict: false
};

结果
符合第二种情况,继续查阅文档,发现返回值是 undefined,所以最后 this 的值就是 undefined。
图片

示例一:MemberExpression 结果为 A.B,显然是一个 Reference 类型,并且我们写的出来相关属性

var Reference = {
  base: A,
  name: 'B',
  strict: false
};

然后我们判断,显然符合第一个,于是
this = GetBase(ref),那this就是A了 ,所以示例一的结果是200
图片
示例二:MemberExpression 结果为 (A.B),显然是一个 Reference 类型,甚至可以说和第一个一样。最后示例二的结果是200

示例三:MemberExpression 结果为 (A.bar = A.B),这是个赋值表达式
图片
我们翻阅文档发现返回的这个东西是一个具体的值,而不再是一个 Reference,
所以,this指向 undefined,其值会被隐式转换为全局对象。于是找全局变量,结果是100
图片
示例四:MemberExpression 结果为 (false || A.B),是一个逻辑与的表达式
图片
所以和示例三一样,this指向 undefined,结果是100。

示例五:MemberExpression 结果为 (foo.bar, foo.bar),是一个逗号表达式
结果
所以和上两个一样,this指向 undefined,结果是100。

总结

尽管ECMAScript角度来看、看晦涩难懂的官方文档是一种进度十分缓慢的学习办法,但是可以从一个十分严谨的层次去理解。通过ECMAScript的角度来理解this,更加深入与透彻,如果仅仅将this理解为调用函数的对象,我们将会有很多东西无法从逻辑上解释的通,比如示例四五和示例零虽然都指向undefined,但是原因却大不相同。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-03 11:05:05  更:2021-08-03 11:05:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 4:15:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码