• vue js中使用typeof和Object.prototype.toString.call()判断类型(超详细),浅析call()和apply()的区别


    一、typeof

    《JavaScript权威指南》中对 typeof 的介绍:typeof 是一元操作符,放在其单个操作数的前面,操作数可以是任意类型。返回值为表示操作数类型的一个字符串。

    typeof返回的数据类型有6种,分别是:

    1、object,对象类型;

    tips:数组使用typeof 会返回object,null 被认为是一个空的对象引用,typeof(null)为object。

      

    2、undefined,未定义类型;

     

    3、string,字符串类型;

     

    4、number,数字类型;

      

    5、boolean,布尔类型;

     

    6、function,函数类型。

     综上可以看出,对于数组、对象来说,其关系错综复杂,使用 typeof 都会统一返回 “object” 字符串

    二、Object.prototype.toString.call()

    toString() 方法返回一个表示该对象的字符串。

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

    ES5 规范中当 toString 方法被调用的时候,下面的步骤会被执行:

    1. 如果 this 值是 undefined,就返回 [object Undefined]

    2. 如果 this 的值是 null,就返回 [object Null]

    3. 让 O 成为 ToObject(this) 的结果

    4. 让 class 成为 O 的内部属性 [[Class]] 的值

    5. 最后返回由 "[object " 和 class 和 "]" 三个部分组成的字符串

    下面列举使用Object.prototype.toString.call()的几种情况:(标黄较为常用)

    1.[object Number]

    为什么需要call?
    由于Object.prototype.toString()本身允许被修改,像Array、Boolean、Number的toString就被重写过,所以需要调用Object.prototype.toString.call(arg)来判断arg的类型,call将arg的上下文指向Object,所以arg执行了Object的toString方法。至于call,就是改变对象的this指向,当一个对象想调用另一个对象的方法,可以通过call或者apply改变其this指向,将其this指向拥有此方法的对象,就可以调用该方法了。

    此处引用Object.prototype.toString.call()原理_年轻的老六的博客-CSDN博客_object.prototype.tostring.call

    2.[object String]

    3.[object Boolean] 

    4.[object Undefined] 

    5.[object Null] 

    6.[object Object] 

    7.[object Array] 

    8.[object Date] 

    9.[object Error] 

    10.[object RegExp] 

    11.[object Function] 

    12.[object Math] 

    13.[object JSON] 

    三、.call()和.apply()的区别

    此处参考博客:call()和apply()方法的区别和详细用法_想你有幸的博客-CSDN博客_call方法和apply的区别是什么

    每个函数都包含两个非继承而来的方法:call()方法和apply()方法。callapply可以用来重新定义函数的执行环境,也就是this的指向;callapply都是为了改变某个函数运行时的context,即上下文而存在的,换句话说,就是为了改变函数体内部this的指向。

    • 相同点

    call()apply()方法的相同点就是这两个方法的作用是一样的。都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域

    一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向,看个例子:

    1. function add(a, b) {
    2.     return a + b;
    3. }
    4.  
    5. function sub(a, b) {
    6.     return a - b;
    7. }
    8.  
    9. console.log(add.call(sub, 2, 1));//3

    为什么add.call(sub, 2, 1)的执行结果是3呢,因为call()方法改变了this的指向,使得sub可以调用add的方法,也就是用sub去执行add中的内容,再来看一个例子:

    1. function People(name, age) {
    2.     this.name = name;
    3.     this.age = age;
    4. }
    5.  
    6. function Student(name, age, grade) {
    7.     People.call(this, name, age);
    8.     this.grade = grade;
    9. }
    10.  
    11. var student = new Student('小明', 21, '大三');
    12. console.log(student.name + student.age + student.grade);//小明21大三

    在这个例子中,我们并没有给Student的name和age赋值,但是存在这两个属性的值,这还是要归功于call()方法,它可以改变this的指向。
    在这个例子里,People.call(this, name, age);中的this代表的是Student,这也就是之前说的,使得Student可以调用People中的方法,因为People中有this.name = name;等语句,这样就将name和age属性创建到了Student中。

    总结一句话就是call()可以让括号里的对象来继承括号外函数的属性。

    • 不同点

    call()apply()的不同点就是接收参数的方式不同

    • apply()方法接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
    • call()方法不一定接受两个参数,第一个参数也是函数运行的作用域(this),但是传递给函数的参数必须列举出来。

    即call可以传入多个参数;apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入。

    PS:apply()可以将一个数组默认的转换为一个参数列表([param1,param2,param3]转换为param1,param2,param3)。

    例:

    1. var arr1 = [1, 2, 3];
    2. var arr2 = [4, 5, 6];
    3. arr1.push.apply(arr1, arr2);
    4. console.log(arr1);//[ 1, 2, 3, 4, 5, 6 ]

     

  • 相关阅读:
    java计算机毕业设计线上导医系统源码+数据库+系统+lw文档+mybatis+运行部署
    应变计在工程中的角色:精准监测与安全保障的得力助手
    java EE初阶 — 计算机工作原理
    3.3让我们直接对显示器说点什么吧
    题目0158-快递业务站
    从 B 站出发,用 Chrome devTools performance 分析页面如何渲染
    Win,M1Mac上安装jupyter的MATLAB支持插件的方法
    Docker搭建Mylar
    2022就业季|Spring认证教你,如何使用 Spring 构建 REST 服务
    【阅读】一周翻过《构建之法》,笔记整理
  • 原文地址:https://blog.csdn.net/weixin_43312391/article/details/126120860