We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
可以配合重学js —— js数据类型(四):Object 基础介绍(内部方法和内置插槽等)查看。
主要讲了 Object 一些api的内部算法过程以及普通对象的生成过程。
所有的普通对象都有一个叫 [[Prototype]] 的内置插槽。该内置插槽的值要么是 null 要么是一个用来实现继承的对象。该 [[Prototype]] 对象的 数据属性 是为了get 使用而不是 set 使用 而继承(作为子对象的属性可见)的。访问器属性是为 get 使用和 set 使用继承的。
每个普通对象有个布尔值 [[Extensible]] 内置插槽,它用于实现基本内部方法的不变量中指定的与可扩展性相关的内部方法不变量。即,一旦对象的 [[Extensible]] 内部插槽值被设为 false,那么:
其实对应 Object.preventExtensions()。
在接下来的算法描述中,假设 O 是普通对象,P 是属性键,V 是任何ECMAScript语言值,Desc 是属性描述符 record。
每个普通的对象内部方法都委托给一个类似名称的抽象操作。如果一个抽象操作依赖于另一个内部方法,那么该内部方法在 O 上被调用,而不是直接调用类似名称的抽象操作。这些语义确保将普通对象内部方法应用于奇异对象时,将调用奇异对象自己覆盖的内部方法。
当 O 的 [[GetPrototypeOf]] 内部方法被调用时:
断言:V 的类型要么是对象要么是 Null.
定义 current 变量,值为 O.[[Prototype]].
如果 SameValue(V, current) 结果为 true,返回 true。
定义 extensible 变量,值为 O.[[Extensible]].
如果 extensible 是 false,返回 false.(不可扩展)
定义 p 变量,值为 V.
定义 done,值为 false.
如果 done 是 false 的话,重复以下步骤:
8.1 如果 p 是 null,将 done 设为 true
8.2 否则如果 SameValue(p, O) 结果为 true,返回 false(这一步防止对象将自身设为自己的原型对象)
8.3 否则,
将 O.[[Prototype]] 的值设为 V
返回 true
步骤8中的循环保证在任何原型链中都不会有循环,该原型链仅包括使用 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 的普通对象定义的对象。
O 是对象,P是属性名。目的拿属性描述符!
断言:IsPropertyKey(P)为 true
如果 O 自身没有属性 P,返回 undefined
定义 D,值为新创建且没有任何字段的属性描述符
定义 X,值为 O.P
如果 X 是数据属性
5.1 设置 D.[[Value]] 为 X 的 [[Value]] 属性值
5.2 设置 D.[[Writable]] 为 X 的 [[Writable]] 属性值
否则,
6.1 断言 X 为访问器属性
6.2 设置 D.[[Get]] 为 X 的 [[Get]] 属性值
6.3 设置 D.[[Set]] 为 X 的 [[Set]] 属性值
设置 D.[[Enumerable]] 为 X 的 [[Enumerable]] 属性值
设置 D.[[Configurable]] 为 X 的 [[Configurable]] 属性值
返回 D
O.[[GetOwnProperty]](P)
注意:如果 O 是 undefined,仅执行校验,不会执行对象更新!
断言:如果 O 不是 undefined,那么IsPropertyKey(P)结果为 true
如果 current 是 undefined,
a. 如果 extensible 是 false,返回 false
b. 断言:extensible 是 true
c. 如果 IsGenericDescriptor(Desc) 结果是 true 或者 IsDataDescriptor(Desc) 结果是 true
d. 否则
e. 返回 true
如果 Desc 每个字段都缺失,返回 true
如果 current.[[Configurable]] 是 false,
a. 如果 Desc.[[Configurable]] 存在且值为 true,返回 false
b. 如果 Desc.[[Enumerable]] 存在且 ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) 结果为 false,返回 false
如果 IsGenericDescriptor(Desc) 结果是 true
a. 注意:无需进一步验证
如果 ! SameValue(! IsDataDescriptor(current), ! IsDataDescriptor(Desc)) 结果为 false,
a. 如果 current.[[Configurable]] 为 false,返回 false b. 如果 IsDataDescriptor(current) 结果为 true,
c. 否则
如果 IsDataDescriptor(current) 和 IsDataDescriptor(Desc) 结果都是 true,
a. 如果 current.[[Configurable]] 是 false 并且 current.[[Writable]] 也是 false,
a. 断言:! IsAccessorDescriptor(current) 和 ! IsAccessorDescriptor(Desc) 都为 true
b. 如果 current.[[Configurable]] 是 false,
如果 O 不是 undefined,
a. Desc 每个字段都存在,将对象 O 的 P 属性描述符中相应属性设置为字段的值
获取对象属性值。
该方法就是各种文章博客说的,数据属性直接返回 [[Value]] 值,访问器属性返回 [[Get]] 调用后的结果值
以前看网上某些文章,讲到访问器对象时,会冒出 getter 这个名词,我当时打印控制台愣是找不到它,心想是哪位大佬定义的然后流传开来,今天才知道,规范就这么定义的!
O.[[GetPrototypeOf]]()
parent.[[Get]](P, Receiver)
parent.[[Set]](P, V, Receiver)
Receiver.[[GetOwnProperty]](P)
Receiver.[[DefineOwnProperty]](P, valueDesc)
OrdinaryDelete ( O, P )
带参数 proto(对象或null)的抽象操作 OrdinaryObjectCreate 用于指定新的普通对象的运行时创建。可选参数 additionalInternalSlotsList 是必须定义为对象一部分的除 [[Prototype]] 和 [[Extensible]] 之外其他内部插槽名称的 List。如果该 List 未提供,将会使用一个新的空 List。
该抽象操作创建一个普通对象,如果构造器的 "prototype" 属性存在,那么该对象的 [[Prototype]] 值从它取得。否则,将 internalDefaultProto 用于 [[Prototype]]。可选的 internalSlotsList 是一个 List,其必须是对象的一部分其它内部插槽的名称。
"prototype"
确定用于创建与特定构造函数相对应的对象的 [[Prototype]] 值。
[[Prototype]]
注意:如果 constructor 不提供 [[Prototype]] 值,使用的默认值是从构造函数的领域而不是从正在运行的执行上下文中获取的。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
普通对象和奇异(怪异)对象行为
普通对象内部方法和内置插槽
所有的普通对象都有一个叫 [[Prototype]] 的内置插槽。该内置插槽的值要么是 null 要么是一个用来实现继承的对象。该 [[Prototype]] 对象的 数据属性 是为了get 使用而不是 set 使用 而继承(作为子对象的属性可见)的。访问器属性是为 get 使用和 set 使用继承的。
每个普通对象有个布尔值 [[Extensible]] 内置插槽,它用于实现基本内部方法的不变量中指定的与可扩展性相关的内部方法不变量。即,一旦对象的 [[Extensible]] 内部插槽值被设为 false,那么:
在接下来的算法描述中,假设 O 是普通对象,P 是属性键,V 是任何ECMAScript语言值,Desc 是属性描述符 record。
每个普通的对象内部方法都委托给一个类似名称的抽象操作。如果一个抽象操作依赖于另一个内部方法,那么该内部方法在 O 上被调用,而不是直接调用类似名称的抽象操作。这些语义确保将普通对象内部方法应用于奇异对象时,将调用奇异对象自己覆盖的内部方法。
[[GetPrototypeOf]] ( ) —— Object.getPrototypeOf(O)
当 O 的 [[GetPrototypeOf]] 内部方法被调用时:
OrdinaryGetPrototypeOf ( O )
[[SetPrototypeOf]] ( V ) —— Object.setPrototypeOf
OrdinarySetPrototypeOf ( O, V )
断言:V 的类型要么是对象要么是 Null.
定义 current 变量,值为 O.[[Prototype]].
如果 SameValue(V, current) 结果为 true,返回 true。
定义 extensible 变量,值为 O.[[Extensible]].
如果 extensible 是 false,返回 false.(不可扩展)
定义 p 变量,值为 V.
定义 done,值为 false.
如果 done 是 false 的话,重复以下步骤:
8.1 如果 p 是 null,将 done 设为 true
8.2 否则如果 SameValue(p, O) 结果为 true,返回 false(这一步防止对象将自身设为自己的原型对象)
8.3 否则,
将 O.[[Prototype]] 的值设为 V
返回 true
省去[[IsExtensible]] ( )等相关
[[GetOwnProperty]] ( P ) —— Object.getOwnPropertyDescriptor()
OrdinaryGetOwnProperty ( O, P )
断言:IsPropertyKey(P)为 true
如果 O 自身没有属性 P,返回 undefined
定义 D,值为新创建且没有任何字段的属性描述符
定义 X,值为 O.P
如果 X 是数据属性
5.1 设置 D.[[Value]] 为 X 的 [[Value]] 属性值
5.2 设置 D.[[Writable]] 为 X 的 [[Writable]] 属性值
否则,
6.1 断言 X 为访问器属性
6.2 设置 D.[[Get]] 为 X 的 [[Get]] 属性值
6.3 设置 D.[[Set]] 为 X 的 [[Set]] 属性值
设置 D.[[Enumerable]] 为 X 的 [[Enumerable]] 属性值
设置 D.[[Configurable]] 为 X 的 [[Configurable]] 属性值
返回 D
[[DefineOwnProperty]] ( P, Desc ) —— Object.defineProperty()
OrdinaryDefineOwnProperty ( O, P, Desc )
O.[[GetOwnProperty]](P)
IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )
ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )
断言:如果 O 不是 undefined,那么IsPropertyKey(P)结果为 true
如果 current 是 undefined,
a. 如果 extensible 是 false,返回 false
b. 断言:extensible 是 true
c. 如果 IsGenericDescriptor(Desc) 结果是 true 或者 IsDataDescriptor(Desc) 结果是 true
d. 否则
e. 返回 true
如果 Desc 每个字段都缺失,返回 true
如果 current.[[Configurable]] 是 false,
a. 如果 Desc.[[Configurable]] 存在且值为 true,返回 false
b. 如果 Desc.[[Enumerable]] 存在且 ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) 结果为 false,返回 false
如果 IsGenericDescriptor(Desc) 结果是 true
a. 注意:无需进一步验证
如果 ! SameValue(! IsDataDescriptor(current), ! IsDataDescriptor(Desc)) 结果为 false,
a. 如果 current.[[Configurable]] 为 false,返回 false
b. 如果 IsDataDescriptor(current) 结果为 true,
c. 否则
如果 IsDataDescriptor(current) 和 IsDataDescriptor(Desc) 结果都是 true,
a. 如果 current.[[Configurable]] 是 false 并且 current.[[Writable]] 也是 false,
否则,
a. 断言:! IsAccessorDescriptor(current) 和 ! IsAccessorDescriptor(Desc) 都为 true
b. 如果 current.[[Configurable]] 是 false,
如果 O 不是 undefined,
a. Desc 每个字段都存在,将对象 O 的 P 属性描述符中相应属性设置为字段的值
返回 true
[[Get]] ( P, Receiver )
OrdinaryGet ( O, P, Receiver )
O.[[GetOwnProperty]](P)
的结果(P 的属性描述符)O.[[GetPrototypeOf]]()
结果(找原型对象)parent.[[Get]](P, Receiver)
结果 (递归调用去原型链上找)[[Set]] ( P, V, Receiver )
OrdinarySet ( O, P, V, Receiver )
O.[[GetOwnProperty]](P)
结果 (属性描述符)OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )
O.[[GetPrototypeOf]]()
结果 (拿原型对象)parent.[[Set]](P, V, Receiver)
结果Receiver.[[GetOwnProperty]](P)
结果Receiver.[[DefineOwnProperty]](P, valueDesc)
结果[[Delete]] ( P )
OrdinaryDelete ( O, P )
结果OrdinaryDelete ( O, P )
O.[[GetOwnProperty]](P)
结果[[OwnPropertyKeys]] ( ) —— Object.getOwnPropertyNames()
OrdinaryOwnPropertyKeys(O)
OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )
OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )
GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
and so on...
The text was updated successfully, but these errors were encountered: