你不知道的typeof string 竟然等于object

2,949 阅读4分钟

写在开头

  • 越是高级的岗位,从事越底层的工作,就越需要你对基础知识扎实,我以后不会再跟以前一样搞那么十几个的手写源码教程了,会更专注基础
  • 明天是1024,我会在公众号送出【100个现金红包】,不关注也可以参与抽奖,大家记得参与就好。(并非为了宣传公众号,就简单发个福利,让大家高兴热闹下,不少号主也经常抽到我的礼品)
  • 今天研究的是字符串

正式开始

  • 为什么要研究字符串
    • 因为JS有一个特殊点:typeof null结果是object
  • 还有一个原因是:字符串竟然有方法,但是它又不可以设置属性。让我们用代码揭晓
    const str = '前端巅峰Peter老师牛逼'
    str.xxoo = '你关注了吗?'
    console.log(str.xxoo, 'xxoo')
  • 结果输出:undefined
  • 为什么?
    • 因为字符串是基础数据类型,具体答案看后面。

可是字符串为什么又有方法?

  • 用代码说话:
    const str = '前端巅峰Peter老师牛逼'
    console.log(str.substring(1), 'xxoo')
  • 结果输出:端巅峰Peter老师牛逼

  • 划重点思考:为什么这个字符串 又有了方法? 明明它只是一个字符串啊!

被遗留的创建创建字符串方法

  • 还有一种创建字符串方法,我们忘了。
    const str = new Object('前端巅峰Peter老师牛逼')
    console.log(typeof str, 'str')
  • 打印结果:obect
  • 通过new Object创建的字符串,竟然typeof结果是object,那么我想,会不会是以某种情况访问字符串时,会自动转换成这样结果呢?

揭晓答案

  • 我们创建好了字符串后,通过平常的形式 例如:const str = '特皮牛逼',然后再去调用它的方法时,会有以下几个步骤:
    • 声明字符串:const str = '特皮牛逼'
    • 访问它的属性(方法):str.substring(1)
    • 以读模式访问str这个字符串,会有接下来几个步骤
      • new String返回一个实例
      • 调用实例上的substring方法
      • 销毁实例
      • 我之前文章提到过,JS里面的字符串一旦创建,他们的值就不能改变。要改变某个变量的保存的的字符串,首先要销毁原来的字符串,然后再用另外一个包含新值的字符串填充该变量
      • 所以上面这段代码,真实的运行应该是:
原始代码:
const str = 'Peter老师666'
str.substring(1)
真正内部执行的是:
let str = new String('Peter老师666')
let str1 = str.substring(1) 
str = null 

重点:JS里面的字符串一旦创建,他们的值就不能改变。要改变某个变量的保存的的字符串,首先要销毁原来的字符串,然后再用另外一个包含新值的字符串填充该变量

那么为什么给字符串设置属性为什么无效呢?

  • 我们声明:const str = '前端巅峰'
  • 然后给它设置属性 str.xxoo = 'xxoo'
  • 然后我们读取它的属性str.xxoo
  • 这期间经历了什么:
    • str.xxoo = 'xxoo'时,首先会创建一个实例,给这个实例上设置xxoo属性的值为:xxoo
    • 当这行代码执行完了,这个实例就销毁了
    • 于是当我们访问str的时候,并没有这个属性

这就叫原始值包装类型,它的声明周期只是这一行访问它的代码执行完就销毁了。这是它与引用类型的区别,我们通过new String()创建的实例就是一个引用类型,所以它是一个object.

通过new String创建的实例是一个对象(引用类型)

  • 代码:
    const str = new String('前端巅峰Peter老师牛逼')
    console.log(str, 'str')
  • 所以typeof str得到的结果是:object

写在最后

  • 如果有什么写得不好的地方,可以在下面评论指出,平时比较忙,以后会尽量写一些基础、底层被遗忘的知识点,不忘初心,写文章为了让更多人学到他们想要的
  • 如果感觉写得不错,点个赞/在看/关注吧,公众号:[前端巅峰]

本文使用 mdnice 排版

- END -