类与类型 获取类型几种方式!!

说到类型,JavaScript 定义了少量的数据类型: null undefined 布尔值 数字 字符串 函数 和 对象。

假如要区分值得类型,无疑 typeof 首选 。如下

  

 1 typeof 1
 2 typeof "string"
 3 typeof true
 4 typeof null
 5 typeof undefined
 6 typeof {}
 7 typeof /\W/
 8
 9
10
11 :1 number
12 :2 string
13 :3 boolean
14 :4 object
15 :5 undefined
16 :6 object
17 :7 object

在以面向对象思想设计中,我们往往更希望将类作为类型来对待,这样就可以根据对象所属的类来区分它们。JavaScript 核心内置对象可以通过 class 属性来得到其类型,但是这种方式对于自定义对象来说是不能通过 class 属性来区分对应的类型。

  看看下面的实战代码-: 前面章节提到过 class 属性是不能直接获取,只能借助 toString 方式来获取,但是在 部分对象覆盖了 toString 例如 Date Math 等 那可以通过 call 或 apply 达到统一道理

function classOf(o) {
    if (o == null) return "Null";
    if (o === "undefined") return "undefined";
    return Object.prototype.toString.call(o).slice(8, -1);
}
function User() {}

console.log(classOf([]))
console.log(classOf(new Date()))
console.log(classOf(new RegExp()))
console.log(classOf(Math))
console.log(classOf({}));
console.log(classOf(new User()))

Array
Date
RegExp
Math
Object
Object

对于自定义对象是没有办法判断其属于什么类型,下面主要介绍下三个属性: instanceof运算符 、constructor属性、构造函数的名字。 但是每种技术都不甚完美。

  instanceof 语法格式

    操作符左边为实例对象,右边为定义构造函数。

  先来看看下面的简单实例: 

function A() {};
function B() {};
var a = new A();
console.log(a instanceof A); // true
A.prototype = new B();
console.log(a instanceof A); //false

  上面主要定义两个构造函数,然后声明一个变量a 再更改A的原型对象指向。 从上面两个输出来看,可以得出,只要 A.prototype 在a的原型链上的对象,不管是直接继承还是间接继承,其都会返回 true;

可以用下图表示:

 

 根据得出结论可以看出,在更该之后其原型 A.prototype 指向新的实例,并不存在于a对象原型链上。 从instanceof操作符右侧虽然制定的构造函数,但是其并不是根据其来进行判断,而是检测的是他们的继承关系。 那么有没有直接判断某个对象是不是继承另一个对象尼?

  Object.isPrototypeOf()

function A() {};

function B() {};
var a = new A();
console.log(A.prototype.isPrototypeOf(a));
A.prototype = new B();
console.log(A.prototype.isPrototypeOf(a));

true
false

instanceof 与 isPrototypeOf 两者缺点相同,不能通过对象获取类的名称,而是只能判断某个对象是不是存在其原型链上。

注意: 在多框架的情况下, 例如 宿主对象 Array ,在每个框架都拥有一套不同的构造函数,所以在进行A框架-> B框架传递一个Array实例时, 使用 instanceof 会返回false

constructor 属性

  顾名思义 获取对象的构造函数。构造函数是类的公共标识,所以判断某个实例是不是属于某个类可以直接使用 constructor属性

先来看看其使用:如下实例 

function Person() {}

function classOf(o) {
    var con = o.constructor;
    switch (con) {
        case Number:
            console.log("Number");
            break;
        case String:
            console.log("String");
            break;
        case Boolean:
            console.log("Boolean");
            break;
        case Array:
            console.log("Array");
            break;
        case RegExp:
            console.log("RegExp");
            break;
        case Date:
            console.log("Date");
            break;
        case Object:
            console.log("Object");
            break;
        case Person:
            console.log("Person");
            break;
    }
}

classOf(1);
classOf("string");
classOf(true);
classOf([]);
classOf(/\w/);
classOf(new Date());
classOf({});
classOf(new Person());

Number
String
Boolean
Array
RegExp
Date
Object
Person

 注意:这种方式也是存在一个问题,在多个上下文环境的(多框架的情况下),其是不能正确返回的问题。

  

构造函数名称

   在instanceof 和 constructor 在针对多中上下文的情况下,都会出现错误。如果在多框架下,唯一解决办法是可以通过根据构造函数名称而不已构造函数本省作为公共标识。

JavaScript中提供非标准的 name 属性,在某些浏览器中不支持name属性时,可以通过先把函数转换为字符串,再进行比较。  //主要获取函数名称

Function.prototype.getName = function() {
    return this.name || A.toString().match(/\w+\s*([^()*])/)[1];
}

