这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要介绍了 Javascript 中的包装类型介绍, 包装类型是指在执行代码的一瞬间把数据包装成引用类型, 本文讲解的就是这个小知识, 需要的朋友可以参考下
最近不看犀牛书了,那本翻译的特烂而且好拗口,尤其是原型那块说的乱七八糟,后来经同事介绍,买了本 js 高级程序设计,然后就继续苦逼的看,不吐槽了,继续说说 js 中有新鲜感的包装类型。
一:String
说到 String 类型,蛮有意思,平时我们都是这样定义一个 string 类型,如下图:
但是在 js 中有一点非常特别,那就是 string 类型是属于基本类型,不属于引用类型,那就说明 string 的值是保存在 "栈" 上面的,而很多语言不是这样,比如 C#,我觉得 js 不作为引用类型也是情有可原,毕竟它玩不了多线程,而 C#中一个线程栈空间只分配 1M,如果 string 在 C# 中是值类型的话,那就有爆栈的可能,而 js 却没有栈空间限制,所以也就不存在爆栈的情况了。
那么下一个问题来了,我们经常会对 string 进行一系列的操作,比如 substring。如下图:
那刚才也说了,string 的值是直接保存在栈上面的,那它怎么会有 substring 呢?按照官网的解释是这样的:这时候会使用 String 类型把 s 包装成引用类型。然后使用 String 类型的内部实现,正好 String 内部定义了 substring 方法,所以其实上面的代码在 js 的内部应该是这样实现的。
- var s=new String("hello")
- var r=s.substring(3)
- s="hello"
可以看到,其实包装类型只是在执行代码的一瞬间,将 s 包装成了 String 引用类型,然后再调用 String 引用类型下面的 substring 方法,继而重新将 "hello" 值赋给 s,最后的效果就是 s="hello", r="lo",如果你仔细观察,你会发现,如果我给 s 动态的附一个属性,比如 color,那么你再次读取 color 的话,是不会读取 color 值的,比如下图:
如果你懂了上面我说的原理,那么你对 console.log(s.color) 等于 undefined 就不足以为奇了,我们可以看到,当我使用 s.color="red" 的时候,js 引擎发现有调用属性的写法,会立即在后台动态让其包装成 String 类型,然后就给 String 下面新增了一个属性 color=red,然后内部立刻会重新设置 s 的值为 "hello"(s="hello"),接下来当你 console.log 来输出 s.color 时,js 引擎判断又有调用属性的写法,再次 new String("hello") 了下,自然在这个新的 String 类型下面是没有 color 属性的,所以返回 undefined 了。
刚才我也说了,这种包装操作是 js 在后台动态追加和删除的,将基本类型转化为了引用类型,那么两者有多大的区别呢?
<1>:这个不用说,一个栈,一个堆,如果你对 C# 比较了解,可以认为是一个 box 和 unbox 的操作。
<2>: 我们知道所有的引用类型都是继承自 object,注意是引用类型,不要被面向对象搞混了,比如在 C# 中,所有的类型都是 object 子类,在 js
里面却不是这样,我们可以用 instanceof 看一下。
二:Boolean
如果你懂得了 String 这个包装类,那么其实 Boolean 包装类跟它是一个原理,只不过在 Boolean 类型的使用中,是有一个注意事项的,我们知道一个引用类型,除非它是 null 或者 undefined,否则它永远都是 true,而这个 Boolean 类型正是做了这个 box 操作,如下图:
我们看到这个时候 b 已经不是单纯的基本类型了,而是引用类型,这时候就再也 "与或" 不出我想要的结果了。还有一个 Number 包装类,这个也没什么注意事项的,就不说了。
来源: http://www.phperz.com/article/17/0430/271997.html