浅谈JavaScript中的string拥有方法的原因


Posted in Javascript onAugust 28, 2015

引子

我们都知道,JavaScript数据类型分两大类,基本类型(或者称原始类型)和引用类型。

基本类型的值是保存在栈内存中的简单数据段,它们是按值访问的。JS中有五种基本类型:Undefined、Null、Boolean、Number和String。

引用类型的值是保存在堆内存中的对象,它的值是按引用访问的。引用类型主要有Object、Array、Function、RegExp、Date。

对象是拥有属性和方法的,所以我们看到下面这段代码一点也不奇怪.

var favs=['鸡蛋','莲蓬'];
favs.push('秋葵');
console.log(favs);//["鸡蛋", "莲蓬", "秋葵"]
console.log(favs.length);//3

Array是引用类型,所以它自然可以拥有属性(length)和方法(push),这天经地义地就像夏天一定要吃冰淇淋一样。但是,再看下面的代码,仔细想想,这这这,合法吗?

var realMessage="Said I love you but I lied";
var myMessage=realMessage.substring(5,15);
console.log(myMessage); //"I love you"

有一个心碎的女纸任性地对一个用来分手的字符串任性地执行了“substring”方法,然后开心地看着剪辑版睡过去了。可是可是可是,不是说string是基本类型吗,为什么它可以拥有方法??还有没有王法啊青天大老爷!

其实,这一切,都是因为有个叫“基本包装类型”的东东。这个基本包装类型特别耿直,是真正的“事了拂衣去,深藏功与名”!

基本包装类型

除了一开始提到的Object、Array等引用类型,JavaScript还为我们提供了三种特殊的引用类型:String、Number和Boolean,方便我们操作对应的基本类型。

继续看上面的剪辑字符串的例子,有没有注意到,尽管使用了substring方法,realMessage本身的值是不会变的,调用这个方法只是返回了一个新的字符串。

这就是基本包装类型的作用了。本来你是没有方法的,但是你想用方法的时候,你尽管调,对应的基本包装类型有这个方法就行。例如上面的substring方法,string这个基本类型是不可能有这个方法的,但是String这个包装类型有啊,它会吭吭哧哧地把这个方法执行完把结果返回。在执行到:

realMessage.substring(5,15)

这行代码时,发生了很多事。

首先,它会从内存中读取realMessage的值。当处于这种读取模式下的时候,后台就开始干活了。JS高程是这样描述后台完成的这些动作的:

1.创建String类型的一个实例;
2.在实例上调用指定的方法;
3.销毁这个实例

上面的例子可以用这样的代码来说明:

var _realMessage=new String("Said I love you but I lied");
var myMessage=_realMessage.substring(5,15);
_realMessgae=null; //方法调用后即销毁

所以,这样我们就明白了,并不是基本类型string执行了自身方法,而是后台为它创建了一个对应的基本包装类型String,它根据基本类型的值实例化出了一个实例,让这个实例去调用指定方法,最后销毁自己,感天动地有木有。

注意最后一步基本包装类型“会销毁”的特性,这决定了我们不能为基本类型值添加自定义属性和方法。

var me="sunjing";
me.age=18;
console.log(me.age);//undefined

我给“me“这个字符串添加了age属性,值设为美好的18岁,然并卵,再次访问时,这个属性已经渺无踪迹了。这是因为:

执行到第二行代码属性赋值时,后台创建了一个基本包装类型的实例,这个age属性确实挂到实例上去了,但是紧跟着,这个实例就被销毁了。执行到第三行时,又重新创建了新的基本包装类型的实例,自然是没有age属性的。

显示使用基本包装类型

除了在字符串处于读取模式下,后台会帮我们创建基本包装类型实例时,我们自己也可以显示地创建。

var str=new String("hello");
var str2=str.toUpperCase();
console.log(str2);//"HELLO:

这样与后台帮我们创建时变量中保存的东西是不同的。

var str1=new String("hello");
var str2="hello";
typeof str1 //"object"
typeof str2 //"string"

总结

多亏了有基本包装类型,我们操作string、boolean、number这三种基本类型更方便了。每当读取这三种基本类型值时,后台会创建对应的包装类型实例,这个实例会调用指定方法,调用完会被销毁。这种短暂的生命周期决定了我们不能为基本类型添加自定义的属性和方法。

我们再来看下javascript中String类的subString()方法和slice()方法

最近在看《Javascript高级程序设计》一书,在书中发现一些以前没有接触过的且比较实用的技巧和知识点,想通过博客记录一下,以加深记忆。

在该书2.8.4节中讲到String类中的subString()方法和slice()方法,其用法和返回结果都基本相同,如下示例:

var strObj = new String("hello world");
alert(strObj.slice(3));    // 输出结果:"ol world"
alert(strObj.subString(3));  
// 输出结果:"ol world"
alert(strObj.slice(3, 7));    // 输出结果:"lo w"
alert(strObj.subString(3,7));   // 输出结果:"lo w"

