IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JS学习笔记——JavaScript中常用的typeof、instanceof和Object.prototype.toString()等方法基础介绍 -> 正文阅读

[JavaScript知识库]JS学习笔记——JavaScript中常用的typeof、instanceof和Object.prototype.toString()等方法基础介绍

今天浏览博客时,看到一篇JS中对类型判断讲解的文章,感觉写的听好,正好平时在工作中也经常遇到判断类型的情况,所以就想记录一下。

1、typeof

众所周知,js是一门弱语言,它在声明变量时无需确定变量的类型,js在运行时会自动判断。那么如何判断一个变量的类型呢,js提供了typeof运算符

1.1、typeof的作用

typeof运算符:是用来检测一个变量的类型, 把类型信息当作字符串返回,值包括如下6种:

  • undefined:表示未定义的变量或值
  • boolean:表示布尔类型的变量或值
  • string:表示字符串类型的变量或值
  • number:表示数字类型的变量或值
  • object:表示对象类型的变量或值,或者null(这个是js历史遗留问题,将null作为object类型处理)
  • function:表示函数类型的变量或值

1.2、typeof的使用

示例:

console.log(typeof a);    //'undefined'

console.log(typeof(true));  //'boolean'

console.log(typeof '123');  //'string'

console.log(typeof 123);   //'number'

console.log(typeof NaN);   //'number'

console.log(typeof null);  //'object'

var obj = new String();

console.log(typeof(obj));    //'object'

var  fn = function(){};

console.log(typeof(fn));  //'function'

console.log(typeof(class c{}));  //'function'

【注意】需要注意的几点是:

  • NaN返回number
  • null返回Object
  • new String()的实例返回object
  • class返回function

1.3、typeof的局限性

typeof有一定的局限性,比如数组返回的也是object(如下图)

typeof([1,2,3])  //"object"
typeof(new Array())  //"object"

这样用来判断数组的话就不合适了,这时候可以选择使用instanceof

2、instanceof

2.1、instanceof的作用

instanceof 运算符:是用来测试一个实例对象在其原型链中是否存在一个构造函数prototype 属性。

官方解释:

The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor. 

从字面意思理解,就是判断一个对象(实例)的原型链上是否存在一个构造函数的prototype属性,也就是顺着__proto__一直找prototype

判断constructor.prototype是否出现在obj的原型链上:

function instanceof (obj, constructor) {
  // 获取实例对象obj的原型对象
  let proto = obj.__proto__
  while (true) {
    if (proto === null) {
      return false//原型链最终指向null,如果顺着proto一直找到null,还没找到原型,那就return false
    }
    if (proto === constructor.prototype) {
      return true//找到原型,return true
    }
    //顺着__proto__继续往上找
    proto = proto.__proto__
  }
}
function Foo(){}
let foo = new Foo()
instanceof(foo,Foo) //true
instanceof(foo,Function) //true
instanceof(foo,Object) //true

在JS原型链中,原型链最终指向null,所以如果顺着proto一直找到null,还没找到原型,那就return false

2.2、instanceof的使用

Object instanceof Object     //true
Object instanceof Function   //true

Function instanceof Object   //true
Function instanceof Function //true

String instanceof Object     //true
String instanceof Function   //true

Number instanceof Object     //true
Number instanceof Function   //true

String instanceof String     //false
Number instanceof Number     //false

分析可知:

  • Object.__proto__指向 Function.prototype,而Function.prototype.__proto__指向Object.prototype,所以前两个为true
  • Function.__proto__指向Function.prototype,而Function.prototype.__proto__指向Object.prototype,所以3和4也为true
  • StringNumber是函数,也都是先指向Function.prototype,再指向Object.prototype,所以5,6,7,8也都为true
  • Number instanceof Number和String instanceof String,为false,因为Number.__proto__Number.prototype完全是两回事,String同理

如果对于上面最后2个例子还是不理解,即Number.__proto__Number.prototype是两回事(String同理),可以看下面:

function abc(){}
abc instanceof abc  //false
  • 我们新建一个函数abc,则abc instanceof abc的意思就是看左边abc.__proto__是否存在abc.prototype,很明显,答案是false。
  • 因为左边abc.__proto__Function.prototype,而Function.prototype.__proto__又指向了Object.prototype,所以最终只能找到Object.prototype,但是右边是Foo.prototype,无法相等,结果是false

这样解释一下应该就好理解了。

基本数据类型:

对于一些基本数据类型:StringNumberBooleanUndefinedNullSymbol这种,最好不要用instanceof,因为根据instanceof的定义来看,instanceof是针对的an object(实例对象)的,所以判断基本数据类型的时候可能发生错误

let str1 = '1111'
let str2 = new String('1111')

console.log(str1 instanceof String)  //false
console.log(str2 instanceof String)  //true
String('1111') instanceof String     //false

