在JavaScript并非所有的一切都是对象


Posted in Javascript onApril 11, 2013

虽然很多语言宣称:“一切皆是对象”,但是 javascript 中,并不是所有的值都是对象。

原始值 vs 对象
javascript 中的值可以被划分为两大类:原始值(primitive)和对象(object)。

定义
javascript 的两种值的定义:

下面的值是原始值。

1.字符串
2.数字:在 JavaScript 中所有的数字都是浮点数
3.布尔值
4.null
5.undefined

所有其它的值都是对象(object)。对象可以进一步划分:

1.原始值的包装器:Boolean, Number, String。很少直接使用。

2.用字面量创建的对象。 下面的字面量产生对象,也可以通过构造函数创建对象。您可以使用字面量创建对象。

•[] 就是 new Array()
•{} 就是 new Object()
•function() {} 就是 new Function()
•/\s*/ 就是 new RegExp("\\s*")
3.日期:new Date("2011-12-24")

区别
您可以通过枚举的原语和定义对象非原语定义原语和对象。 但你也可以描述的原语和对象是什么。 让我们开始与对象。

1.对象是可变的:

> var obj = {};
> obj.foo = 123; // 添加属性和值
123
> obj.foo // 读属性,返回属性的值
123

2.每个对象都有自己唯一的标识符,因此通过字面量或构造函数创建的对象和任何其他对象都不相等,我们可以通过 === 进行比较。

> {} === {}
false

对象是通过引用来比较的,只有两个对象有相同的标识,才认为这个对象是相等的。

> var obj = {};
> obj === obj
true

3.变量保存了对象的引用,因此,如果两个变量应用了相同的对象——我们改变其中一个变量时,两一个也会随之改变。

> var var1 = {};
> var var2 = var1;
> var1.foo = 123; // 修改变量 val1 的属性
123
> var2.foo // val2 也改变了
123

正如预期的那样,原始值和对象不一样:

1.原始值是不可变的;你不能给它们添加属性:

> var str = "abc";
> str.foo = 123; // 添加属性(此操作将被忽略)
123
> str.foo // 读属性的值,返回 undefined
undefined

2.原始值没有内部标识,原始值是按值比较的: 比较两个原始值的依据是他们的内容,如果两个原始值的内容相同,这认为这两个原始值相同。

> "abc" === "abc"
true

这意味着,一个原始值的标识就是它的值,javascript 引擎没有为原始值分配唯一标识。

最后两个事实结合起来的意思是:我们无法区分一个变量到底是对象的引用,还是原始值的副本。

陷阱:原始值和它们的包装类型
规则:忽略尽可能多的包装类型。 在其他编程语言如Java,你很少会注意到他们。

原始值类型 boolean, number 以及 string 都有自己对应的包装类型 Boolean, Number 和 String。 包装类型的实例都是对象值,两种类型之间的转换也很简单:

•转换为包装类型:new String("abc")
•转换为原始类型:new String("abc").valueOf()
原始值类型以及它们相应的包装器类型有很多不同点,例如:

> typeof "abc"
'string'
> typeof new String("abc")
'object'
> "abc" instanceof String
false
> new String("abc") instanceof String
true
> "abc" === new String("abc")
false

包装类型的实例是一个对象,因此和 JavaScript 和对象一样,包装类型也无法进行值的比较(只能比较引用)。

> var a = new String("abc");
> var b = new String("abc");
> a == b
false // 虽然 a 和 b 有相同的内容,但是依然返回 false
> a == a
true

原始值没有自己的方法
包装对象类型很少被直接使用,但它们的原型对象定义了许多其对应的原始值也可以调用的方法。 例如,String.prototype 是包装类型 String 的原型对象。 它的所有方法都可以使用在字符串原始值上。 包装类型的方法 String.prototype.indexOf 在 字符串原始值上也有,它们并不是两个拥有相同名称的方法,而的的确确就是同一个方法:

> "abc".charAt === String.prototype.charAt
true

在数字的包装类型 Number 的原型对象有 toFixed 方法,即 Number.prototype.toFixed,但是当我们写如下代码时却发生错误:

> 5.toFixed(3)
SyntaxError: Unexpected token ILLEGAL

此错误是解析错误(SyntaxError),5 后面跟着一个点号(.),这个点被当作了小数点,而小数点后面应该是一个数,以下代码可以正常运行:

> (5).toFixed(3)
"5.000"
> 5..toFixed(3)
"5.000"

值的分类:typeof 和 instanceof
如果你想要对值进行分类,你需要注意原始值和对象之间的区别。 typeof 运算可以用来区分原始值和对象。instanceof 可以用来区分对象,而且,instanceof 对于所有的原始值都返回 false。

typeof
typeof 可以用来判断原始值的类型,以及区分对象值和原始值:

> typeof "abc"
'string'
> typeof 123
'number'
> typeof {}
'object'
> typeof []
'object'

typeof 返回以下字符串:

参数 结果
undefined "undefined"
null "object"
布尔值 "boolean"
数字 "number"
字符串 "string"
函数 "function"
其他 "object"

注释:

