zoukankan      html  css  js  c++  java
  • 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=================

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

        

  • 相关阅读:
    普通锁和分布式锁
    java 正则表达式
    java 字符串转date 格式转换
    消息中间件 kafka
    数据的存储方式:对象存储、文件存储、块存储
    Exceptional Control Flow(6)
    Exceptional Control Flow(5)
    Exceptional Control Flow(4)
    Exceptional Control Flow(3)
    Exceptional Control Flow(2)
  • 原文地址:https://www.cnblogs.com/enein/p/Enein.html
Copyright © 2011-2022 走看看