clearwater 发表于 2020-2-28 15:35

JS基础:字符串的不可变性 VS 简单类型数据类型在内存中的存储

本帖最后由 clearwater 于 2020-2-28 17:50 编辑

我在跟某马的前端视频学习。

1、老师在视频中某个小节,提到字符串的不可变性。-----这个我看懂了。
代码如下:
   // 字符串的不可变性
      var str = 'andy';
      console.log(str);
      str = 'red';
      console.log(str);
老师说,andy 并没有被 red 覆盖掉,而是red 在内存中开辟了一个新的空间,然后把str 指向 red.


2、然后老师又在后面的小节提到,简单数据类据包括:数字型,字符串型等等。他举例说,简单数据内型的数字型是把值替换掉。---这个我也懂了。
var num = 10;
num = 20;



我的问题是上面的第1点,和第2点,好象是矛盾的。第1点是字符串的数据保持不变,只是把变量名指向新的字符串值域;第2点,是把10替换为20.
是不是除了字符串外,简单数据内型(数字型、布尔型,null , undefined)全部在栈中替换值,而字符串型则是开劈新空间?



senile_zhang 发表于 2020-2-28 17:44

本帖最后由 senile_zhang 于 2020-2-28 19:40 编辑

clearwater 发表于 2020-2-28 16:15
谢谢您和楼上另位二位大神的帮助。



你老师说法不严谨呗,一般而言简单类型都是存于栈的,但string除外罢了

如何理解string这种特殊性呢,我提供两个思路:

#### 思路一:是否继承了Object
可以理解为,区分简单类型和复杂类型不在于看他们是否使用了堆空间,而是在于是否继承了Object。
我们知道所有对象在原型链上一路追溯,都会抵达Object.prototype,换句话说就是都继承了Object。

不过这种思路有两个瑕疵:
1.ES6的Symbol如何认定?
Symbol手动验证的话,可以发现它原型链终点也是Object.prototype,那么应该认定为复杂类型。
但我看网上都认定其是简单类型,虽然还没看到比较权威的说法。

2. 继承于 `null` 的对象如何认定?
有多种方法可以把一个对象的 `prototype` 设置为 `null` ,那么此时按这套理论来讲,这个对象就应该是个简单类型了,不符合直觉。

---
#### 思路二:是否使用堆空间
也就是你老师原来的说法,只不过把string这个例外情况视为一种瑕疵。

当然,这种思路也同样不能解释为什么网上把Symbol列为简单类型。个人觉得网上的说法还是有待检验的

---
---
#### 勘误

>#### 思路一:是否继承了Object
可以理解为,区分简单类型和复杂类型不在于看他们是否使用了堆空间,而是在于是否继承了Object。
我们知道所有对象在原型链上一路追溯,都会抵达Object.prototype,换句话说就是都继承了Object。

>不过这种思路有两个瑕疵:
1.ES6的Symbol如何认定?
Symbol手动验证的话,可以发现它原型链终点也是Object.prototype,那么应该认定为复杂类型。
但我看网上都认定其是简单类型,虽然还没看到比较权威的说法。

>2. 继承于 `null` 的对象如何认定?
有多种方法可以把一个对象的 `prototype` 设置为 `null` ,那么此时按这套理论来讲,这个对象就应该是个简单类型了,不符合直觉。

`symbol` 没有原型链,的确是简单类型, ** 对简单类型使用 `Object.getPrototyeOf()` 会发生强制类型转换,将其包装成一个对象。 **
>https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf#Notes

我忘记了这一点,导致以为下面的代码为 `true` 就意味着symbol继承于Object
```js
Object.getPrototypeOf( Object.getPrototypeOf(Symbol()) ) === Object.prototype    //true
```

类似地,对number和boolean使用 `Object.getPrototypeOf()`也发生type coercion

实际上,应该用 `instanceof` 操作符来验证是否存在于原型链的问题
```js
Symbol() instanceof Object    //false
```






cxbb 发表于 2020-2-28 15:38

看起来厉害

吐槽户 发表于 2020-2-28 15:59

我也是半桶水
在学java,看到楼主的问题
说一下自己的看法,
基本数据类型在栈内存里面是值
字符串是引用数据类型在栈内存里面是引用堆内存的地址

王辰瑞 发表于 2020-2-28 15:59

我只记得JS是弱类型语言,不是自带类型转换么。。估计内部处理方式不一样吧。。我只记得JAVA的String new出来的是在堆里,赋值的在栈里,至于那些冗余的堆里之前创建的VM虚拟机会自动回收

井右寺 发表于 2020-2-28 16:04

好像看过一种说法
js的简单数据类型,是直接存储在栈里面的
对象等复杂数据类型,地址是存在栈的,实际数据是保存在堆里的。。。
按照这样来解释的话,js是直接操作栈的,简单数据类型就被直接替换了。
而字符串等,栈地址不变,但栈区存储的地址指向变了,指向堆区开辟的新空间,而堆的管理是由GC控制的,并不会被立即释放。
具体原理也不太清楚,这个东西需要注意的就是,引用类型和值类型的区别了。应该是类比c的指针和值。

wubo777 发表于 2020-2-28 16:06

看起来厉害{:301_1009:}

clearwater 发表于 2020-2-28 16:12

wubo777 发表于 2020-2-28 16:06
看起来厉害

不来回复这些没用回答,手会痒吗?想灌水,去水区。

clearwater 发表于 2020-2-28 16:15

本帖最后由 clearwater 于 2020-2-28 16:18 编辑

井右寺 发表于 2020-2-28 16:04
好像看过一种说法
js的简单数据类型,是直接存储在栈里面的
对象等复杂数据类型,地址是存在栈的,实际数 ...
谢谢您和楼上另位二位大神的帮助。

s的简单数据类型,是直接存储在栈里面的
对象等复杂数据类型,地址是存在栈的,实际数据是保存在堆里的。。。
我引用您的上面文字和老师的说法是一样的。

但是老师说,string也是简单数据类型啊。应该也是存在栈中才对。下面红字的出处是老师的笔记。

2.1 简单数据类型                简单类型(基本数据类型、值类型):在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null
2.2 复杂数据类型
                复杂数据类型(引用类型):在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;

井右寺 发表于 2020-2-28 16:32

clearwater 发表于 2020-2-28 16:15
谢谢您和楼上另位二位大神的帮助。




http://www.imooc.com/wenda/detail/476583
不知道这个说法对不对
:Dweeqw好像在java里面,字符串直接就是对象,直接赋值相当于new。
我刚刚试了下,js里面有String对象,也有string类型,二者居然不是一样的{:1_911:}

幼稚鬼 发表于 2020-2-28 16:38

JS的数据类型又可分为两种,这里讨论ES5
1)基本类型(又叫原始类型):
包括:Undefined、Null、Boolean、Number、String
2)引用类型:
包括:Array 、 Object 、 function 、Date 、RegExp.


两者的区别是基本类型变量存的是数据的具体值,而引用类型变量保存的是值的引用。


但字符串(string)类型比较特殊,因为js中的字符串长度可变,不能存在大小固定的地址空间当中,可以看做是:行为与基本类型相似的不可变引用类型。


上诉内容借鉴了百度知道的回答:https://zhidao.baidu.com/question/1387978414020167860.html
页: [1] 2 3
查看完整版本: JS基础:字符串的不可变性 VS 简单类型数据类型在内存中的存储