第七课:数值以及函数的扩展和修复

1.数值扩展和修复

toFixed(num) 方法可把 Number 四舍五入为指定小数位数的数字。num必需,规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。返回 NumberObject 的字符串表示,不采用指数计数法,小数点后有固定的 num 位数字。如果必要,该数字会被舍入,也可以用 0 补足,以便它达到指定的长度。如果 num 大于 le+21,则该方法只调用 NumberObject.toString(),返回采用指数计数法表示的字符串。

但在有些浏览器下不会这样干,于是修复:

if(0.9.toFixed(0) !==‘1‘){

  Number.prototype.toFixed = function(n){

    var power = Math.pow(10,n);    //Math.pow(x,y),返回 x 的 y 次幂的值

    var fixed = (Math.round(this*power) / power).toString();    //把一个数字舍入为最接近的整数。比如:0.5->1,0.4->0

    if(n == 0)  return fixed;      //当n等于0时,就直接调用round方法,把num四舍五入为最接近num的整数

    if(fixed.indexOf(‘.‘)<0)  fixed + = ‘.‘;        //如果是整数,并且n>0,那么需要添加n位小数。所以先添加小数点.

    var padding = n+1 - (fixed.length - fixed.indexOf(‘.‘));    //小数点后面必须有n个数字。没有就用0填补

    for(var i=0;i<padding;i++)  fixed + = ‘0‘;     //假设fixed为12.2,n为3,那么fixed.length=4,fixed.indexOf(‘.‘)=2,则padding = 4-2 =2;return 12.200

    return fixed;

  }

}

当javascript遇到一个数值时,它会首先尝试按照整数来处理该数值,如行得通,则把数值保存为31位的整数;如果该数值不能视为整数,或者超过31位的范围,则把数值保存为64位的IEEE754浮点数。

最大的Unicode值是1114111,最大的RGB颜色值是16777215(相当于#FFFFFF)。最大的10位数字是Math.pow(2,31)-1.最小的10位整数是-Math.pow(2,31)。

因此,js内部会以整数的形式保存所有Unicode值和RGB颜色。

我们尽量在前端只处理以整数形式保存的数字,大数和小数的操作尽量交给后台处理,实在避免不了,就用专业的库来处理。

2.函数的扩展与修复

bind函数:改变函数执行的上下文。低版本浏览器不支持,需要扩展。

Function.prototype.bind = function(context){

  if(arguments.length < 2 && context == undefined){

    //当传入的参数1个或者0个,并且第一个参数为undefined时(其实就是没传入context,或者传入一个undefined的context),就返回this,也就是函数本身

    return this;      //当方法say.bind(undefined,chaojidan),这种情况下,不会返回this,而是把chaojidan这个参数保存下来,之后会作为参数传到方法say中去。

  }

  var _method = this,args = [].slice.call(arguments,1);

  return function(){

    return _method.apply(context,args.concat.apply(args,arguments));

      //此函数在传入的context上下文中执行。并且把bind传入的参数和函数本身传入的参数合并成一个数组传入函数中执行。

  }

}

这个方法用的最多的是在IE下添加事件时,this的指向问题。IE的API attachEvent在回调中的this指向window.

var addEvent = document.addEventListener ? functon(el,type,fn,capture){  

    el.addEventListener(type,fn,capture)  ;

  } : function(el,type,fn){

    el.attachEvent("on"+type, fn.bind(el));     //把this指向了el元素

  }

apply方法第二个参数一定要是数组或者arguments这样的类数组(jQuery对象{0:"0",1:"1",length:2}也是类数组)。(NodeList这样的传进去在有些浏览器会出问题,因此jQuery中是使用merge来处理数组的合并,而不是使用Array.prototype.push.apply来处理,当然slice,concat这类的数组方法在有些浏览器下也不能很好的处理NodeList)。

hasOwnProperty判断是否是对象的实例属性,而不是原型属性。

bind方法着重于作用域的劫持,改变方法执行时的上下文。

curry 函数柯有化在于参数的不断补充,它可以给你再一次传参的机会,这样你就可以在内部判定参数的个数,决定是否继续返回函数还是结果。这在设计计算器的连续运算上非常有用。举个例子:function curry (fn){   

          function inner(len,arg){  

            if(len<=0)  return fn.apply(null,arg);  

            return function(){  return inner(len-arguments.length,arg.concat(Array.apply([],arguments)))  }  

          }   

          return inner(fn.length,[]); 

       }

function sum(a,b,c,d){  return a+b+c+d;  }

curry(sum)(‘a‘)()(‘b‘,‘c‘)(‘d‘)       //return ‘abcd‘;

这种自身调用自身来补全参数的,叫做self-curry或者recurry。

与curry相似的partial。curry的不足是参数总是通过push的方式来补全,而partial则是在定义时所有参数已经都有了,但某些位置上的参数只是一个占位符,我们在接下来的传参只是替换掉它们。

Function.prototype.partial = function(){

  var fn = this, args = Array.prototype.slice.call(arguments);

  return function(){

    var arg = 0;

    for(var i=0;i<args.length&&arg<arguments;i++ ){

      if(args[i] == undefined){

        args[i] = arguments[arg++];

      }

    }

    return fn.apply(this,args);

  }

}

这里是使用undefined作为占位符。

比如:var delay = setTimeout.partial(undefined,10);     ->  fn = setTimeout

delay(function(){});      //执行时,会先执行for循环,把partial中的参数遍历,如果有undefined,就用delay中的参数代替,因此这里会用function代替undefined。这时return setTimeout.apply(this,[function,10])。

对于占位符,我们可以使用一个纯空对象:

var _ = Object.create(null);      //纯空对象没有原型,没有toString,valueOf等继承自Object的方法。

另外一种实现方法:

function partial(fn){

  var A = [].slice.call(arguments,1);     //数组化

  return A.length < 1? fn : function(){

    var a = Array.apply([],arguments);    //数组化

    var c = A.concat();       //复制一份

    for(var i =0;i<c.length;i++)  if(c[i] === _)  c[i] = a.shift();

    return fn.apply(this,c.concat(a));

  }

}

function test(a,b,c,d){  return a+b+c+d;  }

var fn = partial(test, 1, _,2,_);        //这里的意思就是,方法test需要传入4个参数,目前只传入了两个。其他两个用_来占位。

fn(4,5)      //再传入两个参数,传参结果是(1,4,2,5),然后返回执行test的方法。

curry和partial的应用场景比较少,主要使用在异步上。比如:Ajax的异步函数回调嵌套问题,就可以使用curry将嵌套减少可以接受的范围。

加油!

时间: 2024-10-29 22:08:53

第七课:数值以及函数的扩展和修复的相关文章

【C++探索之旅】第一部分第七课:函数效应,分而治之

内容简介 1.第一部分第七课:函数效应,分而治之 2.第一部分第八课预告:传值引用,文件源头 函数效应,分而治之 上一课<[C++探索之旅]第一部分第六课:控制流程,随心所至>中,我们学习了条件语句和循环语句. 这两种语句也算是算法的核心了.在更早的课程中,我们学习了变量.这些都是所有编程语言的必备元素. 这一课我们又要学习一个几乎所有编程语言都有的极重要元素: 函数. C++的所有程序都或多或少用到函数,到目前为止,你其实也已经用了好多次了,不过你可能只缘身在此山中,还云深不知处. 函数的功

第七课 函数的嵌套调用【项目1-4】

第七课 函数的嵌套调用 项目一[k次方之和] 设计程序,计算: 请在下面的程序结构基础上完成设计. [cpp] view plain copy print? #include<stdio.h> int power(int m,int n); //求m的n次方(m^n) int sum_of_power(int k,int n);  //从1^k到n^k的累加和 int main( ) { int k, n; scanf("%d %d", &k, &n); p

第七课 进程通信

unix_c_07.txt================第七课 进程通信================一.基本概念------------1. 何为进程间通信~~~~~~~~~~~~~~~~~进程间通信(Interprocess Communication, IPC)是指两个,或多个进程之间进行数据交换的过程.2. 进程间通信分类~~~~~~~~~~~~~~~~~1) 简单进程间通信:命令行参数.环境变量.信号.文件.2) 传统进程间通信:管道(fifo/pipe).3) XSI进程间通信:

