4

javascript中ToPrimitive详解

 2 years ago
source link: https://snayan.github.io/post/explanatio_of_ToPrimitive/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

javascript中ToPrimitive详解

July 06, 2017/「 javascript 」/ Edit on Github ✏️

看了这么多框架方面的东西,但注意,基础很重要。今天就来说说 javascipt 中容易忽略的类型转换问题。 在 javascript 中有 7 种基本类型,它们为:stringnumberbooleanundefinednullsymbolobject。判断类型的方式是typeof。我们把stringnumberbooleanundefinednullsymbol这几类称为原始类型。

typeof 1 // 'number'
typeof "aa" // 'string'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof undefined // 'undefined'
typeof null // 'object'
typeof {} // 'object'
typeof function() {} // 'function'

注意两点,一是,对于函数,实际上也可以认为是object,但使用typeof得到的结果是function;二是,对于nulltypeof得到的结果是object

再来看看这些类型之间是怎么转换的呢?今天我们讨论的是object类型转为原始值,对于原始值转为object,可以直接进行包装即可,例如new Number(1),本次不予讨论,本次也不讨论原始类型之间的相互转换。

object 转为 number

先看看下面的几个情况,objectnumber,输出的值是几多

var obj = {}
console.log(Number(obj)) // NaN
obj = {
  valueOf: function() {
    return 1
  },
}
console.log(Number(obj)) // 1
obj = {
  toString: function() {
    return 2
  },
}
console.log(Number(obj)) // 2
obj = {
  valueOf: function() {
    return 1
  },
  toString: function() {
    return 2
  },
}
console.log(Number(obj)) // 1

从上面的例子可以看出,object转为number是根valueOftoString函数有关的。具体步骤如下:

  1. 调用对象的valueOf()方法,如果返回结果是原始类型,则根据这个原始类型再转换为number
  2. 否则,调用对象的toString()方法,如果返回的结果是原始类型,则根据这个原始类型再转换为number
  3. 否则,抛出一个异常TypeError。注意一点的是,symbol转为number时会抛出异常的,null转为number0

object 转为 string

我们再来看看下面的例子,输出是几多

var obj = {}
console.log(String(obj)) // "[object Object]"
obj = {
  valueOf: function() {
    return "a"
  },
}
console.log(String(obj)) // "[object Object]"
obj = {
  toString: function() {
    return "b"
  },
}
console.log(String(obj))
;("b")
obj = {
  valueOf: function() {
    return "a"
  },
  toString: function() {
    return "b"
  },
}
console.log(String(obj)) // "b"

从上面的例子可以看出,object转为string时也是与valueOftoString有关,步骤如下:

  1. 调用对象的toString()方法,如果返回值是原始类型,则再把这个原始类型转为string
  2. 否则调用对象的valueOf()方法,如果返回值为原始类型,则再把这个原始类型转为string
  3. 否则,抛出一个异常TypeError。注意,symbol转为string时会抛出异常。

object 转为 boolean

object转为boolean时总是true,在 javascript 中转为boolean且值为false时只有以下几种值;false''0NaNundefinednull

看了这么多,实际上主要是objectnumberstring时比较复杂,涉及 javascript 中内部的 ToPrimitive 方法。下面为 ecmascript262 中的官方定义:

The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType to favour that type.

函数签名为ToPrimitive(input[,PreferredType])=>PreferredType。如果 PreferredType 为 Number,则执行以下步骤:

  1. 如果 input 是原始值,则返回这个值,结束。
  2. 否则,如果 input 是对象,则调用input.valueOf()。如果结果是原始值,则把结果值转为Number
  3. 否则,调用input.toString()。如果结果是原始值,则把结果值转为Number
  4. 否则,抛出一个TypeError

如果PreferredTypeString,则把第二步和第三步进行交换。PreferredType也可以省略的,这种情况下,日期会被认为是String而其他值会被认为是Number。 需要注意的是,每个对象都有默认的valueOftoString方法,valueOftoString则根据具体的类型有所区别,  如下:

var obj = {}
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "[object Object]"
obj = [1, 2]
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "1,2"
obj = function() {}
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "function (){}"
obj = new Date()
console.log(obj.valueOf()) // 1497082546564
console.log(obj.valueOf() === obj) // false
console.log(obj.toString()) // "Sat Jun 10 2017 16:15:46 GMT+0800 (CST)"
//......

ecma-262


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK