JavaScript values: not everything is an object
之前在技术群里看到这样一个问题 : "null is object?" 如果不是 为什么 typeof null // "object"
如果你不知道那就请看“Axel Rauschmayer” 对Object的理解.
英文原文地址 : http://www.2ality.com/2011/03/javascript-values-not-everything-is.html
===================Enein翻译=======================
这篇博客主要是说明JavaScript中两个比较重要的值: 基本类型、Object类型. 在它们工作中是有些地方要注意的.
【1】 基本类型与Object类型
在JavaScript中类型大体可以分为两种主要类型: primitives、objects;
【1.1】 定义
Primitives(以下简称使用英文代替) 类型的定义如下:
(1) Strings === > "abc"
(2) Number ===> 4, 3.75 (所有的numbers在JavaScript中都是浮点型的)
(3) Booleans ===> true, false
(4) null ===> 通常需要显示的分配.指定为'空'
(5) undefined ===> 通常为默认值. 自动分配
剩下的所有的类型都为Object Object还可以进行再次区分:
(1) 包装primitives(原型的, 基本)类型的'包装类'(在JavaScript中没有类的概念借用Java语言中的词使之表达), 一般不直接使用.
(2) 对象字面量:(尽可能的去使用'对象字面值'的这种形式去创建所需的对象)
* [] ==> (等同于) new Array()
* {} ==>(等同于) new Object()
* function(){} ==>(等同于) new Function()
* /\s*/ ==>(等同于) new RegExp("\\s*")
(3) 日期类型: new Date("2012-08-21")
【1.2】 性质不同
你可以通过列举primitives(基本类型)来定义基本类型,也可以通过非基本类型来定义Objects来定义Objects.
* 在默认情况下Objects是可变的.
> var obj = {}; > obj.foo = 123; // write : 123 > obj.foo; // read : 123
* 相比于引用, Objects有着独特的意义.
每个对象的创建通过表达式比如constructor('构造方法') 或使用字面量来不同于其它对象.实际上可以通过 (===) 绝对等于运算符.
通过引用比较对象: 两个对象仅在它们有相同的定义的时候才去比较、它们是否有相同内容这点不重要.
> {} === {} // false > var obj = {} > obj === obj // true
* 使用变量保存对象的引用
两个变量可以指向同一个对象, 改变一个变量观察另一个变量的值.
> var var1 = {}; > var var2 = var1; > var1.foo = 123; // 123 > var2.foo; // 123
反之primitives则是不同的;
* Primitives是不可改变的。
你加入的任何属性将会立即被销毁.
> var str = "abc"; > str.foo = 123 ; // write - ignored : 123 > str.foo //read : undefined
* Primitives之间是通过Value值来比较的, 本身没有明确的'实例'
比较两个基本类型, 一是看它们的value值, content, 如果它们的值相同那么它们就可以比较.
最后这两个实例联系一起说明 "你没有办法判断一个变量是primitives的指向还是完整的copy" 在内部 前者是对的主要针对于字符串,后者主要是针对numbers.
【2】陷阱: Primitives 和 它们的'包装器' 规则
尽可能的忽略包装类型,在比较其它的程序语言比如 Java. 你将很少注意它们.
这三个基本类型(primitives) string, number, boolean 有相应类型的实例: String, Number, Boolean
primitives类型与wrapper之间的转换:
* Primitives to wrapper : new String("abc")
* Wrapper to primitives: new String("abc").valueOf()
基本类型"abc"是不同于包装类型的比如 new String("abc"); 看一下 typeof / instanceof
> typeof "abc" // 'string' > type new String("abc") // 'object' > "abc" instanceof String // 'false' > new String("abc") instanceof String //'true' > "abc" === new String("abc") // 'false'
包装实例是Object,没有办法去比较两个object 在JavaScript中. 甚至不能使用'非严格模式'下的 == (这是非严格模式下的表达式, 推荐首先 === )
ps: 这里指出没有办法去比较两个object是否相等 注意是在JavaScript的内置属性中. 实际中可以根据自己的需求去prototype加入自己的equals。
> var a = new String("abc") > var b = new String("abc") > a == b // 'false' > a == a //'true'
【3】Prmitives值没它自己的属性
在JavaScript中Wrapper(包装类型)是很少被使用的. 作为 primitives 没有包装它们, 它们可以存储在anywhere. 但primitives没有自己方法只是从它的Wrapper中借用而已.
> "abc".charAt === String.prototype.charAt // 'true'
有两个途径可以完成'借用'.
一种老的方式: 是把 primitives 转换成 wrapper 。
一种新的方式(通过 ECMAScript 5 strict mode): 去显示地使用其包装类型的 prototype 方式 看下面的代码 :
// Methods in Object.prototype are available to all primitives Object.prototype.getType = function() { return typeof this; }; Object.prototype.getTypeStrict = function() { "use strict"; return typeof this; }; console.log("".getType()); // object console.log("".getTypeStrict()); // string
【4】 typeof 与 instanceof
如果你想区分一个值。不幸的是你必须了解决 primitives 与 objects的不同.
typeof 操作符是区分 primitives(基本类型) 有别与其它对象.
instanceof 操作符是区分 objects 如果是 primitives 就返回 false
【4.1】 typeof
typeof 主要是区别 primitives 与其它对象 :
> typeof "abc" // 'string' > typeof 123 // 'number' > typeof {} // 'object' > typeof [] // 'object'
typeof 返回值列表:
Value | Result |
Undeclared variables | "undefined" |
undefined | "undefined" |
null | "object" |
Booleans | "boolean" |
Numbers | "number" |
String | "string" |
Functions | "function" |
All Other values | "object" |
注释:
* null 返回 “object” 不能修复 是众所周知的Bug , 因为它将破坏现在的代码. 虽然typof null 为"object" 但不意味着 null 就是object (StackOverflow)
* typeof 允许你检查一个变量是否已经声名.不会抛异常. 这是函数不能做到的. 因为这样的变量是不能通过校验的.
> typeof undeclaredVariable 'undefined' > undeclaredVariable ReferenceError: undeclaredVariable is not defined
* Functions 实际上也是objects; 给它们自己的类型是有异议的.但有些时候还是很有用的.
* Arrays 是objects 数组是一种特殊的对象.是被明确规定成这样的.
【4.2】 instanceof
instanceof 基本语法:
value instanceof Constructor
如果value是Constructor的实例则返回 true;
等价于
Constructor.prototype.isPrototypeOf(value)
大多数的Objects 都是Object的实例, 因为它们prototype(原型)链最上端为 Object.prototype; Primititves没有实例.
> "abc" instanceof Object false > "abc" instanceof String false
===================Enein-End=================
以上翻译只是出于自己学习, 不为商用. 如需转载请注明出处. 也欢迎指出不足共同进步.