ECMA-262-v6 中 'Symbol' 类型的意义何在?
What is the point of the 'Symbol' type in ECMA-262-v6?
ECMA-262-v6 中的 'Symbol' 类型有什么意义?对象键的快速路径实现?它在幕后做了什么 - 通过保证底层数据不可变对其进行哈希处理?
符号是替代魔法名称的私钥。他们阻止使用简单的字符串来引用该字段,因此只有具有该符号的消费者才能获得访问权限。
一些符号用于向运行时指示特定行为(如 Symbol.iterator
,其作用很像预共享秘密),而其他符号可由库分配并用于有效地隐藏字段。
一般来说,符号旨在替代魔法名称。您可以分配一个符号 const foo = Symbol()
并有选择地传递它,而不是简单地调用 'foo' 的属性。这允许运行时在启动时分配 Symbol.iterator
并保证任何试图实现可迭代的人都以一致的方式这样做。
运行时可以使用符号来优化对某些字段的访问,如果它觉得有必要的话,但不是必须的。
您可以使用符号将消费者引导至特定方法,具体取决于他们的使用情况。例如,如果您有一个可以 return 同步迭代器或生成器的库,具体取决于客户端的异步支持,您可以:
const syncIterable = Symbol();
const asyncIterable = Symbol();
class Foo {
static getIterable(async = false) {
return async ? asyncIterable : syncIterable;
}
[syncIterable]() {
return new SyncFoo();
}
[asyncIterable]() {
return new AsyncFoo();
}
}
let foo = new Foo();
for (let x of foo[Foo.getIterable(true)]()) {
// could be a iterator, could be a generator
}
这是一个相当人为的例子,但展示了图书馆如何使用符号有选择地为用户提供访问权限。
它们在很大程度上帮助我们避免了命名冲突。任何时候你想以独特的方式创建一个 属性,那就是你应该找到一个符号的时候。
看看我的例子
const bert = Symbol('Bert');
'Bert'
Note: this is not a value this is what they called a descriptor,
because the symbol itself is just a unique identifier. So if you were
to visualize what a symbol would be maybe you can visualize is as
something like this "sdfasdfa2342134987fgsdfgsdf9808fsfgsd" absolute
unique symbol so that you can make sure that it will never overrides
any other piece of code in there.
如果我创建第二个符号,这很酷,比如
const person = Symbol('Bert')
你可以看到我又用了'Bert'。那些会是一样的吗,因为我把它们描述成一样的东西?
const bert = Symbol('Bert');
const person = Symbol('Bert');
console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);
如果您要创建 class 的对象,这会很有用。
const classRoom = {
'Mia' : { grade: 50, gender: 'female' },
'Gilbert': { grade: 80, gender: 'male' },
'Gilbert' { grade: 80, gender: 'male' },
};
但是你还有另一个叫 Gilbert 的人,所以你在那里遇到了命名冲突。想象一下,如果您正在处理数以百万计的数据。因此,我们可以使用符号来命名他们,而不是使用人名或使用某种唯一标识符。
const classRoom = {
[Symbol('Mia')] : { grade: 50, gender: 'female' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
};
关于符号的另一件事是它们是不可枚举的,这意味着如果我要这样做,我们不能循环遍历它们
for (const person in classRoom) {
console.log(person);
}
我一无所获。
如果您确实想要访问所有符号,因为它们是您想要获取的一些信息,您可以使用对象方法。
const syms = Object.getOwnPropertySymbols(classRoom);
const data = syms.map(sym => classRoom[sym]);
console.log(data);
ECMA-262-v6 中的 'Symbol' 类型有什么意义?对象键的快速路径实现?它在幕后做了什么 - 通过保证底层数据不可变对其进行哈希处理?
符号是替代魔法名称的私钥。他们阻止使用简单的字符串来引用该字段,因此只有具有该符号的消费者才能获得访问权限。
一些符号用于向运行时指示特定行为(如 Symbol.iterator
,其作用很像预共享秘密),而其他符号可由库分配并用于有效地隐藏字段。
一般来说,符号旨在替代魔法名称。您可以分配一个符号 const foo = Symbol()
并有选择地传递它,而不是简单地调用 'foo' 的属性。这允许运行时在启动时分配 Symbol.iterator
并保证任何试图实现可迭代的人都以一致的方式这样做。
运行时可以使用符号来优化对某些字段的访问,如果它觉得有必要的话,但不是必须的。
您可以使用符号将消费者引导至特定方法,具体取决于他们的使用情况。例如,如果您有一个可以 return 同步迭代器或生成器的库,具体取决于客户端的异步支持,您可以:
const syncIterable = Symbol();
const asyncIterable = Symbol();
class Foo {
static getIterable(async = false) {
return async ? asyncIterable : syncIterable;
}
[syncIterable]() {
return new SyncFoo();
}
[asyncIterable]() {
return new AsyncFoo();
}
}
let foo = new Foo();
for (let x of foo[Foo.getIterable(true)]()) {
// could be a iterator, could be a generator
}
这是一个相当人为的例子,但展示了图书馆如何使用符号有选择地为用户提供访问权限。
它们在很大程度上帮助我们避免了命名冲突。任何时候你想以独特的方式创建一个 属性,那就是你应该找到一个符号的时候。
看看我的例子
const bert = Symbol('Bert');
'Bert'
Note: this is not a value this is what they called a descriptor, because the symbol itself is just a unique identifier. So if you were to visualize what a symbol would be maybe you can visualize is as something like this "sdfasdfa2342134987fgsdfgsdf9808fsfgsd" absolute unique symbol so that you can make sure that it will never overrides any other piece of code in there.
如果我创建第二个符号,这很酷,比如
const person = Symbol('Bert')
你可以看到我又用了'Bert'。那些会是一样的吗,因为我把它们描述成一样的东西?
const bert = Symbol('Bert');
const person = Symbol('Bert');
console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);
如果您要创建 class 的对象,这会很有用。
const classRoom = {
'Mia' : { grade: 50, gender: 'female' },
'Gilbert': { grade: 80, gender: 'male' },
'Gilbert' { grade: 80, gender: 'male' },
};
但是你还有另一个叫 Gilbert 的人,所以你在那里遇到了命名冲突。想象一下,如果您正在处理数以百万计的数据。因此,我们可以使用符号来命名他们,而不是使用人名或使用某种唯一标识符。
const classRoom = {
[Symbol('Mia')] : { grade: 50, gender: 'female' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
};
关于符号的另一件事是它们是不可枚举的,这意味着如果我要这样做,我们不能循环遍历它们
for (const person in classRoom) {
console.log(person);
}
我一无所获。
如果您确实想要访问所有符号,因为它们是您想要获取的一些信息,您可以使用对象方法。
const syms = Object.getOwnPropertySymbols(classRoom);
const data = syms.map(sym => classRoom[sym]);
console.log(data);