由以上代码的输出结果可已看出,slice()方法和subString()方调用方法法和输出结果完全一样,这两种方法返回的都是要处理的字符串的子串,都接受一个或两个参数,第一个参数是要获取的子串的起始位置,第二个参数是要获取子串的终止位置,如果第二个参数省略终止位置就默认为字符串的长度,且两个方法都不改变String对象自身的值。

为什么有两个功能完全相同的方法呢?事实上,这两个方法并不完全相同,不过只在参数为负值时,他们处理参数的方式稍有不同。

对于负数参数,slice()方法会用字符串的长度加上参数,subString()方法将其作为0处理,例如:

var strObj = new String("hello world");
alert(strObj.slice(-3));

// 输出结果:"rld"
alert(strObj.subString(-3));
  // 输出结果:"hello world"
alert(strObj.slice(3,-4));

 // 输出结果:"lo w"
alert(strObj.subString(3,-4))
 // 输出结果:"hel"

这样既可看到slice()和subString()方法的主要不同。当只有参数-3时,slice()返回"rld",subString()则返回"hello world"。这是因为对于字符串"hello world",slice(-3)将被转换成slice(8),而subString(-3)则转化成subString(0)。同样,使用3和-4差别也是很明显。slice()方法将被转换成slice(3,7),与前面的例子相同,返回"lo w"。而subString()方法则将这个两个参数解释为subString(0,3),实际上是:subString(0,3),因为subString()总是把较小的参数作为起始位,较大的数字最为终止位。

Javascript 相关文章推荐
javascript之ESC(第二类混淆)
May 06 Javascript
TinyMCE汉化及本地上传图片功能实例详解
May 31 Javascript
bootstrap选项卡使用方法解析
Jan 11 Javascript
js 动态生成html 触发事件传参字符转义的实例
Feb 14 Javascript
如何正确理解javascript的模块化
Mar 02 Javascript
JavaScript实现图片切换效果
Aug 12 Javascript
利用JavaScript的%做隔行换色的实例
Nov 25 Javascript
详解Vue CLI3配置之filenameHashing使用和源码设计使用和源码设计
Aug 31 Javascript
使用weixin-java-miniapp配置进行单个小程序的配置详解
Mar 29 Javascript
浅谈bootstrap layer.open中end的使用方法
Sep 12 Javascript
js+css3实现简单时钟特效
Sep 13 Javascript
vue 动态创建组件的两种方法
Dec 31 Vue.js
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
Aug 27 #Javascript
jquery实现左右滑动菜单效果代码
Aug 27 #Javascript
jQuery实现响应鼠标背景变化的动态菜单效果代码
Aug 27 #Javascript
jQuery实现带幻灯的tab滑动切换风格菜单代码
Aug 27 #Javascript
jquery图片倾斜层叠切换特效代码分享
Aug 27 #Javascript
JavaScript实现非常简单实用的下拉菜单效果
Aug 27 #Javascript
JavaScript中的Function函数
Aug 27 #Javascript
You might like
php分页示例代码
2007/03/19 PHP
php计算多维数组中所有值总和的方法
2015/06/24 PHP
PHP中Restful api 错误提示返回值实现思路
2016/04/12 PHP
项目中应用Redis+Php的场景
2016/05/22 PHP
PHP进阶学习之垃圾回收机制详解
2019/06/18 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
jQuery 添加/移除CSS类实现代码
2010/02/11 Javascript
js 面向对象的技术创建高级 Web 应用程序
2010/02/25 Javascript
关于textarea提交的内容无法换行的解决办法
2013/04/09 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
Javascript实现可旋转的圆圈实例代码
2015/08/04 Javascript
JavaScript生成二维码图片小结
2015/12/27 Javascript
js实现商品抛物线加入购物车特效
2020/11/18 Javascript
javascript中sort排序实例详解
2016/07/24 Javascript
前后端常见的几种鉴权方式(小结)
2019/08/04 Javascript
一分钟学会JavaScript中的try-catch
2020/12/14 Javascript
学习python (1)
2006/10/31 Python
python中的字典详细介绍
2014/09/18 Python
Python中列表和元组的相关语句和方法讲解
2015/08/20 Python
Python实现视频下载功能
2017/03/14 Python
Python实现的凯撒密码算法示例
2018/04/12 Python
python 获取当天每个准点时间戳的实例
2018/05/22 Python
centos 安装Python3 及对应的pip教程详解
2019/06/28 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
解决Keras TensorFlow 混编中 trainable=False设置无效问题
2020/06/28 Python
施华洛世奇德国官网:SWAROVSKI德国
2017/02/01 全球购物
客房主管岗位职责
2013/12/09 职场文书
蜜蜂引路教学反思
2014/02/04 职场文书
超市开学活动方案
2014/03/01 职场文书
销售职业生涯规划范文
2014/03/14 职场文书
乡镇创先争优活动总结
2014/08/28 职场文书
2014年度个人工作总结
2014/11/07 职场文书
联谊活动总结范文
2015/05/09 职场文书
如何理解PHP核心特性命名空间
2021/05/28 PHP
IDEA2021.2配置docker如何将springboot项目打成镜像一键发布部署
2021/09/25 Java/Android