为什么字符串’abc’可以调用length属性?字符串’abc’本身不是一个对象,为什么可以用点.运算符来调用length?
由字面量定义的字符串在使用其length属性时其实做了如下的操作
1、 创建了一个 String 类型的实例
2、使用实例的属性或方法
3、销毁实例
const str = 'abc'
console.log(str.length);
// 在执行 str.length 的时候 做了以下三步
// 1. let str = new String('abc')
// 2. console.log(str.length);
// 3. str = null
这里引用一个概念包装对象
包装对象
包装对象指的是与数值、字符串、布尔值分别相对应的Number、String、Boolean三个原生对象,在一定条件下,原始数据类型也会自动转为对象,所以万物皆对象。
var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);
typeof v1 // "object"
typeof v2 // "object"
typeof v3 // "object"
v1 === 123 // false
v2 === 'abc' // false
v3 === true // false
这个又要与Number(value),String(str),Boolean(value)几个方法区分开来,不加new运算符的时候,是将括号内的值转换为对应的原始类型值,如:
// 字符串转为数值
Number('111') // 111
// 数值转为字符串
String(111) // "111"
// 数值转为布尔值
Boolean(111) // true
所以什么情况下原始类型值会自动转换为包装对象,调用包装对象上的方法呢?
'abc'.length // 3
这种场合就会自动转,JavaScript 引擎在这种情况下会自动将其转为包装对象,在这个对象上调用length属性。调用结束后,这个临时对象就会被销毁。这就叫原始类型与实例对象的自动转换。 上述代码就相当于
var str = 'abc'
var strObj = new String(str)
// String {
// 0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"
// }
strObj.length // 3,直接调用自身的属性`length`,调用完立马销毁。
最后
所以总结就是,字符串或者数字,可以调用某种方法或属性,js引擎会默认转换为对应的包装类型,用包装类型上面的方法或属性。而非调用原型链上的方法和属性。