NeHe OpenGL教程 第七课:光照和键盘

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第七课:光照和键盘 光照和键盘控制: 在这一课里,我们将添加光照和键盘控制,它让程序看起来更美观. 这一课我会教您如何使用三种不同的纹理滤波方式.教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照.这一课

【C语言探索之旅】 第二部分第七课:文件读写

内容简介 1.课程大纲 2.第二部分第七课: 文件读写 3.第二部分第八课预告: 动态分配 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量类型 文件读写

[译文]JOAL教程 第七课 多普勒效应

[译文]JOAL教程 原文地址:http://jogamp.org/joal-demos/www/devmaster/lesson7.html 原文作者:Athomas Goldberg 译文:三向板砖 转载请保留以上信息. 本节课程对应的学习笔记:http://blog.csdn.net/shuzhe66/article/details/40393371 第七课多普勒效应 本文是DevMaster.net(http://devmaster.net/)的OpenAL教程对应的JOAL版本.C语言

7.7-UC-第七课:进程通信

================ 第七课  进程通信 ================ 一.基本概念 ------------ 1. 何为进程间通信 ~~~~~~~~~~~~~~~~~ 进程间通信(Interprocess Communication, IPC)是指两个, 或多个进程之间进行数据交换的过程. 2. 进程间通信分类 ~~~~~~~~~~~~~~~~~ 1) 简单进程间通信:命令行参数.环境变量.信号.文件. 2) 传统进程间通信:管道(fifo/pipe). 3) XSI进程间通信

BeagleBone Black板第七课:GPIO编程控制

BBB板第七课:GPIO编程控制 在一上课我们通过IO函数做了简单的GPIO端口输出高低电平输出,实现对一个LED指示灯的点亮和关闭控制,本节将通过完整的C++程序,实现第四课Shell脚本的全部功能,实现两个LED指示灯的交替闪亮. 直接通过进入功能程序 1.实现echo 44 > export 打开端口功能 上一课简单测试中,通过手工在BBB板终端模式下打开gpio44端口可通过以下程序实现: #include <stdio.h> #define GPIO_DIR "/sy

第七课 GDB调试 (下)

1序言: 通过前面一节第六课 GDB调试 (下)文章,可以掌握理解了gdb调试:怎么启动.运行,打断点.查看变量.甚至改变变量等的知识,今天来大概讲解下调试bug的类型. 2知识点: 2.1 就像之前所说的没有任何一个程序员敢打包票自己写的代码是没任何bug,bug总会有意无意的出现在我们眼前,当程序运行结果于我们预期结果不一样的时候这时候我们就应该调试,总的来说bug分为:语法错误.逻辑错误.硬件异常: 3原理: 3.1 语法错误:一般情况下出现在编译的时候会有提示编译错误这时候我们就可以马上