const声明
const的行为与let基本相同,唯一一个重要的区别就是用它声明变量的时候必须同时初始化变量,而且尝试修改const声明的时候会导致运行错误
<script> const age = 36 ; age = 36 ; //TypeError:给常量赋值 //const也不允许重复声明 const name = 'Matt'; const name = 'DNEIOF'; //const声明的作用域也是块 const name = 'Matt'; if(true){ const name = 'huiijo'; } console.log(name); // Matt </script>
const声明的限制只适用于它指向的变量的引用,换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制
<script> const person = (); person.name = 'Matt'; // ok </script>
JavaScript引擎会为for循环中的let声明分别创建独立的变量实例,虽然const变量跟let变量很相似,但是不能用const来声明迭代变量
for (const i = 0 ; i < 10 ; ++i){} // TypeError:给常量赋值
不过,如果你只想用const声明一个不会被修改的for循环变量,那也是可以的,换句话说,每次迭代只是创建一个新变量,这对for-of和for-in循环特别有意义
<script> let i = 0; for (const j = 7; i < 5; ++i) { console.log(i); // 7 7 7 7 7 } for (const key in {a: 1, b: 2}) { console.log(key); // a,b } for (const value of [1, 2, 3, 4, 5]) { console.log(value); // 1,2,3,4,5 } </script>
声明风格及最佳实践
ECMAScript 6增加了let和const,从客观上为这门语言更精确地声明作用域和语义提供了更好的支持,行为怪异的var所造成的各种问题
不使用var
有了let和const,大部分开发者会发现自己不再需要var了,限制自己只使用let和const,有助于提升自己的代码质量,因为变量有了明确的作用域、声明位置,以及不变的值
数据类型
ECMAScript有6种简单的数据类型(原始类型):Undefined、Null、Boolean、Number、String和Symbol(符号)是在ECMAScript 6新增的,还有一种类型叫Object(对象),Object是一种无序名值对的集合,这是因为在ECMAScript中不能定义自己的数据类型,所有的值都用以上7种数据类型之一来表示
typeof操作符
因为ECMAScript的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型,typeof操作符就是为此而生的,对一个值使用typeof操作符会返回下列字符串之一
“undefined” 表示值未定义 "boolean" 表示值为布尔值 "string" 表示值为字符串 "number" 表示值为数值 "object" 表示值为对象(而不是函数)或null "function" 表示值为函数 "symbol" 表示值为符号
<script> let message = "some thing"; console.log(typeof message); //"string" console.log(typeof (message)); //"string" console.log(typeof 95); "number" </script>
我们可以发现,在这个例子中,把一个变量(message)和一个数值字面量传给了typeof操作符。此刻的typeof是一个操作符而不是函数,因此不需要参数
注意
严格来说,函数在ECMAScript中被认为是对象,并不代表是一种数据类型。可是,函数也有其自己的特殊的属性,为此就有必要通过typeof操作符来区分函数和其它对象
Undefined类型
Undefined类型只有一个值,就是特殊值Undefined,当我们使用var或者let没有初始化变量的时候,就相当于给变量赋予了一个undefined
<script> let message ; console.log(message == undefined); </script>
在这个例子中,变量message在声明的时候并未初始化,而在比较它和undefined的字面值时,两者是相等的,这个例子等同于下面的实例
<script> let message = undefined; console.log(message == undefined); </script>
这里的变量message显示地以undefined来初始化,但这个是不必要的,因为在默认情况下,任何未经初始化的变量都会取得undefined值
注意注意
一般来说,我们永远不用显式地给某个变量设置undefined值,字面值undefined主要用于比较,而且在ECMA-262第3版之前是不存在的,增加这个特殊值的目的就是为了正式明确空对象指针(null)和未初始化变量的区别
包含undefined值的变量和未定义变量之间是有区别的
<script> let message ; console.log(message); // undefined console.log(age); // 报错 </script>
在上面的例子中,第一个console.log绘制出变量message的值,即undefined。而第二个console.log要输出一个未声明的变量age的值,因此会导致报错,对于未声明的变量,只能执行第一个有用的操作,就是对它调出typeof
我们在对未初始化的变量调用typeof时,返回的结果是undefined,但对未声明的变量调用它时,返回的结果还是undefined,这个就让人很困惑
<script> let message ; console.log( typeof message); // undefined console.log( typeof age); // undefined </script>
无论是声明还是未声明,typeof返回的都是字符串undefined,逻辑上都是对的,因为虽然严格来说这两个变量之间存在根本性差异,但是它们都无法执行实际操作。
undefined是一个假值,如果我们需要,可以用更简洁的方式检测它,不过也要记住,其它可能的值同样是假值,所以一定要明确自己想检测的就是undefined这个字面值,而不仅仅是假值
<script> let message; // 这个变量被声明了,只是值为undefined // age没有声明 if(message){ //这个块不会执行 } if(!message){ //这个块会执行 } if(age){ //这里会报错 } </script>