search

Home  >  Q&A  >  body text

javascript - 怎么理解ECMAScript中的字符串是不可变的?

JavaScript高级程序设计的第33页中提到:ECMAScript中的字符串是不可变的,然后给出了下面的示例。

var lang = "Java";
lang = lang + "Script";

第二行中赋值号左边的lang不就是第一行中定义的lang吗,然后给它赋了新的值不就改变了这个字符串吗。可上面又写到ECMAScript中的字符串是不可变的,这怎么理解?

天蓬老师天蓬老师2897 days ago671

reply all(7)I'll reply

  • 巴扎黑

    巴扎黑2017-04-10 15:01:21

    看图说话,如果string类型的值可变的话,就不存在物理地址B,能直接在地址A上对值进行更新。

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 15:01:21

    你要理解为内存中那块区域不能改变了。
    第二个lang实际上指向了另外一片内存区域了。

    reply
    0
  • 阿神

    阿神2017-04-10 15:01:21

    作为对比,对象和数组是时可变的(Mutable)

    (function() {
        function listMutator(list) {
            list.push('changed');
        }
    
        function objMutator(obj) {
            obj.changed = true;
        }
    
        function stringMutator(str) {
            //无论这里写任何代码都无法改变传入的str
            str += 'changed';
        }
    
        function main() {
            var list = [], obj = {}, string = 'javascript';
    
            listMutator(list);
            console.log(list);//[changed]
    
            objMutator(obj);
            console.log(obj);//{changed:true}
    
            stringMutator(string);
            console.log(string);//无论stringMutator怎么写,这里一定是javascript,也就是“不变性”
        }
    
        main();
    
    })();
    

    这和“按值传递”vs“按引用传递”有点像,初学来说按照“按值传递”的思路可能比较容易理解一点

    reply
    0
  • PHPz

    PHPz2017-04-10 15:01:21

    简单点说 var lang 定义了一个变量,变量就是一个内存起始地址,其指向内存中的内容是可变的!
    不可变指的是字符串常量,即"Java","Script"这样的字符串是不可变的,"Java"="Script"赋值是无法操作的。
    我理解的是这样的。

    查了下资料,楼下的解释应该是正确的。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:01:21

    javascript中明确规定了原始值(null、undefined、数值、布尔值、字符串)的值是不可改变的,这里的不可改变是指改变字符串本身在js中是禁止操作的。也就是说每新建一个字符串,都会开辟一块新的内存:
    var lang = 'java';
    lang = lang +'Script';
    假设保存第一行字符串的地址是A,第二行的地址是B;字符串不可改变的意思就是:执行第二条语句的时候,是新建一个字符串('java'+'Script'),然后将原来指向A的lang改为指向新的地址,即B,若字符串可以修改,那么此时应该是修改原来A地址中的值为javaScript,但是这样在js中是禁止的,所以说字符串是不可修改的。

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:01:21

    像是js,以及c#等一系列的语言,推出任何一个特征都要和c比一比,你知道的:)。

    string的不可变性也是一样,你看:

    1. C的string是可以改变的。

    你可以

    char str[] = "Foo";
    str[0] = ‘G'

    str的内容确实被改变了。可以通过print来证明。打印内容,也打印指针。指针不变,内容变了。

    2.js的不可改.如下的代码,没有任何效果,也可以log出来证明
    var str = "foo";
    str[0] = 'g' ;

    因为,语义上来说,这样做意味着原位修改str的内存区内容

    1. 但是你可以

    var str = "foo";
    var = 'bar'

    因为原位置的内存没有修改,是新分配的。只是打印不了指针,不好直接证明。要么就看代码,那就啰嗦了。非常非常的啰嗦。

    至于好处吗,和性能、存储效率、引用计数有关。

    所以,我就不讲了。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:01:21

    /* String 不可变 */

    var lang = 'Java';
    undefined
    lang[lang.length] = 'S';
    "S"
    lang[lang.length] = 'c';
    "c"
    lang[lang.length] = 'r';
    "r"
    lang[lang.length] = 'i';
    "i"
    lang[lang.length] = 'p';
    "p"
    lang[lang.length] = 't';
    "t"
    lang
    "Java"
    

    /* Array 可变 */

    var arr = ['J', 'a', 'v', 'a']
    undefined
    arr[arr.length] = 'S';
    "S"
    arr[arr.length] = 'c';
    "c"
    arr[arr.length] = 'r';
    "r"
    arr[arr.length] = 'i';
    "i"
    arr[arr.length] = 'p';
    "p"
    arr[arr.length] = 't';
    "t"
    arr
    ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]
    

    reply
    0
  • Cancelreply