有一道经典的题目:

var add = function() {___}; console.log(add(3)(4)(5)); // 输出60

  题目要求能无限相乘,请补充add函数。

  首先很显然,add函数必须返回一个带一个参数的function,不然无法进行后续的连乘操作;其次,乘到最后,没有参数了,add函数直接得把数值返回。其实这类似一个深搜的函数,根据n的值进行递归:

 var add = function(n) {
   if(n === 5)
     return n;
   return n * add(n + 1);
 }
 console.log(add(3));

  第二行相当于没有参数时的判断操作,第四行相当于返回一个带参数的方法。此题的难点是值的累计,如果能设置一个全局变量保存值,将会方便很多,因为没有中间变量,而根据js函数特性又只能返回一个函数,不能返回函数与数字相乘的方式。如果能设置全局变量:

 var add = function(n) {
   ans *= n;
   return add;
 }
 var ans = 1;
 add(5)(4)(3);
 console.log(ans);

  因为要返回一个函数,又要实现值的累计,又不能外加变量,所以只能将累计的值作为参数传入。

 var add = function(a) {
   var temp = function(b) {
     return add(a * b);
   }
   return temp;
 }

  那么,add(3)(4)(5)在以上代码中是如何运作的?第一步a=3,b=4,运算后变成add(3*4)(5),第二步,a=12,b=5,运算后变成add(3*4*5),第三步a=60传入,temp方法return了,在控制台看到如下:

function (b) {
   return add(a * b);
} 

  这时就要关注一下function的toString和valueOf方法。重写toString和valueOf方法,就能得到答案。

 var add = function(a) {
   var temp = function(b) {
     return add(a * b);
   }
   temp.toString = temp.valueOf = function() {
     return a;
   }
   return temp;
 }
 console.log(add(3)(4)(5));

关于valueOf & toString:

  js里除了null外每个对象都有valueOf和toString方法,一般情况下对象会先调用toString方法,然后再调用valueOf。

var bbb = {
  toString: function() {
    console.log('toString');
    return 10;
  },
  valueOf: function() {
    console.log('valueOf');
    return 10;
  }
}

alert(bbb);// 10 toString
alert(+bbb); // 10 valueOf
alert(''+bbb); // 10 valueOf
alert(String(bbb)); // 10 toString
alert(Number(bbb)); // 10 valueOf
alert(bbb == '10'); // true valueOf
alert(bbb === '10'); // false

  这是司徒正美的一个例子,他也对结果作出了解释。如果转换为字符串时调用toString方法,如果是转换为数值时则调用valueOf方法,但其中有两个很不和谐,一个是alert(''+bbb),字符串合拼应该是调用toString方法……另一个我们暂时可以理解为===操作符不进行隐式转换,因此不调用它们。为了追究真相,我们需要更严谨的实验。

var aa = {
  i: 10,
  toString: function() {
    console.log('toString');
    return this.i;
  }
}

alert(aa);// 10 toString
alert(+aa); // 10 toString
alert(''+aa); // 10 toString
alert(String(aa)); // 10 toString
alert(Number(aa)); // 10 toString
alert(aa == '10'); // true toString

  因为aa没重写valueOf方法,在实际运行时,会先优先去寻找其toString方法,而比如alert(+aa)其实是应该优先调用valueOf方法的,但是木有valueOf,所以就退而求其次调用toString了。

var bb = {
   i: 10,
   valueOf: function() {
     console.log('valueOf');
     return this.i;
   }
 }

 alert(bb);// [object Object]
 alert(+bb); // 10 valueOf
 alert(''+bb); // 10 valueOf
 alert(String(bb)); // [object Object]
 alert(Number(bb)); // 10 valueOf
 alert(bb == '10'); // true valueOf

  而以上结果似乎不太和谐,顺着思路,没有toString方法,所以就调用valueOf,但是为何1和4输出的是[object object]。司徒正美说是继承了Object的toString方法,尝试去掉后:

Object.prototype.toString = null;

var cc = {
  i: 10,
  valueOf: function() {
    console.log('valueOf');
    return this.i;
  }
}

alert(cc);// 10 valueOf
alert(+cc); // 10 valueOf
alert(''+cc); // 10 valueOf
alert(String(cc)); // 10 valueOf
alert(Number(cc)); // 10 valueOf
alert(cc == '10'); // true valueOf

