我们的变量名称不能乱起,特别是不要跟window本身带的对象起冲突,也要注意下不要跟js关键字器冲突,不然的话这种bug真的很难找出来。下面实例来说明一下:
起初,看着别人的说明文档,验证ES6中的新出现的基本类型symbol,symbol的最大用途就是定义对象的唯一属性名,可以作为对象属性的标识符使用。对于symbol不细说,就在这里遇见了name。
var name = symbol();
一个简单定义出现的问题,如果改为
let name = symbol();
先谈及 let和var的区别:
var
声明的变量会被提升至当前函数作用域顶端,如果是在全局那么这个变量将会成为window
的一个属性。
而对于let
声明的变量,它会将变量提升至当前块级作用域,并且如果是在全局,当前变量也不会成为window
的属性。
或者这个,都不会报错。到这里如果还不懂,其实是遇到了浏览器的默认行为、window自带对象属性冲突
var n= symbol();
name
为名的变量和别的变量有什么区别?
上图可以看到,name在window对象属性中,表示设置或返回窗口名称。
肯定还会有这样的疑惑,我经常会用name,为什么没有这种问题呢,为什么下面前两张情况不会报错呢?
var name = "test";
console.log(name)//test
var name = 2;
console.log(name)//2
var name = symbol("test")//出错
这还涉及到另一个知识点:javascript的隐式类型变换
window的部分接口:(对于这一部分从网上找到的,不怎么清楚完整版)
[ReplaceableNamedProperties]
interface Window {
// the current browsing context
readonly attribute WindowProxy window;
readonly attribute WindowProxy self;
readonly attribute Document document;
attribute DOMString name;
//..
}
name前没有readonly,说明是可读可写的,但是标明了类型为DOMString
网上资料说DOMString是属于UTF-16的字符串,在js中会直接映射为String(映射原理目前还不太清楚)
var name = 2;
console.log(typeof(name));//string
上面的代码显示,当我们给window.name赋值的时候,这个值会被强制转换为String。
var name = Symbol('test');
的错误,应该是Symbol
变量在做类型转换的时候出了问题。而实际报的错误也证实了我们的猜测:TypeError: Cannot convert a Symbol value to a string
。
这也不是说明Symbol类型不能转换为String,而是属于一种特殊情况。
var test = Symbol('test');
console.log(test.toString()); // Symbol(test)
console.log(String(test)); // Symbol(test)
上面很正常,JavaScript的隐式类型变换和显式的强制转换对于部分变量是不同的。
Symbol
被隐式的转换时,它会首先调用其内部的ToPrimitive
接口,拿到其原始值,然后在其中再调用ToString
函数转换为字符串。注意,这里的这个ToString
函数是其内部的抽象方法,和暴露在外的Symbol.prototype.toString()
不是一个东西。
其他保留字和关键字等同样要谨慎对待,不然出现的bug很难被发现,window对象还有一个是top,不了解的就容易var一个top,
top是js一个window对象,它们是只读的,所以我们不可以给它写入东西,这才导致我们把内容赋给top变量,最后输出的却是window。
所以以后一定要注意下,我们的变量名称不能乱起,特别是不要跟window本身带的对象起冲突,也要注意下不要跟js关键字器冲突,不然的话这种bug真的很难找出来。关键字和保留字查阅。