String() vs new String() 衍生出来的问题

516 阅读4分钟

Number 、 Boolean,也是相同的道理,在这里也一起说明。

先来看一下我们一般是怎么创建一个数字、字符串和布尔值的:

以字面量的方式创建
var num1 = 1;
var str1 = "I Love U";
var bool1 = true;
使用该对象而不带 new 操作符
var num2 = Number(1);
var str2 = String("I Love U");
var bool2 = Boolean(true);
使用 new 操作符
var num3 = new Number(1);
var str3 = new String("I Love U");
var bool3 = new Boolean(true);

看起来三种方式都创建了一个数字、字符串、布尔值,但是这三种创建出来的东西是否都一样呢?

先来看看第一种,一般来说,都是使用字面量的方式来创建数字、字符串和布尔值的,方便、简单。可是使用这种方法创建的变量为什么还是能够使用对应对象中的方法呢?举个例子让大家更好的理解。

var str = "I Love U";
typeof str  //  string
str.length  //  8

变量 str 明明只是一个字面量,它的数据类型是一个字符串并不是一个对象,我们也没有为它添加 length 这个属性,为什么访问 length 这个属性时会返回字符串的长度呢?这中间发生了什么呢?

其实 js 是有区分基本字符串类型和字符串对象的。当代码在一个字面量上(即例子中的变量 str )访问一个 String 对象的才有的属性时,js 会创建一个新的 String 对象,并且其值设置为变量中所包含的字符串的值,访问并打印出 length 属性,然后丢弃掉新创建的 String 对象。( Number 和 Boolean 也是相同的道理) 官方解释

再来看看第二种方式,刚刚说了 js 是有区分基本字符串类型和字符串对象类型的,那么第二种方式创建出来的变量是字符串类型还是对象类型呢?又能不能调用相应的 String 对象中的方法或属性呢?

var str = String("I Love U");
typeof str  //  string
str.length  //  8
str === "I Love U"  //  true

以上例子说明:第二种方式创建出来的变量类型和第一种方式创建出来的变量都是基本字符串类型,通常不会使用第二种方法来创建相应的基础数据类型,而是使用第二种方法来将变量转换成相应的的基础数据类型,例如:

var str = String(1)     //  将数字 1 转换成字符串 1
var num = Number('1')   //  将字符串 1 转换成 数字 1

最后来看看第三种创建方式,第三种创建方式使用了 new 关键字,即是实例化了相应的对象,通过例子来深入认识它:

var strObj = new String("I Love U");
var str = "I Love U"

typeof strObj   //  object
strObj.length   //  8
strObj == "I Love U"    //  true
strObj === "I Love U"   //  false

strObj.custom = 'a';
str.custom = 'a';
strObj.custom   //  'a'
str.custom      //  undefined

通过以上例子可以看出,通过第三种方式创建的变量数据类型为对象,而不是基本数据类型字符串,在 String 构造函数中已经定义好 length 等属性和方法,所以可以正常的使用。也可以自己扩展需要的属性或方法,但是基本数据类型却不可以,虽然在添加时并没有报错,因为在执行这个操作时,js 创建了一个新的 String 对象,并扩展了 custom 这个属性,但是扩展完之后已经丢弃掉这个创建的对象了,所以再想取这个属性的时候,js 又创建了一个新的 String 对象,这个对象和之前扩展了 custom 这个属性的对象并不是同一个对象,这个新的对象并没有 custom 这个属性,所以再取这个 custom 的值时是为 undefined。

总结
  1. 当我们想创建一个简单基本数据类型的变量时,可使用字面量的方式或使用该对象而不带 new 操作符
  2. 使用该对象而不带 new 操作符的方式通常用于基本数据类型的转换
  3. 当我们需要一个对象或想扩展一些属性和方式时,则使用 new 实例化一个对象的方式。
提问、思考

大家都知道在 new 操作符后面的函数就是一个构造函数,即: Number、String、Boolean都是一个构造函数,那为什么直接调用这个构造函数返回的变量是一个基本数据类型,而使用 new 操作符返回的变量却是一个对象呢 ?