简体   繁体   English

为什么我不能覆盖字符串实例的迭代器而不是 String.prototype?

[英]Why can't I override the iterator of a string instance instead of the String.prototype?

This code allows to use the spread operator to split the words of the sentence, just as expected:这段代码允许使用扩展运算符来拆分句子中的单词,正如预期的那样:

 String.prototype[Symbol.iterator] = function* () { yield* this.split(' '); } const result = [...'The quick brown fox jumped over the lazy dog.']; console.log(result);

I wanted to try overriding the Symbol.iterator at instance level to avoid mutating String.prototype , here is my attempt:我想尝试在实例级别覆盖Symbol.iterator以避免变异String.prototype ,这是我的尝试:

 const sentence = 'The quick brown fox jumped over the lazy dog.'; sentence[Symbol.iterator] = function* () { yield* this.split(' '); } const result = [...sentence]; console.log(result); // Not the expected result console.log(sentence[Symbol.iterator]); // Native String iterator

The native String.prototype[Symbol.iterator] doesn't look overridable at instance level, and I don't get why.本机String.prototype[Symbol.iterator]在实例级别看起来不可覆盖,我不明白为什么。 My guess is that sentence is a primitive and not really a String instance.我的猜测是sentence是原始的,而不是真正的String实例。 Then how do I achieve this?那我该如何实现呢?

Because string primitives are not string objects.因为字符串基元不是字符串对象。 Instead, when you use methods on them (or access properties on them), it's as though they were converted to object first.相反,当您对它们使用方法(或访问它们的属性)时,就好像它们首先被转换为 object 一样。 (In loose mode, an object is actually created, but the object is thrown away when the method returns unless something keeps a reference to it.) That means that this code modifies a temporary object that's never saved (not the string primitive; string primitives are immutable): (在松散模式下,实际上创建了一个 object,但是当方法返回时 object 被丢弃,除非有东西保留对它的引用。)这意味着这段代码修改了一个从未保存的临时 object(不是字符串基元;字符串基元是不可变的):

sentence[Symbol.iterator] = function* () {
  yield* this.split(' ');
}

Since it's never saved, later when you use the iterator, you get the default one.因为它从未保存过,所以稍后当您使用迭代器时,您会得到默认值。

You can create a string object instead:您可以改为创建字符串 object:

 const sentence = new String('The quick brown fox jumped over the lazy dog.'); // −−−−−−−−−−−−−−^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^ sentence[Symbol.iterator] = function* () { yield* this.split(' '); }; const result = [...sentence]; console.log(result);

You could define your own words method on strings:您可以在字符串上定义自己的words方法:

 Object.defineProperty(String.prototype, "words", { *value() { yield* this.split(" "); }, configurable: true, writable: true, }); const sentence = "The quick brown fox jumped over the lazy dog."; const result = [...sentence.words()]; console.log(result);

I strongly discourage modifying built-in prototype in a library or similar, but if you're aware of the dangers of future naming conflicts and such, you can do it on your own page or app.强烈反对修改库或类似库中的内置原型,但如果您意识到未来命名冲突等的危险,您可以在自己的页面或应用程序上进行修改。

Or as VLAZ points out , just write a function you pass the string into.或者正如VLAZ 指出的那样,只需编写一个 function 即可将字符串传递到其中。 :-) :-)

You cannot change the "instance" because a primitive is not one.您不能更改“实例”,因为原语不是一个。 For example "hello" is only a string primitive that does not have any properties of its own.例如, "hello"只是一个字符串原语,它自己没有任何属性。 Same with other primitives like 42 .42等其他基元相同。

Calling any object method or using propertirs on a primitive will convert the value to an object for just that operation: ("hello").split(" ") or (42).toFixed(2) .调用任何 object 方法或在基元上使用 propertirs 会将值转换为 object 仅用于该操作: ("hello").split(" ")(42).toFixed(2) The primitives themselves are immutable.原语本身是不可变的。

Without polluting any prototypes or changing any objects, you can simply create a reusable generator function and spread its result:在不污染任何原型或更改任何对象的情况下,您可以简单地创建一个可重用的生成器 function 并传播其结果:

 const sentence = 'The quick brown fox jumped over the lazy dog.'; function* toWords(str) { yield* str.split(' '); } const result = [...toWords(sentence)]; console.log(result);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM