浅谈arguments属性callee
1.首先 arguments 是一个对应于传递给函数的参数的类数组对象
2. arguments.callee 属性包含当前正在执行的函数。
描述
callee 是 arguments 对象的一个属性。它可以用于引用该函数的函数体内当前正在执行的函数。这在函数的名称是未知时很有用,例如在没有名称的函数表达式 (也称为“匿名函数”)内。
警告:在严格模式下,第5版 ECMAScript (ES5) 禁止使用 arguments.callee()。当一个函数必须调用自身的时候, 避免使用 arguments.callee(), 通过要么给函数表达式一个名字,要么使用一个函数声明.
为什么 arguments.callee 从ES5严格模式中删除了?
(改编自 a Stack Overflow answer by olliej)
早期版本的 JavaScript不允许使用命名函数表达式,出于这样的原因, 你不能创建一个递归函数表达式。
例如,下边这个语法就是行的通的:
function factorial (n) {
return !(n > 1) ? 1 : factorial(n - 1) * n;
}
[1,2,3,4,5].map(factorial);
但是:
[1,2,3,4,5].map(function (n) {
return !(n > 1) ? 1 : /* what goes here? */ (n - 1) * n;
});
这个不行。为了解决这个问题, arguments.callee 添加进来了。然后你可以这么做
[1,2,3,4,5].map(function (n) {
return !(n > 1) ? 1 : arguments.callee(n - 1) * n;
});
然而,这实际上是一个非常糟糕的解决方案,因为这 (以及其它的 arguments, callee, 和 caller 问题) 使得在通常的情况(你可以通过调试一些个别例子去实现它,但即使最好的代码也是次优选项,因为(JavaScript 解释器)做了不必要的检查)不可能实现内联和尾递归。另外一个主要原因是递归调用会获取到一个不同的 this 值,例如:
var global = this;
var sillyFunction = function (recursed) {
if (!recursed) { return arguments.callee(true); }
if (this !== global) {
alert("This is: " + this);
} else {
alert("This is the global");
}
}
sillyFunction();
ECMAScript 3 通过允许命名函数表达式解决这些问题。例如:
[1,2,3,4,5].map(function factorial (n) {
return !(n > 1) ? 1 : factorial(n-1)*n;
});
这有很多好处:
- 该函数可以像代码内部的任何其他函数一样被调用
- 它不会在外部作用域中创建一个变量 (除了 IE 8 及以下)
- 它具有比访问arguments对象更好的性能
------------------------------------------------------上面没看懂的话, 看下这个:
在函数内部,有两个特殊的对象:arguments 和 this。其中, arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 请看下面这个非常经典的阶乘函数

function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变 的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为 了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee

function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}

在这个重写后的 factorial()函数的函数体内,没有再引用函数名 factorial。这样,无论引用 函数时使用的是什么名字,都可以保证正常完成递归调用。例如

function factorial(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1);
}
}
var trueFactorial = factorial;
alert(trueFactorial(5)); //120
factorial = function() {
return 0;
}
alert(trueFactorial(5));// 120 如果没有使用arguments.callee,将返回0

在此,变量 trueFactorial 获得了 factorial 的值,实际上是在另一个位置上保存了一个函数 的指针。然后,我们又将一个简单地返回 0的函数赋值给 factorial 变量。如果像原来的 factorial() 那样不使用 arguments.callee,调用 trueFactorial()就会返回 0。可是,在解除了函数体内的代 码与函数名的耦合状态之后,trueFactorial()仍然能够正常地计算阶乘;至于 factorial(),它现 在只是一个返回 0的函数。
参考自js高程第三版
现在已经不推荐使用arguments.callee();
原因:访问 arguments 是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建。影响现代浏览器的性能,还会影响闭包。
不能用怎么办?
像第三段中的例子,重写 factorial()方法导致trueFactorial()结果不在预期。是为了演示而做的。平时写代码应该避免。
递归时用到arguments.callee()是常见的事情,比如
一道面试题。接受参数n=5,不用for循环输出数组【1,2,3,4,5】
这用递归的思路,配合arguments.callee,代码如下

function show(n) {
var arr = [];
return (function () {
arr.unshift(n);
n--;
if (n != 0) {
arguments.callee();
}
return arr;
})()
}
show(5)//[1,2,3,4,5]

现在arguments.callee 被弃用了。怎么办,其实很简单,给内部函数一个名字即可

function show(n) {
var arr = [];
return (function fn() {
arr.unshift(n);
n--;
if (n != 0) {
fn();
}
return arr;
})()
}
show(5)//[1,2,3,4,5]

