JavaScript:类型判断typeof

118 阅读4分钟

判断数据类型

在js中可以判断数据类型的关键字有typeofinstanceof,constructor ,Object.prototype.toString() js中的数据类型分为:

  • 基础数据类型:String,Nmuber,Boolean,Symbol,Null,Undefined
  • 引用数据类型:Object

typeof 运算符返回一个字符串,表示操作数的类型。

console.log('typeof  ""= ', typeof "");
console.log('typeof  1=  ', typeof 1);
console.log('typeof  true=  ', typeof true);
console.log('typeof  Undefined=  ', typeof undefined)
console.log('typeof  Symbol=   ', typeof Symbol('11'))
console.log('typeof Function=   ', typeof new Function())
console.log('typeof null=   ', typeof null)
console.log('typeof array=   ', typeof [])
console.log('typeof Date=   ', typeof new Date())
console.log('typeof Object=   ', typeof {})

运算结果如下

image.png

这个的结果:typeof 对 null ,Object 和Date 等一些数据都返回了Object,这个结果不是我们想要的

instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

根据字面意思就是实例对象的原型链上有没有某个prototype

function C(){}
function D(){}
C.prototype.add = {};
var o = new C(); //这个 __proto__ 指向了原型的内存地址,引用类型
console.log(o instanceof C)
C.prototype = {}; // 这个改变了  不影响O的原型地址
console.log(o instanceof C)

MDN描述:如果表达式 obj instanceof Foo 返回 true,则并不意味着该表达式会永远返回 true,因为 Foo.prototype 属性的值有可能会改变,改变之后的值很有可能不存在于 obj 的原型链上,这时原表达式的值就会成为 false。另外一种情况下,原表达式的值也会改变,就是改变对象 obj 的原型链的情况,虽然在目前的 ES 规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 __proto__ 伪属性,是可以实现的。比如执行 obj.__proto__ = {} 之后,obj instanceof Foo 就会返回 false 了。

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回 false,因为 Array.prototype !== window.frames[0].Array.prototype,并且数组从前者继承。所以这个结果也并不是我们想要的

constructor 构造函数属于被实例化的特定类对象

当一个函数被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向函数的引用

image.png

实例化对象指向,内部使用原型链查找本身不存在 constructor 属性

image.png

image.png

但是有一个问题:null 和 undefined 是有 constructor 属性他们还需要单独判断下,如果我改写了prototype那么就不准确了,为啥P1还能准确呢因为P1的__proto__ 是指向之前的引用地址的,所以不响应的

image.png

Object.prototype.toString

每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型

image.png

如果我们直接调用 Object.prototype.toString 。其他的对象覆写了这个方法,没有办法直接调用因为 this 指向的Object。我们想调用这个方法话是不是可以使用改变 this 来调用呀

// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true);            // => "[object Boolean]"

// Number 类型,tag 为 "Number"
Object.prototype.toString.call(1);               // => "[object Boolean]"

// String 类型,tag 为 "String"
Object.prototype.toString.call("");              // => "[object String]"

// Array 类型,tag 为 "String"
Object.prototype.toString.call([]);              // => "[object Array]"

// Arguments 类型,tag 为 "Arguments"
Object.prototype.toString.call((function() {
  return arguments;
})());                                           // => "[object Arguments]"

// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function(){});    // => "[object Function]"

// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error());     // => "[object Error]"

// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/);           // => "[object RegExp]"

// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date());      // => "[object Date]"

// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new class {});    // => "[object Object]"

这个方法可以准确的数据类型: 方便大家使用封装为方法

/* slice  提取某个字符串的一部分,并返回一个新的字符串
            且不会改动原字符串 支持负数从后往前找
 substring 法返回一个字符串在开始索引到结束索引之间的一个子集,
           或从开始索引直到字符串的末尾的一个子集。
 */
 // 这样觉得不想引用方法 建议使用该方法
function typeOf(params){
    // const  value =Object.prototype.toString.call(params)
    // return value.substring(8,value.length - 1)
    return  Object.prototype.toString.call(params).slice(8,-1)
}
// 做原型链引用的操作,数据劫持来实现,null 和 undefined 不能使用,还有可能被覆写了问题
Object.defineProperty(Object.prototype, '_typeOf', {
    //writable:false,      //属性的值是否可以被重写
    enumerable: false,   //是否会出现在for in 或者 Object.keys()的遍历中
    configurable: false, //是否配置,以及可否删除
    get() {
        return function () {
            return Object.prototype.toString.call(this).slice(8, -1)
        }
    }
})

学习到的知识点

  1. 原型链,继承
  2. 判断数据类型的方法
  3. 字符串截取的方法
  4. 数据劫持的方法
  5. js中的数据类型有那些
  6. 如有错误,请评论我校正