如果只重写了toString,对象转换时会无视valueOf的存在来进行转换。但是,如果只重写了valueOf方法,在要转换为字符串的时候会优先考虑toString方法。在不能调用toString的情况下,只能让valueOf上阵了。对于那个奇怪的字符串拼接问题,可能是出于操作符上,翻开ECMA262-5 发现都有一个getValue操作。嗯,那么谜底应该是揭开了。重写会加大它们调用的优化高,而在有操作符的情况下,valueOf的优先级本来就比toString的高。

valueOf和toString的更多相关文章

  1. Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...

  2. valueOf和toString的区别

    基本上所有的JavaScript数据类型都有valueOf(),toString()方法,null除外,这两个方法解决了JavaScript值运算和显示的问题 valueOf()会把数据类型转换成原始 ...

  3. Javascript中valueOf与toString区别

    前言 基本上,所有JS数据类型都拥有这两个方法,null除外.它们俩解决JavaScript值运算与显示的问题,重写会加大它们调用的优化. 测试分析 先看一例:var aaa = {  i: 10,  ...

  4. JavaScript的valueOf和toString

    深度好文 http://www.cnblogs.com/coco1s/p/6509141.html 知识要点 不同对象调用valueOf和toString的顺序不一样 高阶函数的使用,替代for循环 ...

  5. JS类型转换之valueOf和toString详解

    最近群里有人发了下面这题: 实现一个函数,运算结果可以满足如下预期结果: add(1)(2)// 3 add(1,2,3)(10)// 16 add(1)(2)(3)(4)(5)// 15 对于一个好 ...

  6. JavaScript中的valueOf与toString方法

    基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题. JavaScript 的 valueOf() 方法 valu ...

  7. 深入理解Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...

  8. valueOf()、toString()

    基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题. JavaScript 的 valueOf() 方法 valu ...

  9. String、String.valueOf、toString 它们三者的区别总结

    今天在使用这个的时候发现,他们三者好像在某些场所都是可以用的,但是不免会让人想到那既然它们三者这么的相似,那么总有些什么区别吧.我也在网上找了一些资料看.自己也看了API文档,就将他们三的区别总结一下 ...

随机推荐

  1. Tomcat如何添加管理员

    为Tomcat添加管理员,然后用管理员登录后就可以看到所有加载的工程包,以及运行的平台,还可以对项目进行管理,比如删和添加. 一.工具:apache-tomcat-7.0.39 二.添加步骤 1. 首 ...

  2. Python Backup Files

    近来书写 Python 脚本进行替换以前的 shell 脚本,发现 Python 优于 shell 的最直观的一点Python 结构明了,可读性高(本人认为)在此做一些记录 本次记录利用 Python ...

  3. Jena学习笔记(2)——利用数据库保存本体

    注明:本文档是使用Jena2.6.4,数据库为MySQL,数据库驱动版本为mysql-connector-java-5.1.13-bin.jar. 1 Jena的数据库接口 Jena提供了将RDF数据 ...

  4. 解决android的ListView嵌套在ScrollView中不能被滚动的问题

    使用滚动条容易带来一个后果,就是高度和宽度不受控制了, 之前就遇到一个已经有ScrollView的页面需要加个列表listView,然后就发现listView只看到前两行数据,下面的看不到,拉滚动条也 ...

  5. UI设计实战篇——利用Bootstrap框架制作查询页面的界面

    Bootstrap框架是一个前端UI设计的框架,它提供了统一的UI界面,简化了设计界面UI的过程(缺点是定制了界面,调整的余地不是太大).尤其是现在的响应时布局(我的理解是页面根据不同的分辨率,采用不 ...

  6. MVC+AjaxFileUpload文件上传

    来源:微信公众号CodeL 本次给大家分享的是ajaxfileupload文件上传插件,百度一大堆功能超炫的文件上传插件,为什么我们会选择这个插件呢? 原因是在此之前,我们尝试使用过很多基于flash ...

  7. selenium获取html的表格单元格数据

    获取网页的表格的某个单元格的值,思路: 1.获取表格 2.获取表格的所有行 3.根据某一行获取该行的所有列 4.根据某一列获得该行该列的单元格值 根据以上思路,可以知道,只需要行.列就可以得到单元格的 ...

  8. POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

    题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...

  9. Hadoop 一二事(1) - 简单介绍与杂谈

    大数据大数据,身边很多朋友都在谈大数据,Big Data!!! 到底是什么,用来干嘛的,也很少有人说得出一二,那今天开始就简单说说这一二事吧 hadoop 的来源:是作者女儿的一个玩具 - 一只黄色的 ...

  10. cygwin下的vim 的vimrc配置

    1.一直接照 vim 在linux的配置使用 cygwin下的 vi. vim --version 之后,出现了帮助...