原文地址(原文会一直不断更新): blog.gcl666.com/2019/07/08/…
简介
本文将维护且不断更新 ECMAScript 标准下一些常见,或最新的 API 或功能实现伪码。
参考地址: tc39.es/ecma262/#se…
可直接在版本一章 5 找到本文中所有 Api 。
本文约定:
-
标题右上角的 数组n-year 表示该 API 发布的版本及年份
比如:ES6 是 ECMASCript 2015 代表
{6-2015}
Object
Object.assign(target, …sources)6-2015
实现原理图:

伪码:
function assign(target, ...sources) {
let to = ToObjecct(target);
// 1. 只有目标参数,原样返回
if (arguments.length === 1) {
return to;
}
// 2. 获取后面的参数列表,要合并到 target 里面的对象列表
let sources = List(sources); // 参数列表
// 3. 取到当前循环中的源对象
for (let nextSource in sources) {
// 3.1 非法情况不做处理
if (nextSource !== undefined || nextSource !== null) {
let from = ToObject(nextSource);
// 3.2 取出当前对象的所有自身的 keys
let keys = from.[[OwnPropertyKeys]]();
// 3.3 遍历这些 keys 取出非 Undefined 且可枚举的属性
// 添加到 target 对象上去
for (let nextKey in keys) {
let desc = from.[[GetOwnProperty]][nextKey];
if (desc !== undefined && desc.[[Enumerable]] === true) {
let propValue = Get(from, nextKey);
Set(to, nextKey, propValue, true);
}
}
}
}
// 4. 返回扩展之后的目标对象
return to;
}
Object.prototype.toString(obj)
// toString(object)
function toString(obj) {
// 1. 判断 undefined 和 null
if (this === undefined) {
return '[object Undefined]';
}
if (this === null) {
return '[object Null]';
}
let O = ToObject(this); // 上下文变量对象化
let isArray = IsArray(O); // 先判断是不是数组类型
let builtinTag = ''
let has = builtinName => !!O.builtinName;
// 2. 根据内置属性,检测各对象的类型
if (isArray === true) { // 数组类型
builtinTag = 'Array';
} else if ( has([[ParameterMap]]) ) { // 参数列表,函数参数对象
// 函数的参数 arguments 对象
builtinTag = 'Arguments';
} else if ( has([[Call]]) ) { // 函数
builtinTag = 'Function';
} else if ( has([[ErrorData]]) ) { // Error对象
builtinTag = 'Error';
} else if ( has([[BooleanData]]) ) { // Boolean 布尔对象
builtinTag = 'Boolean';
} else if ( has([[StringData]]) ) { // String 对象
builtinTag = 'String';
} else if ( has([[DateValue]]) ) { // Date 对象
builtinTag = 'Date';
} else if ( has([[RegExpMatcher]]) ) { // RegExp 正则对象
builtinTag = 'RegExp';
} else {
builtinTag = 'Object' // 其他
}
// 3. 最后检测 @@toStringTag - Symbol.toStringTag 的值
let tag = Get(O, @@toStringTag);
if (Type(tag) !== 'string') {
tag = builtinTag;
}
return `[object ${tag}]`;
}
Symbol
Symbol.for(key)6-2015
在全局符号注册表(Global Symbol Registry)中创建或查找符号值,返回一个符号变量。
Symbol.for = function (key) {
// 1 key 转字符串
let stringKey = ToString(key);
// 2. 遍历 GlobalSymbolRegistryList 注册表
for (let e in GlobalSymbolRegistryList) {
// 符号值已经存在
if (SameValue(e.[[Key]], stringKey)) {
return e.[[Symbol]];
}
}
// 3. 注册表中不含 `stringKey` 的符号值,则创建新的符号值
// 3.1 新建符号值
let newSymbol = Symbol(stringKey);
// 3.1 给 [[Description]] 赋值
newSymbol.[[Description]] = stringKey;
// 4. 注册到符号注册表中去
GlobalSymbolRegistryList.push({
[[Key]]: stringKey,
[[Symbol]]: newSymbol
});
// 5. 返回新建的符号值
return newSymbol;
}
Generator 抽象操作(Abstract Operations)
GeneratorStart(generator, generatorBody)6-2015
实现包含:
- generator 状态初始化
- 将当前的执行上下文交给 generator
- 如果恢复执行(
next())- 执行 generator 函数体,得到执行结果
- 断言执行过程是否异常(assert.throw)或无内容(assert.return)直接返回
- 函数体执行完,释放栈帧,重置下一个栈帧为当前运行栈帧
- 将 Generator 状态置为 'completed' ,因为到这里表示正常执行完成了
- 根据
result.[ [Type]]类型(normal, return, throw) 决定 value 的值 - 最后得到
{value: xxx, done: true/false }将结果返回
- 否则,保存上下文到 generator, 然后改变状态为
suspendedStart
function GeneratorStart(generator, generatorBody) {
// Assert: 初始状态
generator.[[GeneratorState]] = undefined;
// 取出栈顶的运行时栈帧
let genContext = RunningExecutionContext;
// 当前执行上下文的执行组件,设置成当前逐个 generator
genContext.component = generator;
// 调用 next() 触发代码执行
if (evaluation.resumed) {
// 执行 generator 的内容,得到结果
let result = eval(generatorBody),
resultValue;
// Assert: 直接返回
if (assert.return) {
return;
}
// Assert: 出现异常
if (assert.throw) {
throw new Error()
}
// generator body 执行完成,删除该栈帧 genContext
ExecutionContextStack.delete(genContext);
// 将栈顶的栈帧置为当前运行的栈帧
RunningExecutionContext = ExecutionContextStack.unshift();
// 设置 generator 的状态:已完成,此时该 generator 已经执行完成
// 执行上下文被删除,永远不会再恢复,后面其他的代码都不会被执行而丢弃掉
generator.[[GeneratorState]] = 'completed';
// 处理结果值 { value: xxx, done: false/true }
// 根据结果类型,决定 value 的值
if (result.[[Type]] === 'normal') {
// 正常情况,返回 { value: undefined, done: true }
resultValue = undefined;
} else if (result.[[Type]] === 'return') {
resultValue = result.[[Value]];
} else {
if (result.[[Type]] === 'throw'){
throw new Error();
}
// 返回结果值 { value: xxx, done: true }
return Completion(result);
}
}
// 没有调用 next() 将状态置为挂起,保存 generator 的执行上下文
generator.[[GeneratorContext]] = genContext;
generator.[[GeneratorState]] = 'suspendedStart';
return NormalCompletion(undefined);
}

版本链接
< ECMAScript 2015
| Api | 链接(Link) |
|---|---|
Object.prototype.toString(obj) |
Link->2.2 |
ECMAScript 2015(ES6)
| Api | 链接(Link) |
|---|---|
Object.assign(target, ...sources) |
Link->2.1 |
Symbol.for(key) |
Link->3.1 |
GeneratorStart(generator, generatorBody) |
Link->4.1 |