小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
上篇文章我们学习了函数的caller, 谁调用了我?
今天我们就来学习callee,我是谁!
定义
callee这个属性并不是属于Function的属性,而是属于 arguments的属性。 它可以用于引用该函数的函数体内当前正在执行的函数。
简单说,就是 我是谁!。
function sum(num1, num2){
console.log("sum===arguments.callee:", sum === arguments.callee);
return num1 + num2;
}
sum()
// sum === arguments.callee: true
严格模式
我们在严格模式下试试, 在代码顶部添加use strict
"use strict"
function sum(num1, num2){
console.log("sum===arguments.callee:", sum === arguments.callee);
return num1 + num2;
}
sum()
结果是收到如下的错误的提示:
更多关于严格模式,可以参见 严格模式 MDN。
起源
// TODO::
命名函数表达式
用途
递归
主要是匿名函数,没办法获得对函数的引用,比如如下例子:
const utils = {
sumTotal: function (n) {
if (n == 1) return 1;
return arguments.callee(n - 1) + n;
}
}
console.log("sumTotal:", utils.sumTotal(100)
// sumTotal: 5050
其实上面的代码也可以写成如下:
用 utils.sum替换arguments.callee
const utils = {
sumTotal: function (n) {
if (n == 1) return 1;
return utils.sumTotal(n - 1) + n;
}
}
console.log("sumTotal:", utils.sumTotal(100))
// sumTotal: 5050
那再换一个例子:
function sumTotal(n) {
if(n == 1) return 1;
return arguments.callee(n - 1) + n;
};
console.log([5, 10, 20].map(sumTotal))
// [ 15, 55, 210 ]
上线的写法没问题,如果使用匿名函数呢?
console.log([5, 10, 20].map(function(){
if(n == 1) return 1;
return /这里写什么呢?/(n - 1) + n;
}))
答案就是arguments.callee:
console.log([5, 10, 20].map(function(n){
if(n == 1) return 1;
return arguments.callee(n - 1) + n;
}))
// [ 15, 55, 210 ]
写这么多,有人说,给函数取个名字不行吗? 答案是行啊,这不是为了演示, 特定场景下非你不可以吗?
我就是要用匿名函数,可能就是非你不可。
动态创建的函数
var sumTotal = new Function("n", `
if(n == 1) return 1;
return /这里写什么?/(n - 1) + n;
`)
这里,arguments.callee闪亮登场!
var sumTotal = new Function("n", `
if(n == 1) return 1;
return arguments.callee(n - 1) + n;
`)
console.log(sumTotal(100));
附送一个吧
所以能不能用,我们检查是不是有严格模式和处于严格模式。
有没有严格模式:
主要是利用严格模式下 this 是等于undefined这个特性
var hasStrictMode = (function(){
"use strict";
return this == undefined;
}());
是否处于严格模式:
var isStrict = (function(){
return this === undefined;
}());
小结
今天一起学了函数的一个有意思的特性, callee, 其属于arguments的属性,不是Function的属性,大多数情况下并没有太多的用途,而且严格模式还不可以使用, 但是匿名函数和动态函数场景下,还是有其特定的作用。
今天你收获了吗?