在js引擎中对变量的存储主要有两种位置,堆内存和栈内存。
和java中对内存的处理类似,栈内存主要用于存储各种基本类型的变量,包括Number、String、Boolean、Undefined、Null以及对象变量的指针(也有人认为还有一个Symbol)。
堆内存主要负责像对象Object这种变量类型的存储。
<script type="text/javascript">
var str1 = "abc";
var str2 = 'abc';
var str3 = new String ("abc");
var str4 = new String ("abc");
var str5 = new String ("");
str5 = "abc";
console.log(str1 == str2); //true
console.log(str1 === str2); //true
console.log(str1 == str3); //true
console.log(str1 === str3); //false
console.log(str3 == str4); //false
console.log(str3 === str4); //false
console.log(str1 == str5); //true
console.log(str3 == str5); //true
console.log(str3 === str5); //false
console.log(typeof str1); //string
console.log(typeof str2); //string
console.log(typeof str3); //object
console.log(typeof str4); //object
console.log(typeof str5); //string
</script>
在java中,双引号表示字符串string,而单引号表示单个字符char。
但在JavaScript中,语法相对宽松,单引号和双引号效果都一样的。
首先执行var str1 = “abc”,在栈中创建一个变量命名为str1,将abc存放进来。接着执行var str2 = ‘abc’,在栈中创建变量str2,将abc存放进来
所以str1与str2是在栈中开辟不同空间存放字符串abc。str1 === str2结果是true。
String()是JS的内置对象之一。new String()每调用一次,不管其字符串值是否相等,是否有必要创建新对象,都会创建一个新的对象。
执行var str3 = new String (“abc”),通过用new()新建一个对象,存放于堆内存中。然后栈中创建引用变量str3,并且存放堆中对象的地址,指向该对象。
由于隐式类型转换的原因,所以str1 == str3结果是true,但str1 === str3结果是false。
同理,执行var str4 = new String (“abc”),会再次new一个新的对象,存放于堆内存中。每调用一次就会创建一个新的对象。然后栈中创建引用变量str4,存放堆中再次创建的对象的地址,指向新建的对象。
所以str3和str4存放的是不同的堆地址,指向不同的对象。地址值不一样,所以两次判断都是false。
因为str5 = "abc"的执行,str5原本存放的地址被替换为了abc,存储的是常量——字符串,不再是地址。所以str3 === str5结果是false,str3 == str5结果是true(隐式类型转换)。