JavaScript隐式转换

193 阅读2分钟

JavaScript特点:JavaScript是一种弱类型,或者说是一种动态语言。这意味着你不用提前声明变量类型,在程序运行过程中,变量的数据类型会被自动确定

思考一个问题

思考一下,下面的代码会输出什么?

Object
console.log({} + {});
console.log({} - {});
console.log({} + 1);
console.log({} + "1");
console.log({} - 1);
console.log({} - "1");

Array
console.log([] + []);
console.log([] + 1);
console.log([] + "1");
console.log([] - 1);
console.log([] - "1");

Function
function a() {}

function aa(q, w, e) {}

console.log(a + aa);
console.log(a - aa);
console.log(aa.length);

Object 的隐式转换

console.log({} + {}); //[object Object]
console.log({} - {}); //NaN
console.log({} + 1); //[object Object]1
console.log({} + "1");//[object Object]1
console.log({} - 1);//NaN
console.log({} - "1");//NaN

当在使用运算符在计算时,如果存在复杂数据类型,那么它将会被转换为基本数据类型再进行运算。这就涉及“对象类型转基本类型”的这个过程。这个过程的具体规则是,在转换时,会调用对象上的toStringvalueOf方法,该方法的返回值是转换后的结果。

console.log({} + {}); //[object Object][object Object] 
console.log({}.toString() + {}.toString()); //[object Object][object Object] 
console.log({}.valueOf() + {}.valueOf()); //[object Object][object Object] 

在上面的代码案例中,可以明显看出,对象直接做运算的时候会调用实例上的,toString或者valueOf方法进行类型转换,但是这两个方法是可以重写的,我们尝试一下重写这两个方法。

console.log( //10
  {
    toString() {
      return 9;
    },
  } + 1
);
console.log( //"71"
  {
    valueOf() {
      return 7;
    },
  } + "1"
);
console.log(//1
  {
    toString() {
      return 2;
    },
  } - 1
);
console.log(//2
  {
    valueOf() {
      return 3;
    },
  } - "1"
);

从上面的案例可以看出,在重写了toStringvlueOf方法后,输出的方式完全被改变了,可以说明,重写这两个方法是可以改变了Object的隐式转换方式,因为在Object进行计算的时候,会去调用这两个方法进行隐式转换。思考一下,Object在进行隐式转换的时候,是调用vlaueOf,还是调用toString

console.log( //8
  {
    valueOf() {
      return 9;
    },
    toString() {
      return 3;
    },
  } - 1
);

console.log( //2
  {
    toString() {
      return 3;
    },
  } - 1
);

可以看出来,重写的时候,同时重写toStringvalueOf这两个方法的时候会先调用valueOf方法, 如果只有toString方法的时候,会只有调用toString方法。

Array

console.log([] + []); // 空
console.log([] + 1); //1
console.log([] + "1");//1
console.log([] - 1);//-1
console.log([] - "1");//-1

数组在做运算的时候,会调用自身的join方法进行,隐式转换,可以观察下面的代码,输出的结果是一模一样

console.log([].join() + [].join());  // 空
console.log([].join() + 1); //1
console.log([].join() + "1"); //1
console.log([].join() - 1);
console.log([].join() - "1");//-1