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 方式 看下面的代码 :    

View Code
 // 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=================

以上翻译只是出于自己学习, 不为商用. 如需转载请注明出处. 也欢迎指出不足共同进步.

    

posted @ 2012-08-21 17:30  Enein  阅读(2105)  评论(0编辑  收藏  举报