首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript中的字符串原语和字符串对象有什么不同?

JavaScript中的字符串原语和字符串对象有什么不同?
EN

Stack Overflow用户
提问于 2013-06-23 07:08:33
回答 12查看 56.2K关注 0票数 124

摘自MDN

新字符串文字(用双引号或单引号表示)和从非构造函数上下文中的字符串调用返回的字符串(即,不使用

关键字)是原始字符串。JavaScript自动将原语转换为String对象,因此可以对原语字符串使用String对象方法。在要对原语字符串调用方法或进行属性查找的上下文中,JavaScript将自动包装字符串原语并调用该方法或执行属性查找。

因此,我认为(逻辑上)对string基元的操作(方法调用)应该比对string对象的操作慢,因为在对string应用method之前,任何string基元都会转换为string对象(额外的工作)。

但在这个test case中,结果正好相反。-1\f25-1\f6编码块-1\f25-1\f6比-1\f25-2\f6编码块-2\f25-1\f6运行得更快,两个编码块如下:

代码块-1 :

代码语言:javascript
复制
var s = '0123456789';
for (var i = 0; i < s.length; i++) {
  s.charAt(i);
}

代码块-2 :

代码语言:javascript
复制
var s = new String('0123456789');
for (var i = 0; i < s.length; i++) {
    s.charAt(i);
}

结果因浏览器而异,但代码块-1\f25-1\f6总是更快。谁能解释一下,为什么代码块-1\f25-1比-1\f25-1代码块-2\f25-1快。

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2013-06-23 07:34:20

JavaScript有两个主要的类型类别,原语和对象。

代码语言:javascript
复制
var s = 'test';
var ss = new String('test');

单引号/双引号模式在功能方面是相同的。除此之外,您尝试命名的行为称为自动装箱。因此,实际发生的情况是,当调用包装器类型的方法时,原语被转换为包装器类型。简单地说:

代码语言:javascript
复制
var s = 'test';

是一种原始数据类型。它没有方法,它只是一个指向原始数据内存引用的指针,这解释了更快的随机访问速度。

例如,当你使用s.charAt(i)的时候会发生什么呢?

因为s不是String的实例,所以JavaScript将自动装箱s,它的包装器类型typeof stringString,带有typeof object,或者更准确地说是s.valueOf(s).prototype.toString.call = [object String]

自动装箱行为根据需要将s来回转换为其包装器类型,但标准操作的速度非常快,因为您正在处理更简单的数据类型。然而,自动装箱和Object.prototype.valueOf有不同的效果。

如果你想强制自动装箱或者将一个原语转换为它的包装器类型,你可以使用Object.prototype.valueOf,但是行为是不同的。基于各种各样的测试场景,自动装箱只应用“必需的”方法,而不改变变量的原始性质。这就是为什么你会获得更快的速度。

票数 160
EN

Stack Overflow用户

发布于 2013-06-23 07:45:52

这在很大程度上依赖于实现,但我会尝试一下。我将以V8为例,但我假设其他引擎也使用类似的方法。

字符串原语被解析为v8::String对象。因此,就像jfriend00提到的那样,可以直接在它上面调用方法。

另一方面,String对象被解析为扩展Objectv8::StringObject,除了是一个完全成熟的对象外,它还充当v8::String的包装器。

现在这是合乎逻辑的,在执行方法之前,对new String('').method()的调用必须对此v8::StringObjectv8::String进行拆箱,因此速度较慢。

在许多其他语言中,原始值没有方法。

MDN的方式似乎是解释原语的自动装箱如何工作的最简单的方法(在flav的回答中也提到了),即JavaScript的原语-y值如何调用方法。

但是,智能引擎不会在每次需要调用方法时都将字符串原语-y转换为字符串对象。关于解析原始值的属性(和“方法”),Annotated ES5 spec.中也提到了这一点:

备注在上述方法之外,无法访问在步骤1中创建的对象。实现可能会选择避免实际创建对象。..。

在非常低的级别上,字符串通常被实现为不可变的标量值。示例包装器结构:

代码语言:javascript
复制
StringObject > String (> ...) > char[]

你离原语越远,到达原语的时间就越长。在实践中,String原语比StringObject要频繁得多,因此引擎将方法添加到String原语的相应(解释的)对象的类中并不奇怪,而不是像MDN的解释所建议的那样在StringStringObject之间来回转换。

?在JavaScript中,“方法”只是一个属性的命名约定,它解析为函数类型的值。

票数 36
EN

Stack Overflow用户

发布于 2016-04-14 14:01:15

对于字符串文字,我们不能赋值属性

代码语言:javascript
复制
var x = "hello" ;
x.y = "world";
console.log(x.y); // this will print undefined

而在String对象的情况下,我们可以分配属性

代码语言:javascript
复制
var x = new String("hello");
x.y = "world";
console.log(x.y); // this will print world
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17256182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档