> ## Content Index
> Fetch the complete content index at: https://blog.hacking.pub/llms.txt
> Use this file to discover other available public pages before exploring further.

# js valueOf
- URL: https://blog.hacking.pub/2017/04/08/js-valueof-2/
- Published: 2017-04-08T07:07:57.000Z
- Updated: 2017-04-08T07:13:39.000Z
- Author: chainhelen
- Tags: js, nodejs, javascript, valueOf, 柯里化

#### toString的区别

valueOf()：返回最适合该对象类型的原始值；  
toString(): 将该对象的原始值以字符串形式返回。

在数值运算里，会优先调用valueOf()，如a + b；  
在字符串运算里，会优先调用toString()，如alert(c)。  
[知乎来源](https://www.zhihu.com/question/24262399/answer/27215444?ref=blog.hacking.pub)

我在网上找到的其他例子，放在crhome里面跑，或者nodejsV7.7.2都是不同的  
所以有理由相信，之前的js实现跟当前流行的是不一样的，下面以nodejs为主

```
var c = { 
    i: 10,
    valueOf: function () {
        console.log("valueOf --->")
        return this.i + 30;
    },
    toString: function () {
       console.log("toString --->")
       return this.i + 10;
    } 
}
console.log(c > 20)
console.log(+c)
console.log(c)
console.log(String(c));
console.log(Number(c));

//output
valueOf --->
true
valueOf --->
40
valueOf --->
{ [Number: 40]
  i: 10,
  valueOf: [Function: valueOf],
  toString: [Function: toString] }
toString --->
20
valueOf --->
40

```

从上面结果可以看到，当对象尝试+、>等跟数字运算符相关的，都是优先调用Valueof的，而String强转才调用toString

算数运算符：+ - \* / % ++ --  
关系运算符：== != > >= < <=  
逻辑运算符：&& || ! ^ & |  
位运算符：& | \~ ^ >> << >>>

#### 难题

遇到过这样的一道难题，大概让写出满足下面条件的函数

```
console.log(
    f(10)(10) == 20 &&
    f(10)(20)(50) == 80 &&
    f(10)(20)(50)(100) == 180 &&
    f(10, 20, 50, 101) == 181 &&
    f(10, 20, 50)(102) == 182
)
上述为true

```

是的如果f返回的是一个数字，那么例子2的f(3)可能再去调用f(3)(2)呢？答案就是这个valueOf（如果函数对象没有toString的话，其实用toString也可以，如果没有valueOf的话，回去尝试调用toString）

[知乎上某答案区别](ttps://www.zhihu.com/question/31805304/answer/53390138)  
为什么valueOf比toString好呢？贴一段v8代码Object -> Primitive的过程：如果是Date类型的话，走DefaultString，否则走DefaultNumberDefaultNumber会判断Object有木有valueOf方法，有的话，直接调用return，没有的话去判断toString方法

```
/* -------------------------------------
   - - -   C o n v e r s i o n s   - - -
   -------------------------------------
*/

// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
// (1) for number hint, and (2) for string hint.
function ToPrimitive(x, hint) {
  // Fast case check.
  if (IS_STRING(x)) return x;
  // Normal behavior.
  if (!IS_SPEC_OBJECT(x)) return x;
  if (IS_SYMBOL_WRAPPER(x)) throw MakeTypeError('symbol_to_primitive', []);
  if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
  return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
}
// ECMA-262, section 8.6.2.6, page 28.
function DefaultNumber(x) {
  if (!IS_SYMBOL_WRAPPER(x)) {
    var valueOf = x.valueOf;
    if (IS_SPEC_FUNCTION(valueOf)) {
      var v = %_CallFunction(x, valueOf);
      if (%IsPrimitive(v)) return v;
    }

    var toString = x.toString;
    if (IS_SPEC_FUNCTION(toString)) {
      var s = %_CallFunction(x, toString);
      if (%IsPrimitive(s)) return s;
    }
  }
  throw %MakeTypeError('cannot_convert_to_primitive', []);
}

```

当然我这道题跟上面那道答案的题是有点不同的，不过本质上是一样的  
答案如下:

```
function f(){
    let sum = 0;
    for(i in arguments) {
        sum += arguments[i];
    }
    function m(){
        for (i in arguments) {
            sum += arguments[i];
        }
        return m;
    }
    m.valueOf=function(){
        return sum;
    }
    return m;
}

```

这东西叫柯里化，本质上如果直接打印f(10)其实还是打印对象本身

```
console.log(f(10))
//output
{ [Number: 10] valueOf: [Function] }

```