参考地址:https://www.cnblogs.com/lijinwen/p/5727550.html
mdn : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments/callee
浅谈arguments属性callee的更多相关文章
- Abp vNext 番外篇-疑难杂症丨浅谈扩展属性与多用户设计
说明 Abp vNext基础篇的文章还差一个单元测试模块就基本上完成了我争取10.1放假之前给大家赶稿出来,后面我们会开始进阶篇,开始拆一些东西,具体要做的事我会单独开一个文章来讲 缘起 本篇文章缘起 ...
- 浅谈arguments与arguments的妙用
1.每个函数都有一个arguments属性,表示函数的实参集合,这里的实参是重点,就是执行函数时实际传入的参数的集合. 2.arguments不是数组而是一个对象,但它和数组很相似,所以通常称为类数组 ...
- 浅谈title属性与alt属性
XHTML是CSS布局的基础,webjx.com一直强调XHTML知识的学习,重视语义和文档的结构.title 和alt 属性,给我最直观的感受就是,可以提高文档的适应性,并合理提高关键词密度.在XH ...
- 浅谈WPF依赖项属性
浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...
- $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
$.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...
- 浅谈CSS3中display属性的Flex布局
浅谈CSS3中display属性的Flex布局 最近在学习微信小程序,在设计首页布局的时候,新认识了一种布局方式display:flex 1 .container { 2 display: fle ...
- CSS属性中的display属性浅谈;
首先我们要知道什么是块级元素和行内元素有什么区别: 承接上篇文章:(浅谈HTML和body标签) 块级元素:浏览器解析为独占一行的元素(例如:div.table.ul等.),浏览器会在该元素的前后显示 ...
- 浅谈Vue中计算属性(computed)和方法(methods)的差别
浅谈Vue中计算属性(computed)和方法(methods)的差别 源码地址 methods方法和computed计算属性,两种方式的最终结果确实是完全相同 计算属性是基于它们的响应式依赖进行缓存 ...
- 浅谈JS严格模式
浅谈JS严格模式 简介 何为严格模式?严格模式(strict mode)即在严格的条件下运行,在严格模式下,很多正常情况下不会报错的问题语句,将会报错并阻止运行. 但是,严格模式可以显著提高代码的健壮 ...
随机推荐
- linux文本编辑工具
文本编辑工具VIM vim 主要有三种工作模式,分别是命令模式.插入模式和编辑模式,输入 vim 文件名 我们可以进入命令模式,输入字符 i或者a或者o我们可以进入插入模式,进入插入模式之后我们可以进 ...
- 【SQL登录问题】
essay from:http://www.jb51.net/article/59352.htm 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器 今早 ...
- php模式的设计
工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式. 工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,虽然工厂方法可以任意命名这个静态 ...
- 在基于ABP框架的前端项目Vue&Element项目中采用电子签名的处理
在前面随笔介绍了<在基于ABP框架的前端项目Vue&Element项目中采用电子签章处理文件和打印处理>的处理,有的时候,我们在流程中或者一些文件签署的时候,需要签上自己的大名,一 ...
- [SPDK/NVMe存储技术分析]004 - SSD设备的发现
源代码及NVMe协议版本 SPDK : spdk-17.07.1 DPDK : dpdk-17.08 NVMe Spec: 1.2.1 基本分析方法 01 - 到官网http://www.spdk.i ...
- 74CMS 3.0 CSRF漏洞
一. 启动环境 1.双击运行桌面phpstudy.exe软件 2.点击启动按钮,启动服务器环境 二.代码审计 1.双击启动桌面Seay源代码审计系统软件 2.因为74CMS3.0源代码编辑使用GBK编 ...
- 网络监听HTTP协议信息实验
一.开启环境 登录web服务器,在服务器中开启phpstudy服务器环境. 在操作机中打开目标站[Web服务器IP地址]地址.安装wordpress,数据库名:wordpress,用户名root 密码 ...
- Java study 4
JAVA 学习第四天 今日学习内容 快捷键.复习.注释.字面量 快捷键 学习地址:IJ快捷键 复习 jdk下载.安装.部署环境.第一个Java程序入门学习,环境变量path 注释 注释:顾名思义就是用 ...
- 知识点简单总结——FWT(快速沃尔什变换),FST(快速子集变换)
知识点简单总结--FWT(快速沃尔什变换),FST(快速子集变换) 闲话 博客园的markdown也太傻逼了吧. 快速沃尔什变换 位运算卷积 形如 $ f[ i ] = \sum\limits_{ j ...
- CF736D Permutations(伴随矩阵)
CF736D Permutations(伴随矩阵) Luogu 题解时间 首先把边直接放进邻接矩阵, 很明显行列式的奇偶和方案数的奇偶一样. 设 $ A_{ i , j } $ 为矩阵的该行列的余子式 ...