These are the two lines of code extracted var name = Symbol('test')
It keeps prompting that it cannot be converted. Is the keyword reserved? Or other reasons?
Why can it be compiled by changing var name1 = Symbol('test')
?
Other ordinary var s1 s2
can also be compiled.
三叔2017-06-26 10:57:19
This question is quite interesting. I have never noticed it. After looking through the information, I found that many things came together by coincidence, and then this problem appeared. To be precise, it’s the browser’s default behavior
and JavaScript’s implicit type conversion
that’s causing the trouble.
Let’s go step by step, first of all, what is the difference between var
and let
?
var
will be promoted to the top of the current function scope. If it is global, then this variable will become an attribute of window
.
For variables declared by let
, it will promote the variable to the current block-level scope, and if it is global, the current variable will not become an attribute of window
.
So, in the big picture something like this happens:
var test1 = 'test1';
let test2 = 'test2';
console.log(window.test1); // test1
console.log(window.test2); // undefined
Then, what is the difference between the variable named name
and other variables?
We know above that var name = 'test1';
can actually be equivalent to window.name = 'test1'
. It is easy to think, is name
a fixed reserved word?
Looking through the specifications, it’s true. The window.name
attribute represents the name of the current window context. The following are some interfaces of window
:
[ReplaceableNamedProperties]
interface Window {
// the current browsing context
readonly attribute WindowProxy window;
readonly attribute WindowProxy self;
readonly attribute Document document;
attribute DOMString name;
//..
}
The name
attribute in the last line here does not have the prefix readonly
, indicating that it is readable and writable, and its data type is DOMString
. DOMString
refers to a UTF-16 string, which is directly mapped to String
in JavaScript.
So when we assign a value to window.name
, this value will be coerced into String
.
We can give it a try:
var name = { a:1, b:2 };
console.log(window.name); // [object Object]
var name = [0, 1, 2, 3];
console.log(window.name); // 0,1,2,3
You can probably guess at this point that the error in var name = Symbol('test');
should be that there is a problem with the type conversion of the Symbol
variable. The actual error reported also confirmed our guess: TypeError: Cannot convert a Symbol value to a string
.
However, it doesn’t seem right. Symbol
variables can be converted into strings, for example:
let test = Symbol('test');
console.log(test.toString()); // Symbol(test)
console.log(String(test)); // Symbol(test)
Well, this is a cliché. JavaScript’s implicit type conversion and explicit cast are different for some variables. Unfortunately, Symbol
falls into this category here.
Symbol
is implicitly converted, it will first call its internal ToPrimitive
interface to get its original value, and then call the ToString
function to convert it to a string. Note that the ToString
function here is its internal abstract method, and is not the same thing as the exposed Symbol.prototype.toString()
.
For the Symbol
variable, an error will be reported when it calls ToString
. I will not go into more details. If you are interested, you can read the specification for yourself: ToString (argument).
仅有的幸福2017-06-26 10:57:19
I just tried it on the console, it is indeed a very amazing BUG, but you will
var name = Symbol("test");
//改成
let name = Symbol("test"); //试试。。
Then I was surprised to find that the BUG was gone again. . I guess it has something to do with how the browser parses syntax, but I don't understand these things.
代言2017-06-26 10:57:19
name is a unique attribute of window. If you try changing the variable, you will not get an error. . .
欧阳克2017-06-26 10:57:19
name is a unique attribute of window. Any value assigned to the name variable in the global environment will be automatically converted into a string. However, the Symbol type cannot be directly converted into a string, so an error is reported.
You can
var name = 1;
console.log(name);
You’ll know.