这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
前言
为什么字符串'abc'可以调用length属性?字符串'abc'本身不是一个对象,为什么可以用点.运算符来调用length?
原型上的方法
一开始我以为'abc'可以调用length属性,肯定是因为'abc'是String对象的实例,length不就是原型上的方法了吗?自然而然可以调用,于是简单写了几句。
console.log('abc'.length) // 3
console.log('abc' instanceof String) // false
instanceof用于判断一个变量是否某个对象的实例,为false,相当于字符串'abc'不是String对象的实例,所以不存在什么继承原型上的方法这一说!
那是咋回事呢?
这里引用一个概念包装对象
包装对象
包装对象指的是与数值、字符串、布尔值分别相对应的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引擎会默认转换为对应的包装类型,用包装类型上面的方法或属性。而非调用原型链上的方法和属性。