对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。
1 const person = { 2 name : 'Tom', 3 age : 18 4 }; 5 person.age = 20; 6 alert(person.age);
上面的代码中,常量person存储的是一个地址,指向一个对象。不可变的只是这个地址,即不能把person指向另一个地址,但对象本身是可变的,所以其属性的值是可以修改的。
下面是另外一个例子:
1 const arr = []; 2 arr.push(1); 3 arr.push(2); 4 alert(arr.length); 5 arr.length = 0; 6 alert(arr.length);
上面的代码中,常量arr是一个数组,这个数组本身是可写的,但如果将另一个数组赋值给arr,就会报错。
如果真的想把对象冻结,应该使用Object.freeze()方法。
1 const person = Object.freeze({ 2 name : 'Tom', 3 age : 18 4 }); 5 person.age = 20; 6 alert(person.age); //18
上面的代码中,常量person指向一个冻结的对象,所以修改属性值不起作用。
除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的例子:
1 var person = { 2 name : 'Tom', 3 age : 18, 4 friend : { 5 name : 'Jerry', 6 age : 19 7 } 8 }; 9 var constantize = (obj)=>{ 10 Object.freeze(obj); 11 Object.keys(obj).forEach((key,value)=>{ 12 if(typeof obj[key] === 'object'){ 13 constantize(obj[key]); 14 } 15 }) 16 }; 17 constantize(person); 18 person.friend.age = 25; 19 alert(person.friend.age); //19