跟我学习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 相关文章推荐
一个简单的js渐显(fadeIn)渐隐(fadeOut)类
Jun 19 Javascript
理解Javascript_07_理解instanceof实现原理
Oct 15 Javascript
javascript实现html页面之间参数传递的四种方法实例分析
Dec 15 Javascript
为jQuery-easyui的tab组件添加右键菜单功能的简单实例
Oct 10 Javascript
JS实现简单拖拽效果
Jun 21 Javascript
关于使用axios的一些心得技巧分享
Jul 02 Javascript
原生js实现省市区三级联动代码分享
Feb 12 Javascript
详解写好JS条件语句的5条守则
Feb 28 Javascript
基于vue实现一个禅道主页拖拽效果
May 27 Javascript
AntV F2和vue-cli构建移动端可视化视图过程详解
Oct 08 Javascript
微信小程序实现页面左右滑动
Nov 16 Javascript
解决Antd Table表头加Icon和气泡提示的坑
Nov 17 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
jq的get传参数在utf-8中乱码问题的解决php版
2008/07/23 PHP
php json相关函数用法示例
2017/03/28 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
PHP实现文件上传与下载
2020/08/28 PHP
PHP http请求超时问题解决方案
2020/11/13 PHP
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
原生JS实现表单checkbook获取已选择的值
2013/07/21 Javascript
一个CSS+jQuery实现的放大缩小动画效果
2014/02/19 Javascript
jQuery制作简单柱状图实例
2015/01/28 Javascript
Boostrap入门准备之border box
2016/05/09 Javascript
浅谈jquery选择器 :first与:first-child的区别
2016/11/20 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
2017/06/19 Javascript
用JS实现选项卡
2020/03/23 Javascript
[49:17]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第三场 1月26日
2021/03/11 DOTA
让Django支持Sql Server作后端数据库的方法
2018/05/29 Python
python中eval与int的区别浅析
2019/08/11 Python
Python Django Cookie 简单用法解析
2019/08/13 Python
Pytorch中index_select() 函数的实现理解
2019/11/19 Python
python pygame实现挡板弹球游戏
2019/11/25 Python
python标准库OS模块详解
2020/03/10 Python
Python如何定义接口和抽象类
2020/07/28 Python
Python3.7安装PyQt5 运行配置Pycharm的详细教程
2020/10/15 Python
Python离线安装各种库及pip的方法
2020/11/28 Python
Pyecharts 中Geo函数常用参数的用法说明
2021/02/01 Python
css3和jquery实现自定义checkbox和radiobox组件
2014/04/22 HTML / CSS
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
Lowe’s加拿大:家居装修、翻新和五金店
2019/12/06 全球购物
这76道Java面试题及答案,祝你能成功通过面试
2016/04/16 面试题
客服部工作职责范本
2014/02/14 职场文书
入股协议书
2014/04/14 职场文书
物业管理专业自荐信
2014/07/01 职场文书
2014年老干部工作总结
2014/11/21 职场文书
单位接收函格式
2015/01/30 职场文书
应聘教师求职信范文
2015/03/20 职场文书
运动会广播稿50字
2015/08/19 职场文书
python实现简单聊天功能
2021/07/07 Python