Javascript中的重载的实现以及方法apply和call
2012-08-14 21:45
676 查看
Javascript中,先定义的函数,可以被后定义的函数覆盖。因此Javascript不支持函数的重载。比如下面的例子:
虽然有函数p(a, b, c),但是由于语言的特性,该函数被后面的p(a,b)所覆盖。因此只能调用 function p(a, b)。事实上,javascript中函数的定义可以如下形式:
这种形式的定义,更直观的看出p被覆盖了。javascript不是纯粹的函数式语言,但是也拥有函数式语言的一些特性,在这里所有的函数都是对象。Javascript语言也不需要编译,因此也无法在编译期间绑定函数。因此javascript调用函数的时候,就直接使用该函数当前的定义。
Javascript语言中,函数的参数可以是不定个数,任何不确定的值都是默认为undifined。比如:
function p(a, b) {
document.writeln(a);
document.writeln(b);
}
调用p(1);会打印出 1 undefined。
因此使用这种方法可以变相的实现重载的功能,如下:
可以看到调用函数p,会根据参数的个数,调用不同的逻辑。这种方式虽然管用,但不够优雅。
使用apply方法,可以有更优雅的写法。
javascript中,函数即对象,因此作为对象,函数也有自己的一些方法,比如toString(), call(), apply()。了解apply方法前,先看一下和它类似的call方法。
call方法的签名如下:
call([thisObj[, arg1[, arg2[, [, argN]]]]])
call方法——代表别的对象调用方法。call方法允许你改变函数对象的上下文,如果参数thisObj 未提供,则默认global对象为thisObj。
具体看一个例子,理解call方法。
call方法可以接参数,表示函数的参数,比如下面的例子
apply方法和call方法相同,除了apply接受的参数是一个数组。
apply([thisObj[,argArray]])
因此上面的方法,改写成apply的话就得如下写:
网上有老外写了一套方法,专门实现类似重载的效果。
http://ejohn.org/blog/javascript-method-overloading/源码如下:
这套代码使用简单,但是比较难以读懂,主要应用到了闭包,old的值可以一直保存在内存中。通过轮询的方式,找出符合参数个数的function。代码较难读懂,而且效率也并不高。
下面,本人根据上述代码,做了一些小改动,使用一个array保存这些重载函数,避免使用闭包。因此可读性较好。但代码稍稍复杂点。
参考文档:
http://ejohn.org/blog/javascript-method-overloading/
http://odetocode.com/Articles/473.aspx
http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspx
本文出自 “一只博客” 博客,请务必保留此出处http://cnn237111.blog.51cto.com/2359144/963703
<script type="text/javascript"> function p(a, b, c) { alert(a+b+c); } function p(a, b) { alert(a+b); } p(1,2,3);//alert 6; </script>
虽然有函数p(a, b, c),但是由于语言的特性,该函数被后面的p(a,b)所覆盖。因此只能调用 function p(a, b)。事实上,javascript中函数的定义可以如下形式:
var p = function (a,b,c) { alert(a + b + c); } var p = function (a, b) { alert(a + b); }
这种形式的定义,更直观的看出p被覆盖了。javascript不是纯粹的函数式语言,但是也拥有函数式语言的一些特性,在这里所有的函数都是对象。Javascript语言也不需要编译,因此也无法在编译期间绑定函数。因此javascript调用函数的时候,就直接使用该函数当前的定义。
Javascript语言中,函数的参数可以是不定个数,任何不确定的值都是默认为undifined。比如:
function p(a, b) {
document.writeln(a);
document.writeln(b);
}
调用p(1);会打印出 1 undefined。
因此使用这种方法可以变相的实现重载的功能,如下:
function p() { if (arguments.length == 2) { document.writeln(arguments[0]); document.writeln(arguments[1]); } if (arguments.length == 3) { document.writeln(arguments[0]); document.writeln(arguments[1]); document.writeln(arguments[2]); } } p("a", "b"); document.writeln("<br/>"); p("a", "b", "c");
可以看到调用函数p,会根据参数的个数,调用不同的逻辑。这种方式虽然管用,但不够优雅。
使用apply方法,可以有更优雅的写法。
javascript中,函数即对象,因此作为对象,函数也有自己的一些方法,比如toString(), call(), apply()。了解apply方法前,先看一下和它类似的call方法。
call方法的签名如下:
call([thisObj[, arg1[, arg2[, [, argN]]]]])
call方法——代表别的对象调用方法。call方法允许你改变函数对象的上下文,如果参数thisObj 未提供,则默认global对象为thisObj。
具体看一个例子,理解call方法。
var x = 1; var o = { x: 2 }; function f() { this.showtime = function () { alert(Date()); } alert(this.x); } f();//先是调用f函数,然后会给global对象定义了一个showtime方法,alert出global的x变量的值。 this.showtime(); //global对象的showtime()已经被定义了,因此可以调用。 f.call(o); //代表o调用call方法,这时候上下文global被改成o对象,因此this.x就是o.x,this.showtime就是o.showtime() o.showtime(); //o.showtime()已经被定义了,因此可以调用。
call方法可以接参数,表示函数的参数,比如下面的例子
var x = 0; var o = { x: 2 }; function f(a,b) { alert(this.x+a+b); } f.call(o,3,4); //alert 9
apply方法和call方法相同,除了apply接受的参数是一个数组。
apply([thisObj[,argArray]])
因此上面的方法,改写成apply的话就得如下写:
var x = 0; var o = { x: 2 }; function f(a,b) { alert(this.x+a+b); } f.apply(o, [3, 4]);
网上有老外写了一套方法,专门实现类似重载的效果。
http://ejohn.org/blog/javascript-method-overloading/源码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <script type="text/javascript"> function addMethod(object, name, fn) { var old = object[name];//闭包 object[name] = function () { if (fn.length == arguments.length) return fn.apply(this, arguments); else if (typeof old == 'function') return old.apply(this, arguments); }; } function Users() { addMethod(this, "find", function () { // Find all users... alert(); }); addMethod(this, "find", function (name) { // Find a user by name alert(name); }); addMethod(this, "find", function (first, last) { // Find a user by first and last name alert(first + " " + last); }); } var users = new Users(); users.find(); // Finds all users.find("John"); // Finds users by name users.find("John", "Resig"); // Finds users by first and last name users.find("John", "E", "Resig"); // Does nothing </script> </head> <body> </body> </html>
这套代码使用简单,但是比较难以读懂,主要应用到了闭包,old的值可以一直保存在内存中。通过轮询的方式,找出符合参数个数的function。代码较难读懂,而且效率也并不高。
下面,本人根据上述代码,做了一些小改动,使用一个array保存这些重载函数,避免使用闭包。因此可读性较好。但代码稍稍复杂点。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <script type="text/javascript"> var chongzailist = new Array(); //存放重载函数的list function addMethod(object, name, fn) { if (object[name] == undefined) { object[name] = function () { // (arguments.length); for (c in chongzailist) { if (chongzailist[c]["Name"] == name) { for (f in chongzailist[c]["Func"]) { if (chongzailist[c]["Func"][f].length == arguments.length) { return chongzailist[c]["Func"][f].apply(null, arguments); } } } } } } var isexist = false; for (c in chongzailist) { if (chongzailist[c]["Name"] == name) { chongzailist[c]["Func"].push(fn); isexist = true; break; } } if (!isexist) { var fnlist = new Array(); fnlist.push(fn); chongzailist.push(chongzai(name, fnlist)); } } function chongzai(fname, fnlist) { return { Name: fname, Func: fnlist }; } function Users() { addMethod(this, "find", function () { alert(); }); addMethod(this, "find", function (name) { alert(name); }); addMethod(this, "find", function (first, last) { alert(first + " " + last); }); addMethod(this, "get", function () { alert(); }); addMethod(this, "get", function (name) { alert(name); }); addMethod(this, "get", function (first, last) { alert(first + " " + last); }); } //Users(); var users = new Users(); users.find(); // Finds all users.find("John"); // Finds users by name users.find("John", "Resig"); // Finds users by first and last name users.find("John", "E", "Resig"); // Does nothing users.get(); // Finds all users.get("John"); // Finds users by name users.get("John", "Resig"); // Finds users by first and last name users.get("John", "E", "Resig"); // Does nothing </script> </head> <body> </body> </html>
参考文档:
http://ejohn.org/blog/javascript-method-overloading/
http://odetocode.com/Articles/473.aspx
http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspx
本文出自 “一只博客” 博客,请务必保留此出处http://cnn237111.blog.51cto.com/2359144/963703
相关文章推荐
- javascript中apply方法和call方法的作用以及prototype.js中的应用
- JavaScript call() 与 apply() 方法的实现与思路解析
- JavaScript中的call()和apply()方法,借此实现继承
- JavaScript的函数call和apply的区别、以及bind方法
- javascript中apply方法和call方法的作用以及prototype.js中的应用
- JavaScript使用Call和Apply方法实现继承
- 基于JavaScript实现继承机制之调用call()与apply()的方法详解
- javascript中apply方法和call方法的作用以及prototype.js中的应用
- javascript中apply方法和call方法的作用以及prototype.js中的应用
- JavaScript实现继承机制(2)——调用call()与apply()方法
- 基于JavaScript实现继承机制之调用call()与apply()的方法详解
- JavaScript之apply,call以及bind方法
- JavaScript中call,apply,bind方法的总结
- 关于javascript中apply()和call()方法的区别
- JavaScript 中的 call()、apply() 和 bind() 方法
- JavaScript方法call,apply,caller,callee,bind的使用详解及区别
- javascript中call与apply的使用方法
- JavaScript 中的 this 用法以及 call(apply) 的理解
- 关于javascript中apply()和call()方法的区别
- 【JavaScript 学习--09】--理解Js 中的apply 和 call方法