caller & callee 相关 (相关联 call()、apply()、bind() 可以改变caller)
来源:互联网 发布:打印机网络共享设置 编辑:程序博客网 时间:2024/04/30 03:05
相关阅读:《 在JavaScript中借用方法 》
caller : functionName.caller 返回调用者。
(返回一个对函数的引用,该函数调用了当前函数)
function caller() { if (caller.caller) { alert(caller.caller.toString()); } else { alert("函数直接执行"); } } function handleCaller() { caller(); } handleCaller(); caller();
大家会发现第一个alert会弹出调用caller函数的调用者handleCaller,而第二个alert由于没有在其他函数体内调用,所以caller为null,就执行了 alert(“函数直接执行”);
function callerDemo() { if (callerDemo.caller) { var a= callerDemo.caller.toString(); alert(a); } else { alert("this is a top function"); } } function handleCaller() { callerDemo(); } <input type="button" onclick="callerDemo()" value="callerDemo">// 弹出// function onclick() {// callerDemo();// }<input type="button" onclick="handleCaller()" value="handleCaller">// 弹出// function handleCaller() {// callerDemo();// }
上面的例子,可以看出,它就是返回一个调用数据的引用。(指向请求调用的函数) 也由此可以看出,当在这样的情况下,onclick触发事件的时候总是带着匿名函数的。
caller的应用场景 主要用于察看函数本身被哪个函数调用。
callee: 返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文. callee是arguments 的一个属性成员,它表示对函数对象本身的引用,这有利于匿名
(返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。需要注意的是callee拥有length属性,这个在有的时候用于验证还是比较好的)
函数的递归或者保证函数的封装性。 下面一段代码先说明callee的用法
function calleeLengthDemo(arg1, arg2) { alert(arguments.callee.toString()); if (arguments.length == arguments.callee.length) { window.alert("验证形参和实参长度正确!"); return; } else { alert("实参长度:" + arguments.length); alert("形参长度: " + arguments.callee.length); } } calleeLengthDemo(1);
第一个消息框弹出calleeLengthDemo函数本身,这说明callee就是函数本身对象的引用。callee还有个非常有用的应用就是用来判断实际参数跟行参是否一致。上面的代码第一个消息框会弹出实际参数的长度为1,形式参数也就是函数本身的参数长度为2.
应用场景: callee的应用场景一般用于匿名函数 大家看下下面一段代码
var fn=function(n){ if(n>0) return n+fn(n-1); return 0; } alert(fn(10))
函数内部包含了对自身的引用,函数名仅仅是一个变量名,在函数内部调用即相当于调用
一个全局变量,不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法
var fn=(function(n){ if(n>0) return n+arguments.callee(n-1); return 0; })(10); alert(fn)
这样就让代码更加简练。又防止了全局变量的污染。
apply实现call
Function.prototype.call = function () { var ctx = [].shift.apply(arguments) return this.apply(ctx, arguments)}
apply实现bind
Function.prototype.bind = function () { var ctx = [].shift.apply(arguments), args = [].slice.apply(arguments), self = this return function () { return self.apply(ctx, args.concat([].slice.apply(arguments))) }}
实现函数柯里化
Function.prototype.currying = function () { var args = [], self = this return function () { if (arguments.length === 0) { return self.apply(this, args) } else { [].push.apply(args, arguments) return arguments.callee } }}//用法var add = function () { var sum = 0 for (var i = 0; i < arguments.length; i++) { sum += arguments[i] } return sum}.currying()add(2) //并未求值add(3, 3) //并未求值add(4) //并未求值console.log(add()) //12
严格模式不能使用arguments.callee, 稍微改一下
Function.prototype.currying = function () { var args = [], self = this var f = function () { if (arguments.length === 0) { return self.apply(this, args) } else { [].push.apply(args, arguments) return f } } return f}
实现函数反柯里化
Function.prototype.uncurrying = function () { var self = this return function () { var obj = [].shift.apply(arguments) return self.apply(obj, arguments) }}// 用法var push = Array.prototype.push.uncurrying()var obj = {}push(obj, '嘿')console.log(obj) //{0: "嘿", length: 1}
另一种方法:call和apply连用实现函数反柯里化
Function.prototype.uncurrying = function () { var self = this return function () { return Function.prototype.call.apply(self, arguments) //有点绕,其实就是return self.call(args[0], args[1], args[2]...) }}
为数组添加max函数
Array.prototype.max = function () { return Math.max.apply(null, this)}console.log([1, 3, 5, 2].max()) //5
再看一个apply的应用
function adApplyDemo(x) { return ("this is never-online, BlueDestiny '" + x + "' demo"); } function handleAdApplyDemo(obj, fname, before) { var oldFunc = obj[fname]; obj[fname] = function() { return oldFunc.apply(this, before(arguments)); }; } function hellowordFunc(args) { args[0] = "hello " + args[0]; return args; } function applyBefore() { alert(adApplyDemo("world")); } function applyAfter() { handleAdApplyDemo(this, "adApplyDemo", hellowordFunc); alert(adApplyDemo("world")); // Hello world! } <input type="button" onclick="applyBefore()" value="原始的adApplyDemo('world')">// 弹出// this is never-online, BlueDestiny 'world' demo<input type="button" onclick="applyAfter()" value="应用后的adApplyDemo('world')">// 弹出// this is never-online, BlueDestiny 'hello world' demo
需要注意的是,要先点”原始的adApplyDemo(‘world’)”按钮,如果先点”应用后的adApplyDemo(‘world’)”按扭,会先应用了apply方法,这样原始的值将会被改变。或许有的朋友没有发现有什么特别的,我在这里指明一下,当点击左边的按扭时,只有”this is never-online, BlueDestiny ‘world’ demo”, 当点击右边的按扭后,会现结果是”this is never-online, BlueDestiny ‘hello world’ demo”,再点点左边的按扭,看看结果又会是什么呢?自己试试看:D,已经改写了函数adApplyDemo。这个例子则说明了apply的”真正”作用了。
- caller & callee 相关 (相关联 call()、apply()、bind() 可以改变caller)
- js中的apply/call/caller/callee/bind
- callee caller call apply
- call(), apply(), caller(), callee()
- arguments,caller,callee,apply,call
- caller,arguments.callee,call,apply
- js apply/call/caller/callee/bind使用方法与区别分析
- js apply/call/caller/callee/bind使用方法与区别分析
- JavaScript apply、call、caller、callee、bind使用方法与区别分析
- JS 中的call,apply,bind 和 caller, callee
- js apply/call/caller/callee/bind使用方法与区别分析
- js apply/call/caller/callee/bind使用方法与区别分析
- [前端] call、apply、bind 和 aguments、caller、callee解析
- js apply/call/caller/callee/bind使用方法与区别分析
- Javascript - 全面理解 caller,callee,call,apply
- javascript的caller,callee,call,apply
- Javascript - 全面理解 caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 顺顺留学
- iOS APP上架流程详解
- 关于数据库
- com.intellij.openapi.project.IndexNotReadyException: Please change caller according to com.intellij.
- 2017校园招聘编程题——两个字符串中找到最大公共字符串
- caller & callee 相关 (相关联 call()、apply()、bind() 可以改变caller)
- React-Native散记
- Medium 15题 3Sum
- spring获取webapplicationcontext,applicationcontext几种方法详解
- Android6.0 动态权限设置
- python3 目录不存在创建
- 欢迎使用CSDN-markdown编辑器
- 获取Spring的上下文环境ApplicationContext的方式
- LeetCode295:Find Median from Data Stream