由上述例子可以看出:

  • str1是基本数据类型,并不是一个对象,也不是由String实例化出来的,所以str1不是String的实例
  • str2是使用String构造的实例化对象
  • String('1111')没有使用new,所以并不是使用构造函数实例化,而是使用String这个函数返回了一个字符串1111, 所以为false

【注意】
instanceof 语法规定:object instanceof constructor,规定确认对象为object,所以左边如果不是对象的话,一定会返回false;

null比较特殊,虽然null是Object类型,但是null instanceof Object也是false,因为null是空对象不具有任何对象的特性,上面也没有__proto__属性

3、Object.prototype.toString()

3.1、Object.prototype.toString()的作用

Object.prototype.toString()方法:会返回一个形如 "[object XXX]"的字符串,可以用来判断数据类型

不过在说Object.prototype.toString()之前,我们先说一下toString()方法和Object.prototype.toString.call()方法

3.2、toString() 和 call()

MDN官网的解释是:toString() 方法返回一个表示该对象的字符串。

true.toString()  //"true"

[1,2,3].toString()  //"1,2,3"

('hello world').toString()  //"hello world"

({name:'tom'}).toString() //"[object Object]"

({}).toString();     // => "[object Object]"

Math.toString();     // => "[object Math]"

即如果对象的 toString() 方法未被重写,就会返回相应的字符串

但是,大多数对象toString() 方法都是重写了的,并不是 Object.prototype 中的 toString() 方法,这时就需要用 call() 方法来调用。

var arr=[1,2];

//直接对一个数组调用toString()
arr.toString();// "1,2"

//通过call指定arr数组为Object.prototype对象中的toString方法的上下文
Object.prototype.toString.call(arr); //"[object Array]"

为什么toString()会有不同的作用呢?这里我们不做深入的研究,只是简单明白这涉及到js原型及原型链相关知识即可,比如下面的例子:

var arr=[1,2,3];

Object.prototype.toString.call(arr);
//"[object Array]"
Array.prototype.toString.call(arr);
//"1,2,3"

看到这里大家都应该明白了,其实只有Object.prototype上的toString才能用来进行复杂数据类型的判断

  • JS中的对象都继承自Object,所以当我们在某个对象上调用一个方法时,会先在该对象上进行查找,如果没找到则会进入对象的原型(也就是.prototype)进行查找,如果没找到,同样的也会进入对象原型的原型进行查找,直到找到或者进入原型链的顶端Object.prototype才会停止
  • 所以,当我们使用arr.toString()时,不能进行复杂数据类型的判断,因为它调用的是Array.prototype.toString,虽然Array也继承自Object,但JS在Array.prototype上重写了toString
  • 而我们通过toString.call(arr)实际上是通过原型链调用了Object.prototype.toString方法

3.3、精确判断对象的类型

console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]

console.log(Object.prototype.toString.call(100));//[object Number]
console.log(Object.prototype.toString.call("wang"));//[object String]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call({name: "xiaohua"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([1,2,3]));//[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]
  • 可以看到这个方法能判断大多类型,但是针对我们自己创建的function,比如Person,返回的也是[object object],其余场景基本都覆盖到了,可以截取前8位到最后一位,作为类型判断

3.4、面试题

问:Object.prototype.toString和Object.toString是一回事吗?

答:

  • 不是。 因为Object.toStringObject.__proto__.toString,也就是去上一级的原型中拿的方法,是Function.prototype.toString,和Object.prototype.toString根本不是同一个函数
  • 同理NumberStringArray里的toString也和Object.prototype.toString不一样,而且它们也都被重写了toString方法。

可以测试一下,如果删除Array上的toString,我们知道顺着原型链一直找会找到Object.prototype上,这时候会调用Object原型上的toString了,通过控制台打印可以看到输出的是[object Array]。

var arr=[7,7,7];
console.log(Array.prototype.hasOwnProperty("toString"));//true
console.log(arr.toString());//7,7,7

delete Array.prototype.toString;//delete操作符可以删除实例属性

console.log(Array.prototype.hasOwnProperty("toString"));//false
console.log(arr.toString());//"[object Array]"

4、补充

在前面我们有提到,一个字符串,不是对象,但却可以调用String构造函数上的方法,例如:

var str = 'hello world'
str.toString() //"hello world"

简单理解就是,当原始数据类型(boolean,Number、String)在调用方法时,JS 将会创建对象,以便调用方法属性,而在使用完毕后将会销毁该对象

原始值被当作构造函数创建的一个对象来使用时, JS 会将其转换为一个对象,以便其可以使用对象的特性(如方法),而后抛弃对象性质,并将它变回到原始值。

这就牵扯到基本包装类型了,基本类型中BooleanNumberString又是基本包装类型,这三个基本类型都有自己对应的包装对象。包装对象,其实就是对象,有相应的属性和方法。调用方法的过程,是在后台发生的

细节可以参考:js 中的基本类型,引用类型,基本包装类型


本文参考博客:

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:35:15  更:2021-09-22 14:36:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 22:48:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码