•typeof 在操作 null 时会返回 "object",这是 JavaScript 语言本身的 bug。不幸的是,这个 bug 永远不可能被修复了,因为太多已有的代码已经依赖了这样的表现。这并不意味着,null 实际上就是一个对象[4] 。

•typeof 还可以让检查一个变量是否已声明,而不会抛出异常。 没有任何一个函数可以实现此功能,因为你不能把一个未声明的变量传递给函数的参数。

> typeof undeclaredVariable
'undefined'
> undeclaredVariable
ReferenceError: undeclaredVariable is not defined

•函数也是对象类型;这可能是很多人无法理解的,但有时候却是非常有用的。

•数组是一个对象。

更多关于 typeof 的信息 [5] 和 [6]。

instanceof
instanceof 可以检测一个值是否是某个构造函数的实例:

value instanceof Constructor

如果上面的表达式返回 true,则表示 value 是 Constructor 的一个实例。它等价于:

Constructor.prototype.isPrototypeOf(value)

大多数对象是 Object 的实例,因为原型链的末端(prototype chain)是 Object.prototype。 原始值不是任何对象的实例:

> "abc" instanceof Object
false
> "abc" instanceof String
false
Javascript 相关文章推荐
jquery ajax例子返回值详解
Sep 11 Javascript
纯javascript制作日历控件
Jul 17 Javascript
详解javascript的变量与标识符
Jan 04 Javascript
AngularJS 面试题集锦
Sep 06 Javascript
jQuery post数据至ashx实例详解
Nov 18 Javascript
使用vue-cli+webpack搭建vue开发环境的方法
Dec 22 Javascript
Vue 页面切换效果之 BubbleTransition(推荐)
Apr 08 Javascript
使用puppeteer爬取网站并抓出404无效链接
Dec 20 Javascript
如何在Node和浏览器控制台中打印彩色文字
Jan 09 Javascript
JavaScript实现移动端带transition动画的轮播效果
Mar 24 Javascript
jquery+css3实现的经典弹出层效果示例
May 16 jQuery
Vue向后台传数组数据,springboot接收vue传的数组数据实例
Nov 12 Javascript
在JavaScript中typeof的用途介绍
Apr 11 #Javascript
浅谈关于JavaScript的语言特性分析
Apr 11 #Javascript
javascript中的delete使用详解
Apr 11 #Javascript
将字符串转换成gb2312或者utf-8编码的参数(js版)
Apr 10 #Javascript
原生js实现给指定元素的后面追加内容
Apr 10 #Javascript
图片无缝滚动代码(向左/向下/向上)
Apr 10 #Javascript
裁剪字符串trim()自定义改进版
Apr 10 #Javascript
You might like
php中批量修改文件后缀名的函数代码
2011/10/23 PHP
解析PHP中empty is_null和isset的测试
2013/06/29 PHP
php中利用explode函数分割字符串到数组
2014/02/08 PHP
CodeIgniter输出中文乱码的两种解决办法
2014/06/12 PHP
php基础教程
2015/08/26 PHP
php表单加入Token防止重复提交的方法分析
2016/10/10 PHP
php 数组处理函数extract详解及实例代码
2016/11/23 PHP
[原创]PHP实现SQL语句格式化功能的方法
2017/07/28 PHP
PHP实现用户登录的案例代码
2018/05/10 PHP
通过Mootools 1.2来操纵HTML DOM元素
2009/09/15 Javascript
分享一个我自己写的ToolTip提示插件(附源码)
2013/01/20 Javascript
JavaScript实现点击按钮后变灰避免多次重复提交
2013/07/15 Javascript
js中settimeout方法加参数
2014/02/28 Javascript
JS实现的表格行上下移动操作示例
2016/08/03 Javascript
纯原生js实现table表格的增删
2017/01/05 Javascript
js实现倒计时关键代码
2017/05/05 Javascript
DataTables添加额外的查询参数和删除columns等无用参数实例
2017/07/04 Javascript
优雅的将ElementUI表格变身成树形表格的方法步骤
2019/04/11 Javascript
layui表单验证select下拉框实现验证的方法
2019/09/05 Javascript
JavaScript ES6 Class类实现原理详解
2020/05/08 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
[03:39]这就是刀塔,我们是冠军!燃情短片讲述我们的DOTA故事
2019/07/02 DOTA
python 控制语句
2011/11/03 Python
Python中的自省(反射)详解
2015/06/02 Python
python实现用户登录系统
2016/05/21 Python
python如何获取服务器硬件信息
2017/05/11 Python
Python不同目录间进行模块调用的实现方法
2019/01/29 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
pandas map(),apply(),applymap()区别解析
2021/02/24 Python
canvas绘制圆角头像的实现方法
2019/01/17 HTML / CSS
荷兰家电销售网站:Welhof
2020/12/08 全球购物
必须要使用游标的SQL语句有那些
2012/05/07 面试题
计算机工程学院个人求职信
2013/10/05 职场文书
应届本科毕业生求职信
2014/07/23 职场文书
沈阳故宫导游词
2015/01/31 职场文书
幼师自荐信范文(2016推荐篇)
2016/01/28 职场文书