使用 new String("already a string")
的用例是什么?
它的整个意义是什么?
使用 new String("already a string")
的用例是什么?
它的整个意义是什么?
new String("foo")
创建的String
对象实际上用处非常有限,它与原始字符串值唯一的区别在于作为一个对象,它可以存储属性:
var str = "foo";
str.prop = "bar";
alert(str.prop); // undefined
var str = new String("foo");
str.prop = "bar";
alert(str.prop); // "bar"
如果您不确定可以传递给您的代码哪些值,那么我建议您的项目存在更大的问题。没有任何一个原生的JavaScript对象、主要库或DOM方法会返回一个String
对象而不是字符串值。但是,如果您想要确保您拥有一个字符串值而不是String
对象,您可以按照以下方式进行转换:
var str = new String("foo");
str = "" + str;
如果你要检查的值可能是任何对象,则你有以下几个选项:
不必担心String对象,只需使用typeof。这是我的建议。
typeof str == "string"
。
同时使用instanceof和typeof。这通常可以工作,但缺点是对于在另一个窗口中创建的String对象会返回false negative。
typeof str == "string" || str instanceof String
使用鸭子类型。检查一个或多个特定于字符串的方法的存在,例如substring()或toLowerCase()。这显然不太精确,因为它会针对具有您正在检查的名称的方法的对象返回false positive,但在大多数情况下,它已经足够了。
typeof str == "string" || typeof str.substring == "function"
Javascript的创建者为像字符串或整数这样的基本类型创建了包装器,只是为了使它类似于Java。不幸的是,如果有人使用new String("x")创建一个新字符串,元素的类型将是"object"而不是"string"。
var j = new String("x"); j === "x" //false j == "x" //true
String
对象可以拥有属性,而字符串原始值则不行:
var aStringObject=new String("I'm a String object");
var aStringPrimitive="I'm a string primitive";
aStringObject.foo="bar";
console.log(aStringObject.foo); //--> bar
aStringPrimitive.foo="bar";
console.log(aStringPrimitive.foo); //--> undefined
而 String
对象可以被继承,而字符串原始值则无法:
var foo=Object.create(aStringObject);
var bar=Object.create(aStringPrimitive); //--> throws a TypeError
String
对象只能与其自身相等,而不能与具有相同值的其他String
对象相等,而具有相同值的原始类型被认为是相等的:
var aStringObject=new String("I'm a String object");
var anotherStringObject=new String("I'm a String object");
console.log(aStringObject==anotherStringObject); //--> false
var aStringPrimitive="I'm a string primitive";
var anotherStringPrimitive="I'm a string primitive";
console.log(aStringPrimitive==anotherStringPrimitive); //--> true
您可以实现类似于重载的行为:
function overloadedLikeFunction(anArgument){
if(anArgument instanceof String){
//do something with a String object
}
else if(typeof anArgument=="string"){
//do something with a string primitive
}
}
function aConstructorWithOptionalArugments(){
this.stringObjectProperty=new String("Default stringObjectProperty value");
this.stringPrimitiveProperty="Default stringPrimitiveProperty value";
for(var argument==0;argument<arguments.length;argument++){
if(arguments[argument] instanceof String)
this.stringObjectProperty=arguments[argument];
if(typeof arguments[argument]=="string")
this.stringPrimitiveProperty=arguments[argument];
}
}
或跟踪对象:
var defaultStringValue=new String("default value");
var stringValue=defaultStringValue;
var input=document.getElementById("textinput") //assumes there is an text <input> element with id equal to "textinput"
input.value=defaultStringValue;
input.onkeypress=function(){
stringValue=new String(this.value);
}
function hasInputValueChanged(){
//Returns true even if the user has entered "default value" in the <input>
return stringValue!=defaultStringValue;
}
String
对象和字符串原始值在Javascript中实际上给了你两种不同的字符串"类型",它们有不同的行为和用法。对于Boolean
和Number
对象及其相应的原始值也是如此。bind()
、call()
和apply()
时,要注意不要将字符串(或其他)原始值作为this
的值传递,因为该值将在使用之前被转换为String
对象(或一个Boolean
或Number
对象,具体取决于原始值)。请谨慎使用。function logTypeofThis(){
console.log(typeof this);
}
var aStringPrimitive="I'm a string primitive";
var alsoLogTypeofThis=logTypeofThis.bind(aStringPrimitive);
console.log(typeof aStringPrimitive); //--> string;
logTypeofThis.call(aStringPrimitive); //--> object;
logTypeofThis.apply(aStringPrimitive); //--> object;
alsoLogTypeofThis(); //--> object;
还有意外/反直觉的返回类型:
var aStringObject=new String("I'm a String object");
console.log(typeof aStringObject); //--> object
aStringObject=aStringObject.toUpperCase();
console.log(typeof aStringObject); //--> string
如果你真的想要非常谨慎,你可以使用 instanceof
:
if(typeof x === "string" || x instanceof String)
instanceof 运算符也可以正确地处理 String 的子类:
我认为我从未在 JavaScript 中使用过 String 类,但是追求正确性并保持警惕是没有错的。
obj instanceof ConstructorFunction
的工作原理是检查ConstructorFunction.prototype
是否在obj
的原型链中。
var obj = new String("something");
typeof obj; // "object"
obj = ""+obj;
typeof obj; // "string"
更新
虽然这似乎有效,但我还没有考虑过它的影响:
var obj = new String("something"), obj2 = "something else";
obj.constructor === String; // true
obj2.constructor === String; // true
isString(obj) {
return typeof obj === "string" || typeof obj === "object" && obj.constructor === String;
}
虽然我建议您只使用 typeof 和 "string",但用户应该知道通过普通字符串字面量传递。
我应该注意到,这种方法可能容易受到某人创建对象并将其构造函数设置为 String
(尽管它不是字符串...)的影响。
constructor
属性是不够的。在JavaScript中,可能会有一些奇怪的人子类化String。 - mu is too shortinstanceof
,但看起来OP只是想区分对象、字符串字面量和new String('blah')
。无论如何,这个想法已经出现了,我们可以整天吹毛求疵。 - davinObject.prototype.toString.call(aVariable) == '[object String]'
你也可以使用 toString
方法将一个 String 对象(以及其他任何对象)转换为 String 原始值:
var str = new String("foo");
typeof str; // object
typeof str.toString(); // string
感谢大家,即使经过这么多年,这个问题仍然没有一个确切的答案。
JavaScript 有两种类型的数据,
JS 设计时考虑到效率(你知道在 V8 上的JS就像火箭一样),所有原始值都是不可变的(更改 str 或 num 会在幕后创建一个新变量),而对象是可变的。
为了支持像对象一样使用原始值,JS 有了自动装箱的特性。因此,当我们使用任何方法(例如对于数字的 toString())与原始值一起使用时,JS 会自动将其转换为相应的对象,然后执行该方法并将其转换回原始值。通常情况下,我们不应该使用构造函数(带new)来代替原始值,而应该像使用原始值一样使用它(例如 let str = 'testStr')。使用构造函数对象而不是原始值可能会导致执行缓慢和复杂化。
为什么需要检查它是否为字符串?
只需检查它是否已定义或为空,否则可以进行防御性转换为您想要的任何类型,无论是 var bar = new String(foo);
还是 var bar = "" + foo;
。
str = "" + str;
将任何类型都转化为字符串。如果你只希望把 String 对象转换为字符串 (Number 对象转换为数值等),而不改变其他东西,可以写成str = str.valueOf()
。 - Timwi