朋友们,美好的一天!在本文中,我们从规范中获取一个功能并分析其解释。走。前言
即使您非常了解JavaScript,也很难阅读规范。以下代码演示了Object.prototype.hasOwnProperty的用法:const o = {
foo: 1
}
o.hasOwnProperty('foo')
o.hasOwnProperty('bar')
在示例中,“ o”对象没有“ hasOwnProperty”方法,因此我们引用其原型-“ Object.prototype”(原型链)。为了描述Object.hasOwnProperty的工作方式,该规范使用以下伪代码:Object.prototype.hasOwnProperty(V)使用参数V调用hasOwnProperty时,将执行以下步骤:
...和HasOwnProperty(O,P)
HasOwnProperty抽象操作用于确定对象是否具有自己的具有特定键的属性。返回布尔值。使用参数O和P调用该操作。此操作包括以下步骤:
什么是“抽象操作”?什么 [[ ]]?函数为什么有问号?“确认”是什么意思?
让我们找出答案。- P ? ToPropertyKey(V)
- O ? ToObject( this)
- ? HasOwnProperty(O, P).
- (assert): Type(O) Object.
- : IsPropertyKey(P) true.
- desc ? O.[[GetOwnProperty]](P).
- desc undefined, false.
- true.
语言类型和规范中的类型
让我们从熟悉的事物开始。在规范中,有JS已知的未定义,正确和错误的值。它们都是``语言值'',``语言类型的值' ',它们也由规范定义。该规范使用内置的语言值,例如,内部数据类型可能包含值为true或false的字段。 JS引擎通常在其内部机制中不使用语言含义。例如,如果JS引擎是用C ++编写的,则很可能会使用C ++中的true和false,而不是JS中布尔值的内部表示形式。除语言类型外,规范还使用特殊类型(规范类型)-仅在规范中使用的类型。不需要JS引擎来执行它们(但是可以)。在本文中,我们将熟悉特殊类型的“记录”(记录)及其子类型“完成记录”(完成记录)。抽象操作
抽象操作是规范中定义的功能;定义它们是为了减少规格。不需要JS引擎将其作为独立功能执行。在JS中,不能直接调用它们。内部插槽和内部方法
内部插槽和内部方法由[[]]中的名称指示。内部插槽是JS对象或特殊类型的数据元素(集合)。它们用于存储有关对象状态的信息。内部方法是JS对象的成员函数。例如,每个JS对象都有一个内部[[Prototype]]插槽和一个内部[[GetOwnProperty]]方法。内部插槽和方法在JS中不可用。例如,我们无法访问o。[[Prototype]]或调用o。[[GetOwnProperty]]()。 JS引擎可以根据自己(内部)的需要执行它们,但是不需要这样做。有时内部方法变成同名的抽象操作,例如[[GetOwnProperty]]:[[GetOwnProperty]](P)当用键“ P”调用“ O”对象的[[GetOwnProperty]]内部方法时,将执行以下操作:
OrdinaryGetOwnProperty不是内部方法,因为它与任何对象都没有关联;与它一起工作的对象作为参数传递给它。
OrdinaryGetOwnProperty之所以称为“普通”,是因为它对普通对象进行操作。 ECMAScript中的对象是普通的和异常的(异国情调)。如果对象对称为基本内部方法的一组方法做出可预测的行为,则它是普通的。否则(当对象的行为不可预测;不符合预期;当对象的行为偏离正常时,是异常的),则认为这是异常的。- ! OrdinaryGetOwnProperty(O, P)
最著名的异常对象是Array,因为其“ length”属性的行为不规范:设置此属性可以从数组中删除元素。可以在此处找到基本内部方法的列表。完成记录
那问号和感叹号呢?要了解这一点,您需要了解什么是完成记录。完成记录是一种特殊类型(仅出于规范目的而定义)。JS引擎不需要具有相同的内部数据类型。完成记录是一种具有一组固定的命名字段的数据类型。完成记录包含三个字段:每个抽象操作都隐式返回完成记录。即使抽象操作的结果是一个简单的逻辑值,也将其包装在normal类型的完成记录中(请参阅隐式完成值)。注1:这部分的规格不一致。有几个帮助程序函数返回裸值,这些裸值按原样使用,而不会从完成记录中检索出来。注2:规范作者试图使完成记录处理更加明确。如果算法引发异常,则这意味着将接收到具有类型([[Type]])引发和值([[Value]])作为异常对象的完成记录。我们暂时不会考虑其他类型(中断,继续和返回)。ReturnIfAbrupt(参数)表示执行以下操作:
这是完成记录;如果突然结束,请立即返回。否则,我们从完成记录中提取值。
ReturnIfAbrupt看起来像一个函数调用,但事实并非如此。我们调用一个返回ReturnIfAbrupt()的函数,而不返回ReturnIfAbrupt本身。它的行为更像是C语言编程语言中的宏。
ReturnIfAbrupt可以使用如下:
这里进场- argument - (abrupt), argument.
- argument argument.[[Value]].
- obj Foo() (obj - ).
- ReturnIfAbrupt(obj).
- Bar(obj) ( , , obj - , ).
问号:记录 ? Foo()等同于ReturnIfAbrupt(Foo())。使用此缩写有实际价值:我们不需要每次都编写错误处理程序代码。打个比方,让val作为入口! Foo()等效于以下内容:
使用此知识,我们可以按以下方式重写Object.prototype.hasOwnProperty:
Object.prototype.hasOwnProperty(P)
... HasOwnProperty可以这样重写:
HasOwnProperty(O,P)
我们也可以重写内部方法[没有惊叹号的[GetOwnProperty]:
O。[[GetOWnProperty]] 我们假设temp是一个新的临时变量,不会与任何东西交互。- val Foo().
- : val .
- val val.[[Value]].
- P ToProperty(V).
- P , P.
- P P.[[Value]].
- O ToObject( this).
- O , O.
- O O.[[Value]].
- temp HasOwnProperty(O, P).
- temp , temp.
- temp temp.[[Value]].
- NormalCompletion(temp).
- : Type(O) Object.
- : IsPropertyKey(P) true.
- desc O.[[GetOWnProperty]](P).
- desc , desc.
- desc desc.[[Value]].
- desc undefined, NormalCompletion(false).
- NormalCompletion(true).
- temp OrdinaryGetOwnProperty(O, P).
- : temp .
- temp temp.[[Value]].
- NormalCompletion(temp).
我们还知道,在return语句返回除完成记录以外的内容的情况下,此内容隐式包装在NormalCompletion中。后备:返回?富()
规范是否使用Return?Foo()-为什么在这里会有问号?记录退货?Foo()可以扩展如下:
返回行为?Foo()对于正常终止和突然终止都是相同的。
记录退货?Foo()可让您更清楚地指示Foo返回完成记录。- temp Foo().
- temp , temp.
- temp temp.[[Value]].
- NormalCompletion.
陈述
规范中的声明“声明”了算法的不变条件。为了清楚起见,将它们添加到规范中,但不包含任何实现要求;因此,不需要通过特定实现来验证它们。下一步是什么?
我们学会了阅读有关Object.prototype.hasOwnProperty之类的简单方法和诸如HasOwnProperty之类的抽象操作的规范。有了这些知识,我们就可以了解其他抽象操作的作用,这将在下一部分中进行讨论。同样在下一篇文章中,我们将研究属性描述符,这是另一种特殊类型。
感谢您的关注。编码愉快!