注意:这种方式有一个问题是,当函数为匿名函数时,会返回空值。

  但是如果是对象(除函数外)时,可以利用其 class 属性 ,而 class 属性获取方式为:

function classOf(o) {
    if (o == null) return "Null";
    if (o === "undefined") return "undefined";
    return Object.prototype.toString.call(o).slice(8, -1);
}

结合上述几种方式,可以用来获取其type名称

function type(o) {
    var t, c, n;
    if (o === null) return "Null";
    if (o != o) return "NuN";
    /**
     * 通过这种方式:可以区分
     */
    if ((t = typeof o) !== "object") return t;

    //可以区分大部分的内置对象 在大多数情况下 都覆写了toString()
    if ((c = classOf(o)) !== "Object") return c;

    //自定义对象 并且存在constructor和函数名称属性
    if (o.constructor && typeof o.constructor === "function" && (n = o.constructor.getName())) return n;
    return "Object";
}
时间: 2024-12-10 07:22:22

类与类型 获取类型几种方式!!的相关文章

action中请求参数获取的两种方式

action中请求参数获取的两种方式 1.属性驱动? a.直接在 action 类中提供与请求参数匹配属性,提供 get/set 方法? b.在 action 类中创始一个 javaBean,对其提供 get/set ,在请求时页面上要进行修改,? 例如 user.username user.password ,要使用 ognl 表达式? 以上两种方式的优缺点:? 第一种比较简单,在实际操作我们需要将 action 的属性在赋值给模型(javaBean)去操作? 第二种:不需要在直接将值给 ja

Struts2 Web 资源获取的四种方式

Struts2 Web 资源获取一个有四种方式,两个大类 拦截器获取 Web 资源模式 静态对象获取 Web 资源模式 第一种:实现ServletRequestAware.ServletResponseAware.ServletContextAware接口 struts.xml <action name="FirstAction" class="Action.FirstAction"> <result name="success"

C++ socket 传输不同类型数据的四种方式

使用socket传输组织好的不同类型数据,有四种不同的方式(我知道的嘿嘿): a. 结构体 b. Json序列化 c. 类对象 d. protobuf 下面逐一整理一下,方便以后进行项目开发. 1. 使用结构体 假设需要传送的结构体如下: struct person { char name[20]; // 注意:CPU访问内存的时候,对访问地址有对齐的要求,一般为2的幂次方.所以,有的数据被填充,以满足对齐要求. int age; float high; }; 可在发送数据的地方对数据进行处理,

JS创建自定义类型对象的7种方式

https://blog.csdn.net/longyin0528/article/details/80504282 function createIterator (items){var i =0;var _add = function() {var num = items[0]+ items[1];return num;};return {showadd:function(){var num_result = _add();return num_result;}}}var iterator=

Spring 获取bean 几种方式

转载自: http://www.cnblogs.com/luoluoshidafu/p/5659574.html 1.读取xml文件的方式,这种在初学入门的时候比较适用 . ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:tt.xml"); ApplicationContext applicationContext = new FileSystemXmlAppli

Beanutils工具类,封装数据的三种方式,单例模式

org.apache.commons.beanutils.Beanutils; Beanutils setProperty(Object obj,String name,Object value) Object obj:被赋值的对象 String name:属性名 Object value:属性值 getProperty(Object obj,String name) 获取指定属性的属性值 Object obj: 对象 String name: 属性名 populate(Object bean,

Java 字符终端上获取输入三种方式

http://blog.csdn.net/hongweigg/article/details/14448731 在Java 字符终端上获取输入有三种方式: 1.java.lang.System.in (目前JDK版本均支持) 2.java.util.Scanner (JDK版本>=1.5) 3.java.io.Console(JDK版本>=1.6),特色:能不回显密码字符 package com.srie.chapter01; import java.io.BufferedReader; im

JS类对象实现继续的几种方式

0. ES6可以直接使用class,extends来继承. 1.  原型继承 1 2 父类: 3 4 function Persion(name,age){ 5 this.name = name; 6 this.age = age; 7 } 8 9 // 父类的原型对象属性 10 Persion.prototype.id = 10; 11 12 13 // 子类 14 function Boy(sex){ 15 this.sex = sex; 16 } 17 // 继承实现 18 Boy.pro

Spark SQL初始化和创建DataFrame的几种方式

一.前述       1.SparkSQL介绍 Hive是Shark的前身,Shark是SparkSQL的前身,SparkSQL产生的根本原因是其完全脱离了Hive的限制. SparkSQL支持查询原生的RDD. RDD是Spark平台的核心概念,是Spark能够高效的处理大数据的各种场景的基础. 能够在Scala中写SQL语句.支持简单的SQL语法检查,能够在Scala中写Hive语句访问Hive数据,并将结果取回作为RDD使用.     2.Spark on Hive和Hive on Spa