JavaScript数据类型判断


JavaScript数据类型判断

确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符。

1、typeof

typeof()表示“获取变量的数据类型”,返回的是小写,语法为:

// 写法1
typeof 变量;
// 写法2
typeof(变量);

typeof 这个运算符的返回结果就是变量的类型。返回结果的类型是是字符串。

返回结果

类型展示

typeof 的代码写法 返回结果
typeof 数字 "number"
typeof 字符串 "string"
typeof 布尔型 "boolean"
typeof 对象 "object"
typeof 方法 "function"
typeof null "object"
typeof undefined "undefined"
typeof NaN "number"

!> ⚠️ 1:为什么 typeof null的返回值也是 "object"呢?因为 null 代表的是空对象
⚠️ 2:typeof NaN的返回值是 "number"NaN是一个特殊的数字,表示Not a Number,非数值。NaN 是一个特殊的数字。Undefined和任何数值计算的结果为 NaN。NaN 与任何值都不相等,包括 NaN 本身。

返回结果举例

console.log(typeof []); // 空数组的打印结果:object
console.log(typeof {}); // 空对象的打印结果:object

代码解释:这里的空数组[]、空对象{} ,为啥他们在使用 typeof 时,返回值也是 object呢?因为这里的 返回结果object指的是引用数据类型。空数组、空对象都是引用数据类型 Object

因此,在使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,都会返回"object"要想区别内置对象如Array、Date等,单纯使用 typeof 是不行的,JavaScript通过Object.prototype.toString方法,可以检测对象类型。

小结:

使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object”,“function”六种。

2、Object.prototype.toString.call()

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

可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg

原型链的概念

我们都知道js中的对象都继承自Object,所以当我们在某个对象上调用一个方法时,会先在该对象上进行查找,如果没找到则会进入对象的原型(也就是.prototype)进行查找,如果没找到,同样的也会进入对象原型的原型进行查找,直到找到或者进入原型链的顶端Object.prototype才会停止。

所以,当我们使用arr.toString()时,不能进行复杂数据类型的判断,因为它调用的是Array.prototype.toString,虽然Array也继承自Object,但js在Array.prototype上重写了toString,而我们通过toString.call(arr)实际上是通过原型链调用了Object.prototype.toString

判断对象的类型示例:

console.log(Object.prototype.toString.call("tom"));//[object String]
console.log(Object.prototype.toString.call(17));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "tom"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]
// 判断原生JSON对象
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);//输出结果为:[object JSON] ,说明JSON是原生的,否则不是;

对于自定义类型,Object.prototype.toString方法不能准确判断一个实例是否属于某种类型,因此引入instanceof 运算符进行判断。

//自定义类型
  function Person(name, age) {
      this.name = name;
      this.age = age;
  }
  var person = new Person("Rose", 18);
  Object.prototype.toString.call(person); // 打印 "[object Object]"
    console.log(person instanceof Person); // 打印 true

参考引用:

Object.prototype.toString.call(obj)精确判断对象的类型

MDN | Object.prototype.toString()

3、instanceof

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

原理:判断实例对象的proto属性与构造函数的 prototype 是不是用一个引用。如果不是,他会沿着对象的proto向上查找的,直到顶端 Object。

通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。例如:

// 判断 foo 是否是 Foo 类的实例
 function Foo(){};
 var foo = new Foo();
 console.log(foo instanceof Foo) // 输出 true

更重要的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。例如:

// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo(){}
 function Foo(){}
 Foo.prototype = new Aoo(); // JavaScript 原型继承
 var foo = new Foo();
 console.log(foo instanceof Foo) // 输出 true
 console.log(foo instanceof Aoo) // 输出 true

在多层继承关系中,instanceof 运算符同样适用。

instanceof 复杂用法(JavaScript 原型继承机制)

instanceof检测的是原型,用一段代码模拟一下内部执行过程:

instanceof (A,B) = {
    var L = A.__proto__;
    var R = B.prototype;
    if(L === R) {
        //A的内部属性__proto__指向B的原型对象
        return true;
    }
    return false;
}

以下为几个示例:

console.log([] instanceof Array); // true
console.log([] instanceof Object) // true
console.log(Object instanceof Object);//true
 console.log(Function instanceof Function);//true
 console.log(Function instanceof Object);//true
 console.log(Number instanceof Number);//false
 console.log(String instanceof String);//false
 console.log(Foo instanceof Function);//true

从上边的示例可以发现,虽然 instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,从 instanceof 能够判断出 [].__proto__指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最终 Object.prototype.__proto__ 指向了null,标志着原型链的结束。因此,[]、Array、Object 就在内部形成了一条原型链。

JavaScript 原型链

JavaScript 原型链

因此,==instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。==

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

当你在你的脚本中开始处理多个 frame 或多个 window 以及通过函数将对象从一个窗口传到另一个窗口时,比如,你可以通过使用Array.isArray(myObj) 或者Object.prototype.toString.call(myObj) === "[object Array]" 来安全的检测传过来的对象是否是一个数组。

支持 Array.isArray()方法的浏览器有 IE9+、 Firefox 4+、 Safari 5+、 Opera 10.5+和 Chrome。

当检测Array实例时, Array.isArray 优于 instanceof,因为Array.isArray能检测iframes

参考引用:

JavaScript instanceof 运算符深入剖析

instanceof详解

MDN | instanceof、Array.isArray()

4、constructor

constructor 属性返回对创建此对象的数组函数的引用。

语法:
object.constructor

示例:

function Person(){
  this.name = name;
}
var p = new Person('Joe');
console.log(p.constructor === Person); //true
console.log(p.__proto__ === Person.prototype); //true

https://www.cnblogs.com/ihardcoder/p/3667739.html 有待验证


评论
评论
  目录