浅谈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 相关文章推荐
jquery实现非叠加式的搜索框提示效果
Jan 07 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
Dec 01 Javascript
小白谈谈对JS原型链的理解
May 03 Javascript
Node.js Addons翻译(C/C++扩展)
Jun 12 Javascript
Javascript生成带参数的二维码示例
Oct 10 Javascript
ES6扩展运算符的用途实例详解
Aug 20 Javascript
微信小程序之蓝牙的链接
Sep 26 Javascript
vue vuex vue-rouert后台项目——权限路由(适合初学)
Dec 29 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变opacity实现)
Jan 24 Javascript
详解Vue源码学习之双向绑定
Apr 10 Javascript
解决webpack多页面内存溢出的方法示例
Oct 08 Javascript
vuex 实现getter值赋值给vue组件里的data示例
Nov 05 Javascript
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 MSSQL 存储过程的方法
2008/12/24 PHP
php 文件夹删除、php清除缓存程序
2009/08/25 PHP
解析PHP中数组元素升序、降序以及重新排序的函数
2013/06/20 PHP
初识Laravel
2014/10/30 PHP
php实现Linux服务器木马排查及加固功能
2014/12/29 PHP
PHP如何实现跨域
2016/05/30 PHP
php结合ajax实现手机发红包的案例
2016/10/13 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
2017/06/11 PHP
javascript中的绑定与解绑函数应用示例
2013/06/24 Javascript
jquery 取子节点及当前节点属性值
2014/07/25 Javascript
JavaScript验证18位身份证号码最后一位正确性的实现代码
2014/08/07 Javascript
javaScript中Math()函数注意事项
2015/06/18 Javascript
浅析jQuery 3.0中的Data
2016/06/14 Javascript
jQuery图片渐变特效的简单实现
2016/06/25 Javascript
浅谈jquery采用attr修改form表单enctype不起作用的问题
2016/11/25 Javascript
javascript中mouseenter与mouseover的异同
2017/06/06 Javascript
ES6 javascript的异步操作实例详解
2017/10/30 Javascript
vue如何在自定义组件中使用v-model
2018/05/14 Javascript
js实现多图和单图上传显示
2019/12/18 Javascript
VueX模块的具体使用(小白教程)
2020/06/05 Javascript
使用Python简单的实现树莓派的WEB控制
2016/02/18 Python
Python实现约瑟夫环问题的方法
2016/05/03 Python
Python遍历文件夹和读写文件的实现代码
2016/08/28 Python
使用anaconda的pip安装第三方python包的操作步骤
2018/06/11 Python
Django管理员账号和密码忘记的完美解决方法
2018/12/06 Python
Python lambda表达式用法实例分析
2018/12/25 Python
Python上下文管理器用法及实例解析
2019/11/11 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
使用CSS3和Checkbox实现JQuery的一些效果
2015/08/03 HTML / CSS
中国专业的综合网上购物商城:京东
2016/08/02 全球购物
成人教育自我鉴定
2013/11/01 职场文书
财务分析个人的自荐书范文
2013/11/24 职场文书
护士在校生自荐信
2014/02/01 职场文书
连锁酒店店长职责范本
2014/02/13 职场文书
2014年小学教师工作总结
2014/11/10 职场文书
JAVA 线程池(池化技术)的实现原理
2022/04/28 Java/Android