zoukankan      html  css  js  c++  java
  • Prototype源码浅析——Object部分(二)之类型检测

    扯淡:

    本来这个《Prototype源码浅析》是只打算作为学习Prototype的笔记的,不过有时候发现一个问题可以深入一点(虽然还是浅析),就脱离了原来的预期,越来越偏题了。今天的打算本来是写完Str的,但是写到变量检测的时候,发现又可以扯点淡,就又拖累了进程。这个对于项目来说,肯定是不好的,不过对于学习,就不清楚了。

    因为自己吃过的亏,所以从一个新手的角度,写得尽量新手向,新手共勉。

    这里我不关心javascript里面各种类型是怎么定义的,唯一要指出的是

    var str_1 = 'xesam';
    var str_2 = new String('xesam');
    console.log(str_1 === str_2);

    其中str_1和str_2不是同一个东西,先前看到群里面有个人提到类似的一个问题,所以才想起来的。

    检测一个变量的类型,最常见的就是typeof操作符。

    typeof的返回值是一个字符串,一般只能返回如下几个结果:number,boolean,string,function,object,undefined

    但是显然要是我们想区分Date,RegExp这样的具体类,typeof就没有办法了,于是统一归结到object里面

    先看一下Prototype里面的一些定义:

          NULL_TYPE = 'Null',
    UNDEFINED_TYPE = 'Undefined',
    BOOLEAN_TYPE = 'Boolean',
    NUMBER_TYPE = 'Number',
    STRING_TYPE = 'String',
    OBJECT_TYPE = 'Object',
    FUNCTION_CLASS = '[object Function]',
    BOOLEAN_CLASS = '[object Boolean]',
    NUMBER_CLASS = '[object Number]',
    STRING_CLASS = '[object String]',
    ARRAY_CLASS = '[object Array]',
    DATE_CLASS = '[object Date]',

    【这些变量的值是作为规定的结果返回,避免人为错误】

    回到变量检测上,

    我们看个实例:

        var array_1 = [null,undefined,10,NaN,'10',true,function(){}];
    var array_2 = [new Function(),new String(),new Number(),new Boolean(true),{},[],/x/,new Error(),new Date()];
    var varArray = array_1.concat(array_2);
    (function(){
    for(var i in varArray){
    console.log(typeof varArray[i]);
    }
    })();

    下面是结果:

    需要重点注意的几个是:

    null-->object

    NaN-->number

    带有new操作符的除了Function之外,全部都是object。

    我们按照Prototype的形式,包装一下这个过程,作为常规的过程,null和undefined这两个特别的我们先处理掉:

    (function(){
    //先定义一下类型的表示字符串
    var typeMap = {
    'number' : 'Number',
    'boolean' : 'Boolean',
    'string' : 'String',
    'function' : 'Function',
    'object' : 'Object',
    'undefined': 'Undefined',
    'null' : 'Null'
    };
    function type(obj){
    switch(obj){ //检测null和undefined
    case null:{
    return typeMap['null'];
    }
    case undefined:{
    return typeMap['undefined'];
    }
    }
    var objType = typeof obj;
    switch(objType){
    case 'number' : {
    return typeMap['number'];
    }
    case 'boolean' : {
    return typeMap['boolean'];
    }
    case 'string' : {
    return typeMap['string'];
    }
    case 'function' : {
    return typeMap['function'];
    }
    case 'object' : {
    return typeMap['object'];
    }
    }
    }
    for(var i in varArray){
    console.log(type(varArray[i]));
    }
    })();

    【说明:这里和Prototype里面有个不一致的地方,Prototype里面并没有用typeof来检测函数,我这里用了,注意就行】

    或者上面的例子再简单一点:

        (function(){
    function type(obj){
    return obj === null ? 'Null' :
    obj === undefined ? 'Undefined' :
    typeof obj === 'number' ? 'Number':
    typeof obj === 'boolean' ? 'Boolean':
    typeof obj === 'string' ? 'String':
    typeof obj === 'function' ? 'Function': 'Object';
    }
    for(var i in varArray){
    console.log(type(varArray[i]));
    }
    })();

    运行结果:

    现在我们分离出来了“基本类型”【我这里基本类型是指的typeof可以检测出来的类型,不是指的js的基本类型,大牛不要喷我···】

    接下来就是分离object那个里面的类型了。方法提供两个:

    第一、转化为字符串形式

    第二、检测原型

    第一种方法:

    先将获得对象的字符串表示形式,获得字符串形式的方法有几种:

    var obj = 'xesam';
    obj = ''+obj;
    obj = String(obj);
    obj = obj.toString();

    对于alert和consle这样的输出方法,输出对象的时候,都调用了对象的toString()方法。按理来说,这样没什么问题,但是Date,RegExp,Array等都是重写了从Object继承过来的toString的方法的,因此到底返回什么就无法预测了。

    所以要调用,必须使用最原始的Object.prototype.toString。
    使用最原始的Object.prototype.toString的局限就是无法判断自定义的类,除非自定义类重写了自己的toString方法,但是重写自定义类的toString方法之后又会引起枚举(in)的问题(Object第一部分提到过),所以这个需要仔细考虑一下。

    具体的实现如下:

       (function(){
    function objectType(obj){
    obj = Object.prototype.toString.call(obj);
    return obj;
    }
    for(var i in varArray_2){
    console.log(objectType(varArray_2[i]));
    }
    })();

    运行结果:

    第二种方法就是调用instanceof操作符

    比如:

    console.log([] instanceof Array);

    这就是 variable instanceof constructor的形式。

    或者直接判断constructor。

    具体实现:

        (function(){
    function objectType(obj){
    obj = obj.constructor;
    return obj === Array ? '[object Array]':
    obj === Boolean ? '[object Boolean]':
    obj === Date ? '[object Date]':
    obj === RegExp ? '[object RegExp]':
    obj === String ? '[object String]':
    obj === Function? '[object Function]':
    obj === Error ? '[object Error]':
    obj === Number ? '[object Number]':'[object Object]'
    }
    for(var i in varArray_2){
    console.log(objectType(varArray_2[i]));
    }
    })();

    运行结果:

    这个对于自定义的类,也可以获得相应的结果,只是稍微变通一下代码而已。


    转载请注明来自小西山子【http://www.cnblogs.com/xesam/
    本文地址:http://www.cnblogs.com/xesam/archive/2011/12/21/2296146.html

  • 相关阅读:
    有趣的面试题 11 单向链表
    CLR via C# 读书笔记 13 前台线程和后台线程
    c# 使用 new 操作符构造新对象中做了一些什么 (简单版)
    CLR via C# 读书笔记 11 何时使用线程或者线程池
    CLR via C# 读书笔记 31 一种单实例应用程序的实现(信号量)
    延时加载lazyload
    [评论]为什么中国的程序员技术偏低
    关于陈列设计和一些细节的体验
    滚动
    JavaScript 的 parseInt 取整
  • 原文地址:https://www.cnblogs.com/xesam/p/2296146.html
Copyright © 2011-2022 走看看