标签:style blog http java 使用 strong
JavaScript 对象
除了数字、字符串、布尔值、null、undefined(都不可变)这5种简单类型,其他都是对象。
javascript 存在2套类型系统,一套是元类型,用typeof可以检验,有六种:"number"、"string"、"boolean"、"object"、"function"、"undefined"。
另一套是对象类型系统,是元类型object的一个分支。
JavaScript中的对象是可变的键控集合(keyed collections)。
对象是属性的容器,其中每个属性都拥有名字和值。
JavaScript中的对象是无类别的(class-free)的。它对新属性的名字和值没有约束。
JavaScript包括一个原型链特性,允许对象继承另一对象的属性。
引用:
对象通过引用来传递,他们永远不会被拷贝。
原型:
每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype这个JavaScript中的标准对象。
原型连接在更新时不起作用。我们对某个对象做出改变时,不会触及到该对象的原型。原型连接只有在检索值时才会被用到。
包装类,以及“一切都是对象”。
typeof是JS语言中的一个运算符,从它的字面来看,显然它是用来获取类型的,按JavaScript标准的规定,typeof获取变量类型名称的字符串表示,他可能得到的结果有6种:string、bool、number、undefined、object、function,而且JavaScript标准允许其实现者自定义一些对象的typeof值。
在JS标准中有这样一个描述列表:
Type |
Result |
Undefined |
"undefined" |
Null |
"object" |
Boolean |
"boolean" |
Number |
"number" |
String |
"string" |
Object (native and doesn‘t implement [[call]]) |
"object" |
Object (native and implements [[call]]) |
"function" |
Object (host) |
Implementation-dependent
|
instanceof的意思翻译成中文就是"是……的实例",从字面意思理解它是一个基于类面向对象编程的术语,而JS实际上没有在语言级别对基于类的编程提供支持。JavaScript标准虽然只字未提,但其实一些内置对象的设计和运算符设置都暗示了一个"官方的"实现类的方式,即从把函数当作类使用,new运算符作用于函数时,将函数的prototype属性设置为新构造对象的原型,并且将函数本身作为构造函数。
所以从同一个函数的new运算构造出的对象,被认为是一个类的实例,这些对象的共同点是:1.有同一个原型 2.经过同一个构造函数处理。而instanceof正是配合这种实现类的方式检查"实例是否属于一个类"的一种运算符。猜一猜也可以知道,若要检查一个对象是否经过了一个构造函数处理千难万难,但是检查它的原型是什么就容易多了,所以instanceof的实现从原型角度理解,就是检查一个对象的[[prototype]]属性是否跟特定函数的prototype一致。注意这里[[prototype]]是私有属性,在SpiderMonkey(就是Firefox的JS引擎)中它可以用__proto__来访问。
原型只对于标准所描述的Object类型有意义,所以instanceof对于所有非Object对象都会得到false,而且instanceof只能判断是否属于某一类型,无法得到类型,但是instanceof的优势也是显而易见的,它能够分辨自定义的"类"构造出的对象。
instanceof实际上是可以被欺骗的,它用到的对象私有属性[[prototype]]固然不能更改,但函数的prototype是个共有属性,下面代码展示了如何欺骗instanceof
function ClassA(){};
function ClassB(){};
var o = new ClassA();//构造一个A类的对象
ClassB.prototype = ClassA.prototype; //ClassB.prototype替换掉
alert(o instanceof ClassB)//true 欺骗成功 - -!
Object.prototype.toString原本很难被调用到,所有的JavaScript内置类都覆盖了toString这个方法,而对于非内置类构造出的对象,Object.prototype.toString又只能得到毫无意义的[object Object]这种结果。所以相当长的一段时间内,这个函数的神奇功效都没有被发掘出来。
在标准中,Object.prototype.toString的描述只有3句
1. 获取this对象的[[class]]属性
2. 通过连接三个字符串"[object ", 结果(1), 和 "]"算出一个字符串
3. 返回 结果(2).
显而易见,Object.prototype.toString其实只是获取对象的[[class]]属性而已,不过不知道是不是有意为之,所有JS内置函数对象String Number Array RegExp……在用于new构造对象时,全都会设定[[class]]属性,这样[[class]]属性就可以作为很好的判断类型的依据。
因为Object.prototype.toString是取this对象属性,所以只要用Object.prototype.toString.call或者Object.prototype.toString.apply就可以指定this对象,然后获取类型了。
Object.prototype.toString尽管巧妙,但是却无法获取自定义函数构造出对象的类型,因为自定义函数不会设[[class]],而且这个私有属性是无法在程序中访问的。Object.prototype.toString最大的优点是可以让1和new Number(1)成为同一类型的对象,大部分时候二者的使用方式是相同的。
然而值得注意的是 new Boolean(false)在参与bool运算时与false结果刚好相反,如果这个时候把二者视为同一类型,容易导致难以检查的错误。
为了比较上面三种类型判断方法,我做了一张表格,大家可以由此对几种方法有个整体比较。为了方便比较,我把几种判断方式得到的结果统一了写法:
对象 |
typeof |
instanceof |
Object.prototype.toString |
标准 |
"abc" |
String |
—— |
String |
String |
new String("abc") |
Object |
String |
String |
Object |
function hello(){} |
Function |
Function |
Function |
Object |
123 |
Number |
—— |
Number |
Number |
new Number(123) |
Object |
Number |
Number |
Object |
new Array(1,2,3) |
Object |
Array |
Array |
Object |
new MyType() |
Object |
MyType |
Object |
Object |
null |
Object |
—— |
Object |
Null |
undefined |
Undefined |
—— |
Object |
Undefined |
事实上,很难说上面哪一种方法是更加合理的,即使是标准中的规定,也只是体现了JS的运行时机制而不是最佳使用实践。我个人观点是淡化"类型"这一概念,而更多关注"我想如何使用这个对象"这种约束,使用typeof配合instanceof来检查完全可以在需要的地方达到和强类型语言相同的效果。
sign bit(符号): 用来表示正负号
exponent(指数): 用来表示次方数
mantissa(尾数): 用来表示精确度
标签:style blog http java 使用 strong
原文地址:http://www.cnblogs.com/danghuijian/p/3848460.html