跟我学习javascript的基本类型和引用类型


Posted in Javascript onNovember 16, 2015

一、基本类型和引用类型

基本的数据类型有5个:undefined,boolean,number,string,null

typeof null; //"object"
typeof undefined; //"undefined"
typeof 1; //"number"
typeof false //"boolean"
typeof "1" //"string"

(令人困惑的是,对null类型进行typeof操作得到的结果为“object”,然而,ECMAScript标准描述其为一个独特的类型。)

为了便于操作基本类型值,ECMAScript还提供了三个特殊的引用类型:Boolean、Number和String,标准库提供了构造函数来封装布尔值、数字和字符串作为对象。这些类型与其他引用类型相似,同时也具有与各自的基本包装类型相应的特殊行为。实际上,每当读取一个基本类型值时,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。

var s1 = "some text";
var s2 = s1.substring(2);
var s3 = new String("some text");

但是不同于原始的字符串,String对象是一个真正的对象。

typeof s1; //"string"
typeof s3; //"object"

这个例子中的变量s1包含一个字符串,字符串当然是基本类型值。而下一行调用了s1的substring()方法,并将返回的结果保存在s2中。我们知道,基本类型值不是对象,因此从逻辑上讲,它们不应该有方法(但是它们确实有方法)。其实,为了让我们实现这种直观的操作,后台已经自动完成了一系列的处理。当第二行代码访问s1时,访问过程处于一种读取模式,也就是从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成下列处理:

(1)创建String类型的一个实例。

(2)在实例上调用指定方法。

(3)销毁这个实例。

可以使用以下代码表示:

var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

经过此番处理,基本的字符串值就变得跟对象一样了。而且,上面三个步骤也适用于Boolean和Number类型对应的布尔值和数字值。

二、生命周期

引用类型与基本包装类型的主要区别就是对象的生命周期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,只存在于这一行代码的执行期(瞬间),然后立即销毁。这就意味着我们不能在运行时为属性添加属性和方法。

var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined

当然,可以显示调用Boolean、Number和String来创建基本包装类型的对象,不过,不帮不建议这么做。对基本包装类型的实例调用typeof会返回”object”,而且所有基本包装类型的对象都会被转化为布尔值true。。

var obj = new Object("some text");
alert(obj instanceof String) //true

值得注意的是,使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。

var value = "25";
var number = Number(value);//转型函数
alert(typeof number) //number

var obj = new Number(var); //构造函数
alert(typeof obj) //object

三、基本类型特点

1.基本类型的值是不可变得:

任何方法都无法改变一个基本类型的值,比如一个字符串:

var name = 'jozo';
name.toUpperCase(); // 输出 'JOZO'
console.log(name); // 输出 'jozo'

会发现原始的name并未发生改变,而是调用了toUpperCase()方法后返回的是一个新的字符串。
再来看个:

var person = 'jozo';
person.age = 22;
person.method = function(){//...};

console.log(person.age); // undefined
console.log(person.method); // undefined

通过上面代码可知,我们不能给基本类型添加属性和方法,再次说明基本类型时不可变得;

2.基本类型的比较是值的比较:

只有在它们的值相等的时候它们才相等。
但你可能会这样:

var a = 1;
var b = true;
console.log(a == b);//true

它们不是相等吗?其实这是类型转换和 == 运算符的知识了,也就是说在用==比较两个不同类型的变量时会进行一些类型转换。像上面的比较先会把true转换为数字1再和数字1进行比较,结果就是true了。 这是当比较的两个值的类型不同的时候==运算符会进行类型转换,但是当两个值的类型相同的时候,即使是==也相当于是===。

var a = 'jozo';
var b = 'jozo';
console.log(a === b);//true

3.基本类型的变量是存放在栈区的(栈区指内存里的栈内存)

假如有以下几个基本类型的变量:

var name = 'jozo';
var city = 'guangzhou';
var age = 22;

那么它的存储结构如下图:

跟我学习javascript的基本类型和引用类型

栈区包括了变量的标识符和变量的值。

四、引用类型特点

引用类型会比较好玩有趣一些。

javascript中除了上面的基本类型(number,string,boolean,null,undefined)之外就是引用类型了,也可以说是就是对象了。对象是属性和方法的集合。也就是说引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型。来看看引用类型的一些特性:

1).引用类型的值是可变的

我们可为为引用类型添加属性和方法,也可以删除其属性和方法,如:

var person = {};//创建个控对象 --引用类型
person.name = 'jozo';
person.age = 22;
person.sayName = function(){console.log(person.name);} 
person.sayName();// 'jozo'

delete person.name; //删除person对象的name属性
person.sayName(); // undefined

上面代码说明引用类型可以拥有属性和方法,并且是可以动态改变的。

2).引用类型的值是同时保存在栈内存和堆内存中的对象

javascript和其他语言不同,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,那我们操作啥呢? 实际上,是操作对象的引用,所以引用类型的值是按引用访问的。

准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。
假如有以下几个对象:

var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};

则这三个对象的在内存中保存的情况如下图:

跟我学习javascript的基本类型和引用类型

3).引用类型的比较是引用的比较

var person1 = '{}';
var person2 = '{}';
console.log(person1 == person2); // true

上面讲基本类型的比较的时候提到了当两个比较值的类型相同的时候,相当于是用 === ,所以输出是true了。再看看:

