跟我学习javascript的arguments对象


Posted in Javascript onNovember 16, 2015

1、什么是arguments

arguments 是是JavaScript里的一个内置对象,它很古怪,也经常被人所忽视,但实际上是很重要的。所有主要的js函数库都利用了arguments对象。所以agruments对象对于javascript程序员来说是必需熟悉的。在javascript函数体内,标识符arguments具有特殊含义。它是调用对象的一个特殊属性,用来引用Arguments对象。Arugments对象就像数组,注意这里只是像并不是哈。

javascript函数体内,arguments像数组(并不是真的数组,是一个Arguments对象,再次强调)一样,有length属性,可以代表传给函数的参数的个数。

javascript中Arguments对象是函数的实际参数,arguments对象的长度是由实参个数而不是形参个数决定的。形参是函数内部重新开辟内存空间存储的变量,但是其与arguments对象内存空间并不重叠。

js不会主动为你判断你到底给函数传了多少个参数,如果你多传了,多余的部分就没有被使用,如果你少传了,那么没传的参数值就是undefined.所以我们可以借助arguments的length属性来检测调用函数时是否使用了正确数目的实际参数,因为javascript是不会为你做这些事的

function f(x,y,z)
{
 //首先检查传递的参数数量是否正确
 if(arguments.length != 3)
 {
  throw new Error("function f called with " + arguments.length + "arguments");
 }
 //下面运行真正的函数
}

2、arguments创建可变参数列表函数

arguments还为我们提供了这样一种可能,就是为一个函数传任意数目的实际参数:

比如说,我想用一个display()函数来计算每个公司的员工工资总额,对,没错,你传多少参数都行,但是前提是你要传数字,因为我在函数内部懒得判断了。

function display(){
  var sum=0; //总额
  for(var i=0;i<arguments.length;i++){
   sum+=arguments[i];
  }
  document.write(sum+'<br>');
 }

 //A公司
 display(10000,2000,5000);
 //B公司
 display(1000,2000,5000,8000,10000);

怎么样?这个方法很巧妙吧?

说明一下arguments与真正传的形式参数是一致的:

对于arguments和值都存在的情况下,两者值是同步的改变其中一个值,即改变了二者所有的值

function f(a, b, c){
 alert(arguments.length); // result: "2"
 a = 100;
 alert(arguments[0]);  // result: "100"
 arguments[0] = "qqyumidi";
 alert(a);     // result: "qqyumidi"
 alert(c);     // result: "undefined"
 c = 2012;
 alert(arguments[2]);  // result: "undefined"
}

f(1, 2);

3、永远不要修改arguments对象

函数中声明的参数和arguments之间的联系很脆弱,每个声明的参数实际上只是对arguments对象中对应位置的一个引用。

值得注意的是,在ES5的strict mode中,函数声明的参数并不会引用arguments:

function strict(x) {
 "use strict";
 arguments[0] = "modified";
 return x === arguments[0];
}
function nonstrict(x) {
 arguments[0] = "modified";
 return x === arguments[0];
}
strict("unmodified"); // false
nonstrict("unmodified"); // true

正因为在strict和非strict模式下,函数声明的参数和arguments的关系不一致,所以为了避免出现问题,不去修改arguments对象才是最安全的做法。

如果确实需要修改arguments对象,那么可以首先赋值一份arguments对象:

var args = [].slice.call(arguments);
当slice方法不接受任何参数的时候,就会执行复制操作,得到的args也是一个真正的数组对象。同时,args和函数声明的参数之间也没有任何联系了,对它进行操作是安全的。

4、一个变量来保存arguments的引用

假设需要一个API用来遍历若干元素,像下面这样:

var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6); 
it.next(); // 1 
it.next(); // 4 
it.next(); // 1

相应的实现可以是:

function values() { 
 var i = 0, n = arguments.length; 
 return { 
  hasNext: function() { 
   return i < n; 
  }, 
  next: function() { 
   if (i >= n) { 
    throw new Error("end of iteration"); 
   } 
   return arguments[i++]; // wrong arguments 
  } 
 }; 
}

但是执行的实际情况却是:

var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6); 
it.next(); // undefined 
it.next(); // undefined 
it.next(); // undefined

原因在于:对于arguments对象的赋值是隐式完成的。在next方法内部,使用了arguments,然而此arguments和values方法开始处的arguments并不是一个对象。这里的arguments对象是函数next()的。

解决方法也很简单,就是将需要访问的arguments使用另外一个变量进行引用。然后通过闭包的性质在其嵌套的函数中进行访问就可以了,像下面这样:

function values() { 
 var i = 0, n = arguments.length, a = arguments; 
 return { 
  hasNext: function() { 
   return i < n; 
  }, 
  next: function() { 
   if (i >= n) { 
    throw new Error("end of iteration"); 
   } 
   return a[i++]; 
  } 
 }; 
} 
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6); 
it.next(); // 1 
it.next(); // 4 
it.next(); // 1

5、arguments对象的callee属性:

arguments的callee属性是用来引用当前正在执行的函数,这对未命名的函数调用自身非常有好处。

首先用命名函数表达式实现递归的函数:

