使用javascript类库函数时,经常会遇到一个函数,可以使用不同个数的参数的情况
比如:
exp(var1) exp(var1, var2)
但是在实际编写javascript函数时,
函数不能同名,所以不可能是不同参数个数分开写;
参数个数必须符合函数的设置,所以函数声明里有的就必须有,不可能调用时写少几个;
……
这个问题是困扰了很久了,一直不知道为什么?!
今天一早在看别人代码,无意中竟然看到了~
原来不是在函数声明中声明参数个数,而是在函数里直接接收使用,那怎么接收呢?
就是 arguments 了可以500%提高开发效率的前端UI框架!
arguments虽然不是数组,但可以当作数组使用,下标由 0 开始,所以:
arguments[0] 表示接收的第一个参数
arguments[1] 表示接收的第二个参数
……
如此类推……
这样就可以实现不同参数调用同一个函数了~
当然,前提是函数设置了对该参数的处理方法,不然还是白搭
顺便搜索了一下arguments的介绍,一并贴出:
arguments 属性
为当前执行的 function 对象返回一个arguments 对象。
function.arguments
function 参数是当前执行函数的名称,可以省略。
说明
通过 arguments 属性,函数可以处理可变数量的参数。 arguments 对象的 length 属性包含了传递给函数的参数的数目。对于arguments 对象所包含的单个参数,其访问方法与数组中所包含的参数的访问方法相同。
示例
下面的例子说明了 arguments 属性的用法: 可以500%提高开发效率的前端UI框架!
function ArgTest(){ var i, s, numargs = arguments.length; s = numargs; if (numargs < 2) s += " argument was passed to ArgTest. It was "; else s += " arguments were passed to ArgTest. They were " ; for (i = 0; i < numargs; i++) { s += arguments[i] + " "; } return(s); }
巧用arguments
在 Javascript 的函数中有个名为 arguments 的类数组对象。它看起来是那么的诡异而且名不经传,但众多的 Javascript 库都使用着它强大的功能。所以,它的特性需要每个 Javascript 程序员去熟悉它。
它以类似数组的形式保存了当前调用的参数。而它实际上并不是个数组,使用 typeof arguments 语句尝试会返回“object”(对象),所以它不能像 Array 一样使用 push 和 pop 等方法。即便如此,仍然可以使用下标以及长度属性(length)获取它的值。
编写灵活的函数
虽看起来名不经传,但的确 arguments 是非常有用的对象。比如,你可以让函数处理不定数目的参数。在 Dean Edwards 写的 base2 库中,有个叫 format 的函数充分发挥了这一特性: 可以500%提高开发效率的前端UI框架!
function format(string) { var args = arguments; var pattern = new RegExp("%([1-" + arguments.length + "])", "g"); return String(string).replace(pattern, function(match, index) { return args[index]; }); };
replace这个函数的第二个参数可以为一个函数,函数的第一个参数可以为匹配了的文本,第二个参数为第几个匹配的值,返回值为要进行替换的文本
这个函数实现了模板替换,你可以在要动态替换的地方使用 %1 到 %9 标记,然后其余的参数就会依次替换这些地方。例如:format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");
上面的脚本就会返回"And the papers want to know whose shirt you wear" 。
在这里需要注意的是,即便在 format 函数定义中,我们仅定义了个名为 string 的参数。而 Javascript 不管函数自身定义的参数数量,它都允许我们向一个函数传递任意数量的参数,并将这些参数值保存到被调用函数的 arguments 对象中。
转换成实际数组
虽然 arguments 对象并不是真正意义上的 Javascript 数组,但是我们可以使用数组的 slice 方法将其转换成数组,类似下面的代码
var args = Array.prototype.slice.call(arguments);
call(obj,当前函数使用的参数列表)可以500%提高开发效率的前端UI框架!
call 方法第一个参数为一个对象,这个传进去的对象将调用slice函数.因为arguments不是一个数组,所以不能直接调用slice方法,所以只能使用 ''对象冒充''方法了。这样,数组变量 args 包含了所有 arguments 对象包含的值。
使参数构建函数
使用 arguments 对象能够简短我们编写的 Javascript 代码量。下面有个名为 makeFunc 的函数,它根据你提供的函数名称以及其他任意数目的参数,然后返回个匿名函数。此匿名函数被调用时,合并的原先被调用的参数,并交给指定的函数运行然后返 回其返回值。
function makeFunc() { var args = Array.prototype.slice.call(arguments); var func = args.shift(); return function() { return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));}; }
arguments 有一个不可枚举的属性callee(不能用for in读出,可用HasOwnProterty(name)来判断),arguments.callee为正被执行的 Function 对象。slice时己把当前函数指针copy了过去,所以args的第一个元素为函数类型
makeFunc 的第一个参数指定需要调用的函数名称(是的,在这个简单的例子中没有错误检查),获取以后从 args 中删除。makeFunc 返回一个匿名函数,它使用函数对象的(Function Object)apply 方法调用指定的函数。
apply 方法的第一个参数指定了作用域,基本上的作用域是被调用的函数。不过这样在这个例子中看起来会有点复杂,所以我们将其设定成 null ;其第二个参数是个数组,它指定了其调用函数的参数。makeFunc 转换其自身的 arguments 并连接匿名函数的 arguments,然后传递到被调用的函数。
有种情况就是总是要有个输出的模板是相同的,为了节省每次是使用上面提到的 format 函数并指定重复的参数,我们可以使用 makeFunc 这个工具。它将返回一个匿名函数,并自动生成已经指定模板后的内容: 可以500%提高开发效率的前端UI框架!
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
你可以像这样重复指定 majorTom 函数:
majorTom("stepping through the door"); majorTom("floating in a most peculiar way");
那么当每次调用 majorTom 函数时,它都会使用第一个指定的参数填写已经指定的模板。例如上述的代码返回:
"This is Major Tom to ground control. I'm stepping through the door."
"This is Major Tom to ground control. I'm floating in a most peculiar way."
自引用的函数
您可能会认为这很酷,先别急着高兴,后面还有个更大的惊喜。它(arguments)还有个其他非常有用的属性:callee 。arguments.callee 包含了当前调用函数的被引用对象。那么我们如何使用这玩意做些的事情?arguments.callee 是个非常有用的调用自身的匿名函数。
下面有个名为 repeat 的函数,它的参数需要个函数引用和两个数字。第一个数字表示运行的次数,而第二个函数定义运行的间隔时间(毫秒为单位)。下面是相关的代码: 可以500%提高开发效率的前端UI框架!
function repeat(fn, times, delay) { return function() { if (times-- > 0) { fn.apply(null, arguments); var args = Array.prototype.slice.call(arguments); var self = arguments.callee; setTimeout(function(){self.apply(null,args)}, delay); } }; }
repeat 函数使用 arguments.callee 获得当前引用,保存到 self 变量后,返回个匿名函数重新运行原本被调用的函数。最后使用 setTimeout 以及配合个匿名函数实现延迟执行。
作为个简单的说明,比如会在通常的脚本中,编写下面的提供个字符串并弹出个警告框的简单函数:
function comms(s) { alert(s); }
好了,后来我改变了我的想法。我想编写个“特殊版本”的函数,它会重复三次运行每次间隔两秒。那么使用我的 repeat 函数,就可以像这样做到:
var somethingWrong = repeat(comms, 3, 2000); somethingWrong("Can you hear me, major tom?");
结果就犹如预期的那样,弹出了三次警告框每次延时两秒。可以500%提高开发效率的前端UI框架!
最后,arguments 即便不会经常被用到,甚至显得有些诡异,但是它上述的那些惊艳的功能(不仅仅是这些!)值得你去了解它。
相关推荐
函数式编程(Functional Programming)是一种编程范式,它将计算视为数学函数的评估,并且避免改变状态和可变数据。在JavaScript中,函数是一等公民,这意味着函数可以被赋值给变量、作为参数传递给其他函数以及...
5. **函数式数据结构**:如Immutable.js库提供的不可变数据结构,有助于减少副作用和提高代码可预测性。 6. **Monad**:虽然在JavaScript中应用较少,但了解其概念可以帮助理解复杂的函数式编程概念。 7. **...
总的来说,JavaScript提供的参数可变函数功能是非常灵活和强大的,它使得函数调用更加动态,减少了需要定义多个重载函数的需要。然而,在实际的项目中,我们也应当谨慎使用可变参数函数,因为过度依赖这种功能可能会...
从ES6开始,JavaScript允许为函数参数设置默认值,这样当传入的参数为undefined时,会使用默认值。例如: ```javascript function greet(name = 'Guest') { console.log('Hello, ' + name); } greet(); // Hello, ...
JavaScript函数式编程是一种编程范式,它强调将计算视为数据处理,通过函数操作来避免改变状态和可变数据。在JavaScript中,函数式编程能够帮助我们编写更简洁、可读性更强、易于测试和维护的代码。下面我们将深入...
总的来说,`arguments`对象是JavaScript中处理可变长参数的重要工具,它可以提供对所有函数参数的访问,无论实际传入多少参数。然而,由于它的类数组性质和在不同作用域中的独立性,使用时需要注意不要直接修改它,...
5. **函数式数据结构**:使用不可变数据结构(如Underscore的`_.clone`和`_.extend`)可以避免副作用,保证函数式编程的安全性。 6. **惰性计算(Lazy Evaluation)**:只在真正需要时才进行计算,以提高性能。...
一些库如Immutable.js提供了不可变数据结构,遵循函数式编程的原则。 总的来说,JavaScript中的函数式编程提供了编写更简洁、可维护代码的方法。通过掌握这些概念和技巧,开发者可以提高代码质量,减少错误,并更...
基本数据类型是不可变的,而引用数据类型(如对象和函数)是可变的,它们存储的是对象的引用而非实际值。这意味着修改引用类型变量的一个属性会影响到所有引用该对象的变量。 基本数据类型包括: - Number:表示...
但通过使用不可变数据结构(如Immutable.js库提供的数据结构)和函数式编程库(如Ramda或Lodash),开发者可以在JavaScript中实现更接近函数式风格的编程。 总的来说,JavaScript的函数式编程是利用语言固有的函数...
在JavaScript中,函数式编程的核心概念包括纯函数、高阶函数、柯里化、函数组合、闭包和不可变数据。这些概念在实际开发中有着广泛的应用,如提高代码可读性、减少副作用、简化并发处理以及提高测试覆盖率。 1. **...
总结,JavaScript中的函数是灵活多变的,可变函数的参数不固定,匿名函数提供了一种简洁的代码表达方式,而动态函数则允许在运行时创建函数,增强了代码的动态性。理解并熟练运用这些函数类型对于编写高效、灵活的...
`const`则用于声明不可变的常量,一旦赋值就不能更改。这两个关键字的使用有助于避免变量提升(Hoisting)的问题,以及在块级作用域中管理变量。 函数默认参数是另一个重要的ES6特性,它允许你在函数定义时为参数...
总之,jsBezier 是一个强大且易用的JavaScript库,它使得在浏览器环境中处理贝塞尔曲线变得更加便捷。通过学习和掌握这个库,开发者可以提升其在Web图形编程中的技能,创造出更多引人入胜的交互体验。
- **变量声明**:var、let、const,它们的区别在于作用域和可变性。 - **数据类型**:原始类型(Number、String、Boolean、Null、Undefined、Symbol、BigInt)和引用类型(Object)。 - **运算符**:算术运算符、...
在编程领域,可变参数是程序设计中一个非常实用的概念,尤其在动态语言如Python、JavaScript等中,它允许函数接受不同数量的参数。本文将深入探讨可变参数的遍历,以及如何在实际编程中有效地利用这一特性。 首先,...
它的灵活性和混合范式特性使得在JavaScript中实现函数式编程变得简单直观。JavaScript中的函数式编程不仅仅是理论上的抽象概念,它实际上在很多现代的Web开发中得到了应用。开发者可以通过使用一些轻量级的函数式...
`let`和`const`是ES6引入的新特性,其中`let`可变,`const`不可变。 2. **数据类型**:JavaScript有七种数据类型,包括基本类型(Boolean、Null、Undefined、Number、String、Symbol、BigInt)和引用类型(Object)...
`const`用于声明不可变的常量。 2. **数据类型**:JavaScript有七种数据类型,包括基本类型(Undefined、Null、Boolean、Number、BigInt、String和Symbol)和引用类型(Object,其中包含数组和函数)。 3. **字符...