var person1 = {};
var person2 = {};
console.log(person1 == person2); // false

可能你已经看出破绽了,上面比较的是两个字符串,而下面比较的是两个对象,为什么长的一模一样的对象就不相等了呢?

别忘了,引用类型时按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同,那很明显,person1和person2在堆内存中地址是不同的:

跟我学习javascript的基本类型和引用类型

所以这两个是完全不同的对象,所以返回false;

五、简单赋值

在从一个变量向另一个变量赋值基本类型时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上:

var a = 10;
var b = a;

a ++ ;
console.log(a); // 11
console.log(b); // 10

此时,a中保存的值为 10 ,当使用 a 来初始化 b 时,b 中保存的值也为10,但b中的10与a中的是完全独立的,该值只是a中的值的一个副本,此后,这两个变量可以参加任何操作而相互不受影响。

跟我学习javascript的基本类型和引用类型

也就是说基本类型在赋值操作后,两个变量是相互不受影响的。

六、对象引用

当从一个变量向另一个变量赋值引用类型的值时,同样也会将存储在变量中的对象的值复制一份放到为新变量分配的空间中。前面讲引用类型的时候提到,保存在变量中的是对象在堆内存中的地址,所以,与简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象。那么赋值操作后,两个变量都保存了同一个对象地址,则这两个变量指向了同一个对象。因此,改变其中任何一个变量,都会相互影响:

var a = {}; // a保存了一个空对象的实例
var b = a; // a和b都指向了这个空对象

a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'

b.age = 22;
console.log(b.age);// 22
console.log(a.age);// 22

console.log(a == b);// true

它们的关系如下图:

跟我学习javascript的基本类型和引用类型

因此,引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
jQuery 数据缓存data(name, value)详解及实现
Jan 04 Javascript
JQuery文本框高亮显示插件代码
Apr 02 Javascript
实例分析javascript中的call()和apply()方法
Nov 28 Javascript
jQuery中last()方法用法实例
Jan 06 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
javascript控制层显示或隐藏的方法
Jul 22 Javascript
javascript HTML+CSS实现经典橙色导航菜单
Feb 16 Javascript
EasyUi 打开对话框后控件赋值及赋值后不显示的问题解决办法
Jan 19 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
Aug 17 Javascript
vue组件发布到npm简单步骤
Nov 30 Javascript
微信小程序自定义组件的实现方法及自定义组件与页面间的数据传递问题
Oct 09 Javascript
详解微信小程序开发之formId使用(模板消息)
Aug 27 Javascript
简单实现限制uploadify上传个数
Nov 16 #Javascript
跟我学习javascript的隐式强制转换
Nov 16 #Javascript
跟我学习javascript的浮点数精度
Nov 16 #Javascript
跟我学习javascript的严格模式
Nov 16 #Javascript
javascript中tostring()和valueof()的用法及两者的区别
Nov 16 #Javascript
关于javascript中dataset的问题小结
Nov 16 #Javascript
javascript入门教程基础篇
Nov 16 #Javascript
You might like
PHP中实现图片的锐化
2006/10/09 PHP
PHP支持多种格式图片上传(支持jpg、png、gif)
2011/11/03 PHP
php异常处理技术,顶级异常处理器
2012/06/13 PHP
PHP获取当前页面URL函数实例
2014/10/22 PHP
php简单实现无限分类树形列表的方法
2015/03/27 PHP
php跨服务器访问方法小结
2015/05/12 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
2015/12/19 PHP
PHP基于ORM方式操作MySQL数据库实例
2017/06/21 PHP
PHP测试框架PHPUnit组织测试操作示例
2018/05/28 PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
2019/08/13 PHP
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
JQuery记住用户名和密码的具体实现
2014/04/04 Javascript
在Ubuntu系统上安装Node.JS的教程
2015/10/15 Javascript
基于bootstrap风格的弹框插件
2016/12/28 Javascript
微信JSAPI支付操作需要注意的细节
2017/01/10 Javascript
Jquery实现跨域异步上传文件总结
2017/02/03 Javascript
JavaScript实现二分查找实例代码
2017/02/22 Javascript
jquery与js实现全选功能的区别
2017/06/11 jQuery
vue路由权限校验功能的实现代码
2020/06/07 Javascript
Python显示进度条的方法
2014/09/20 Python
实例讲解Python3中abs()函数
2019/02/19 Python
python3+pyqt5+itchat微信定时发送消息的方法
2019/02/20 Python
Django 权限认证(根据不同的用户,设置不同的显示和访问权限)
2019/07/24 Python
python自动化测试之异常及日志操作实例分析
2019/11/09 Python
Python for循环搭配else常见问题解决
2020/02/11 Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
2020/07/30 Python
俄罗斯家居用品购物网站:Евродом
2020/11/21 全球购物
Web Service面试题:如何搭建Axis2的开发环境
2012/06/20 面试题
战友聚会邀请函
2014/01/18 职场文书
2014年员工工作总结范文
2014/11/18 职场文书
部队2014年终工作总结
2014/11/27 职场文书
小学元宵节活动总结
2015/02/06 职场文书
2019年让高校“心动”的自荐信
2019/03/25 职场文书
导游词之神仙居景区
2019/11/15 职场文书
Python time库的时间时钟处理
2021/05/02 Python
浅谈音视频 pts dts基本概念及理解
2022/08/05 数码科技