//函数直接量 指定函数名 递归函数
var result = function fact(x){
 if(x<=1) 
  return 1; 
 else 
  return x*fact(x-1);
};

那里面,我提到可以为函数直接量以函数名。这样实现递归可以很方便的调用自己。

现在用arguments的这个callee同样可以简单的实现

//用函数直接量,采用arguments.callee属性实现递归函数
var result = function(x){
 if(x<=1) return 1; 
 return x*arguments.callee(x-1);
};

在最后提醒大家一点,既然这个arguments这么厉害,那么我们就不要为变量命名为arguments了,事实上arguments是javascript的保留字之一。嗯。

最后补充一点:

区别caller

返回一个对函数的引用,该函数调用了当前函数。

  • - functionName.caller
  • - functionName 对象是所执行函数的名称。

对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。

代码:

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->// caller demo {
function callerDemo() {
 if (callerDemo.caller) {
  var a= callerDemo.caller.toString();
  alert(a);
 } else {
  alert("this is a top function");
 }
}
function handleCaller() {
 callerDemo();
}

handleCaller();//弹出handleCaller的定义

以上就是针对javascript的arguments对象的相关介绍,希望对大家的学习有所帮助。

Javascript 相关文章推荐
jQuery 1.5最新版本的改进细节分析
Jan 19 Javascript
JavaScript中的getDay()方法使用详解
Jun 09 Javascript
js中的eval()函数把含有转义字符的字符串转换成Object对象的方法
Dec 02 Javascript
网页中右键功能的实现方法之contextMenu的使用
Feb 20 Javascript
Vue.js仿Metronic高级表格(二)数据渲染
Apr 19 Javascript
如何抽象一个Vue公共组件
Oct 17 Javascript
vue监听input标签的value值方法
Aug 27 Javascript
vue 实现滚动到底部翻页效果(pc端)
Jul 31 Javascript
layui异步加载table表中某一列数据的例子
Sep 16 Javascript
Vue proxyTable配置多个接口地址,解决跨域的问题
Sep 11 Javascript
详解如何使用React Hooks请求数据并渲染
Oct 18 Javascript
JS代码实现页面切换效果
Jan 10 Javascript
JavaScript函数学习总结以及相关的编程习惯指南
Nov 16 #Javascript
js实现获取div坐标的方法
Nov 16 #Javascript
跟我学习javascript的闭包
Nov 16 #Javascript
jQuery链式操作实例分析
Nov 16 #Javascript
javascript伸缩型菜单实现代码
Nov 16 #Javascript
基于jQuery实现的仿百度首页滑动选项卡效果代码
Nov 16 #Javascript
每天一篇javascript学习小结(Function对象)
Nov 16 #Javascript
You might like
php探针不显示内存解决方法
2019/09/17 PHP
javascript xml为数据源的下拉框控件
2009/07/07 Javascript
js字符串的各种格式的转换 ToString,Format
2011/08/08 Javascript
js实现点击后将文字或图片复制到剪贴板的方法
2014/08/04 Javascript
JavaScript中合并数组的N种方法
2014/09/16 Javascript
JQuery控制DIV的选取实现方法
2016/09/18 Javascript
浅谈javascript:两种注释,声明变量,定义函数
2016/10/05 Javascript
jQuery.form.js插件不能解决连接超时(timeout)的原因分析及解决方法
2016/10/14 Javascript
详解js中==与===的区别
2017/01/08 Javascript
Ionic + Angular.js实现图片轮播的方法示例
2017/05/21 Javascript
Vue2几种常见开局方式详解
2017/09/09 Javascript
iconfont的三种使用方式详解
2018/08/05 Javascript
使用angular-cli webpack创建多个包的方法
2018/10/16 Javascript
vue App.vue中的公共组件改变值触发其他组件或.vue页面监听
2019/05/31 Javascript
纯js实现无缝滚动功能代码实例
2020/02/21 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
[51:26]VP vs VG 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python根据经纬度计算距离示例
2014/02/16 Python
python实现自动发送邮件发送多人、群发、多附件的示例
2018/01/23 Python
Python实现简单的文本相似度分析操作详解
2018/06/16 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
python如何查看微信消息撤回
2018/11/27 Python
python+mysql实现学生信息查询系统
2019/02/21 Python
Python实现从SQL型数据库读写dataframe型数据的方法【基于pandas】
2019/03/18 Python
python中yield的用法详解——最简单,最清晰的解释
2019/04/04 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
2020/03/02 Python
亚马逊印度站:Amazon.in
2017/10/15 全球购物
英国最受欢迎的平价女士时装零售商:Roman Originals
2019/11/02 全球购物
建筑施工实习自我鉴定
2013/09/19 职场文书
总经理岗位职责范本
2015/04/01 职场文书
营运督导岗位职责
2015/04/10 职场文书
观后感格式
2015/06/19 职场文书
慰问信(范文3篇)
2019/10/23 职场文书
MySQL之select、distinct、limit的使用
2021/11/11 MySQL
实例详解Python的进程,线程和协程
2022/03/13 Python
漫改真人电影「萌系男友是燃燃的橘色」公开先导视觉图
2022/03/21 日漫