第6、7步,就是决定函数调用的 this 的值的关键步骤,翻译一下,如同下面的伪代码:
var thisValue = getThisValue(ref) function getThisValue(ref) { // 判断 ref 的类型是否是 Reference,如果不是,直接返回 undefined if(Type(ref) !== Reference) return undefined // 是否是 Object, Boolean, String, Number if(IsPropertyReference(ref)) { return GetBase(ref) } else { // 是一个环境记录项(Environment record),调用其 ImplicitThisValue 方法 return GetBase(ref).ImplicitThisValue() } }关于 GetBase 和 IsPropertyReference 方法:
GetBase(V), 返回引用值 V 的基值 (Reference 的基值 base,详见下面提到的 Reference 的组成)。
HasPrimitiveBase(V), 如果基值是 Boolean, String, Number,那么返回 true。
IsPropertyReference(V), 如果基值是个对象或 HasPrimitiveBase(V) 是 true,那么返回 true;否则返回 false。
而对于 ImplicitThisValue 方法,其属于环境记录项(Environment record)的方法。而环境记录项分为两种:
声明式环境记录项:每个声明式环境记录项都与一个包含变量和(或)函数声明的 ECMA 脚本的程序作用域相关联。声明式环境记录项用于绑定作用域内定义的一系列标识符。其 ImplicitThisValue 永远返回 undefined。
对象式环境记录项:每一个对象式环境记录项都有一个关联的对象,这个对象被称作 绑定对象 。对象式环境记录项直接将一系列标识符与其绑定对象的属性名称建立一一对应关系。其 ImplicitThisValue 通常返回 undefined,除非其 provideThis 标识的值为 true。具体如下:
令 envRec 为函数调用时对应的声明式环境记录项。
如果 envRec 的 provideThis 标识的值为 true,返回 envRec 的绑定对象。
否则返回 undefined。
对象式环境记录项可以通过配置的方式,将其绑定对象合为函数调用时的隐式 this 对象的值。这一功能用于规范 With 表达式(12.10 章 )引入的绑定行为。该行为通过对象式环境记录项中布尔类型的 provideThis 值控制,默认情况下,provideThis 的值为 false。(只有使用了 with 表达式,才会将 provideThis 标识的值为 true)
而上面提到了两种新的类型: 引用规范类型 (Reference)与 环境记录项(Environment record)都是属于ECMAScript 的规范类型,相当于 meta-values,是用来用算法描述 ECMAScript 语言结构和 ECMAScript 语言类型的。
而与规范类型相对于的就是语言类型:就是开发者直接使用的类型,即Undefined, Null, Boolean, String, Number, 和 Object。(ECMAScript的类型分为语言类型和规范类型)
从上面的伪代码中可以看到 thisValue 的值与 ref 是否是引用规范类型(Reference)有直接关联,即调用一个函数时,其()左侧的部分的解释执行的结果的类型是不是 Reference 类型,将直接影响 thisValue 的值。
EcmaScript 5.1标准中的 的规范:
8.7 引用规范类型 (Reference)
Reference 类型是用来说明 delete,typeof,赋值运算符这些运算符的行为。
一个 Reference 是个已解决的命名绑定。其由三部分组成, 基值 (base) , 引用名称(referenced name) 和布尔值 严格引用 (strict reference) 标志。
基值是 undefined, Object, Boolean, String, Number, Environment record 中的任意一个。基值是 undefined 表示此引用可以不解决一个绑定。引用名称是一个字符串。严格引用标志表示是否在严格模式下解释执行的代码。
而引用规范类型(Reference)会被用在标识符解析中,标识符执行的结果总是一个 Reference 类型的值。
EcmaScript 5.1标准中的 的规范:
10.3.1 标识符解析
标识符解析是指使用正在运行的执行环境中的词法环境,通过一个 标识符 获得其对应的绑定的过程。在 ECMA 脚本代码执行过程中,PrimaryExpression : Identifier 这一语法产生式将按以下算法进行解释执行:
令 env 为正在运行的执行环境的 词法环境 。
如果正在解释执行的语法产生式处在 严格模式下的代码 中,则仅 strict 的值为 true,否则令 strict 的值为 false。
以 env,Identifier 和 strict 为参数,调用 GetIdentifierReference 函数,并返回调用的结果。
解释执行一个标识符得到的结果必定是 Reference 类型的对象,且其引用名属性的值与 Identifier 字符串相等。
而 函数就是返回一个 Reference 类型的对象,类似如下对象:
var valueOfReferenceType = { base: <base object>, // Identifier 所处的环境(Environment Record)或者 Identifier 属性所属的对象 propertyName: <property name>, // 与 Identifier 字符串相等 strict: <boolean> };因此,我们可以来看一些相关的示例代码。