《无所不能的JavaScript编程系列:arguments 参数对象》
前言:无所不能的JavaScript
JavaScript起源于Netscape公司的LiveScript语言,这是一种基于对象和事件驱动的客户端脚本语言,最初的设计是为了检验HTML表单输入的正确性,只是用于网页开发的一个弱类型脚本语言。随着Html5在PC和移动端越来越流行,JavaScript变得更加重要了,各种层出不穷的框架使得JavaScript的开发更加简捷,V8的性能带来了Node.js,将JavaScript 推向了服务器端,同时还被用在桌面应用、游戏、AR等各种场景,JavaScript已经变成了全能型选手。时至今日,JavaScript可算是世界上最流行的编程语言之一,这个被大量的开发者与设计师随手拈来增强他们的Web前端的脚本语言,越来越被重视。,
JavaScript成功在于它的无所不为。从一个小脚本到前、后端通吃,这足以证明了它的强大之处。
JavaScript一度被认为是一种玩具编程语言,它有很多缺陷,所以不被大多数后端开发人员所重视。很多人认为,相较Java、Ruby、Python、.Net等语言来说,写JavaScript代码很简单,并且JavaScript只是为了在网页上添加一点交互和动画效果,认为只需要会使用jQuery 做一些页面以及前后端交互就可以在简历写上熟悉JavaScript。
但这是完全错误的理解。JavaScript确实很容易上手,学习性价比高,稍微掌握一点JS基础知识,外加HTML和CSS,就可以做一个简单网页或者拿来应聘一份可以糊口的工作。但其精髓却不为大多数开发人员所熟知,如果想精通JS,使用JS进行随心所欲地编程,编写高质量的JavaScript代码更是难上加难。一个合格的开发人员应该精通JavaScript和其他编程语言。如果你已经掌握了其他编程语言,或者你还什么都不会,请立刻开始学习JavaScript,不要被Web时代所淘汰。
函数的实参和形参
在Java 编程中,函数的形参(parameter)和实参(argument)概念屡见不鲜,但是对JavaScript而言,这两个概念通常被弱化了。但其实在JS编程中,还是需要明确理解一下这两个概念。
弱类型脚本语言JS,它的函数定义并未指定函数形参的类型,函数调用也未对传入的实参值做任何类型检查,对传入参数个数也不检查。
一句话来说,JavaScript 的实参和形参可以不一致。
JavaScript 的arguments 参数对象
严格来说,我们应该称arguments 为“实参对象”,因为arguments 对象的长度是由实参个数而不是形参个数决定的。形参是函数内部重新开辟内存空间存储的变量,但是其与arguments对象内存空间并不重叠。对于arguments和值都存在的情况下,两者值是同步的,但是针对其中一个无值的情况下,对于此无值的情形值不会得以同步。
如下代码可以得以验证:
function test(arg1, arg2, arg3){
console.log(arguments.length); // result: "2"
arg1 = 100;
console.log(arguments[0]); // result: "100"
arguments[0] = "200";
console.log(arg1); // result: "200" console.log(arg3); // result: "undefined"
arg3 = true;
console.log(arguments[2]); // result: "undefined"
console.log(arg3) // result: true
}
test(1, 2);
根据代码我们可以得到JS实参对象的一些规则:
规则1:当传入的实参比形参个数少的时候,剩下的形参都将设置为undefined;
规则2:利用arguments.length可以获取调用函数的参数个数,它的值取决于调用处(实参),不一定等于形参个数;
规则3:需要使用可选实参的时候,需要将可选实参放在实参列表的最后,但应对这些可选形参加以控制,代码如下:
function getName(param1, /* optional */ param2) {
if(param2 === undefined) param2 = ""; // 严格相等,防止null;不需要判断空的话,param2 = param2 || ""
dosomething(); }
arguments.callee 与函数形参
说了半天的实参,那么形参在哪里?先看arguments 对象的callee 属性,callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名,该属性仅当相关函数正在执行时才可用。
arguments.callee 得到函数本身,arguments.callee() 是调用自己,arguments.callee.length 是获取形参个数(PS:当然,函数名.length 亦可)。
好,有了这些知识,我们能做什么?
形参的作用无非就是在JS组件编程中,配合实参做一些校验处理和程序分支处理。arguments.callee 的作用就大了,利用它可以在函数内部进行递归逻辑。
代码如下:
function test(n){
if(n>0){
arguments.callee(n - 1);
alert(n);
}
}
var n = 5;
test(n);
如果知道结果是多少,那就OK了。
注:callee在严格模式下被禁用。
arguments 与类数组对象
arguments 对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments 非常类似Array,但实际上又不是一个Array实例。
我们称呼这类对象为类数组对象。《JS权威指南》中提到过这一概念。
JS数组的一些特性是其他对象所没有的:
1.当有新的元素加进来的时候,自动更新length属性;
2.设置length为一个较小值将截断数组;
3.从Array.prototype中继承一些有用的方法;
4.其类属性为”Array“;
这些属性让数组和常规对象有所区别,称为”特殊的对象“。当然,这不是我们这边要关心的,上面这些属性并不是数组的本质特性。
一种完全合理的看法是:"把拥有一个数值length属性和对应非负整数属性的对象看做一种类型的数组,即类数组对象"。
这些类数组对象(参数对象arguments),并不能调用数组的方法或者期望length属性有什么特殊的行为,但是仍然可以类似数组那样遍历它们,并且可以使用call来操作数组的方法。
上一段代码,验证一下:
function ArgTest(a, b)
var numargs = arguments.length;
alert(numargs); //获取实际传递参数长度 var expargs = ArgTest.length;
alert(expargs); // 获取应该传递参数长度,使用 arguments.callee.length 可以获得同样的效果 alert(arguments.callee); //可以打印函数本身 Array.prototype.selfvalue = 1;
alert(new Array().selfvalue);
}
function testAguments(){
alert(arguments.selfvalue);
}
运行代码你会发现第一个alert显示1,这表示数组对象拥有selfvalue属性,值为1,而当你调用函数testAguments时,你会发现显示的是“undefined”,说明了不是arguments的属性,即arguments并不是一个数组对象。
因此,直接调用arguments.slice() 将返回一个"Object doesn't support this property or method"错误,因为arguments不是一个真正的数组。
使用Array.prototype.slice.apply(arguments)能将函数的参数对象转化为一个真正的数组。
JavaScript 的函数重载
对于arguments 参数说了这么多,最后再扯一下函数重载吧。本人是Java 程序猿出身,对于面向对象的三大特性(封装、继承、多态)是根深蒂固,JavaScript的封装和继承在后续文章中会介绍到,那么多态和重载,JavaScript是如何处理的呢?
很遗憾,由于JavaScript中函数的声明和调用特性,可以看出JavaScript中函数是不能重载的。
根据其他语言中重载的依据:"函数返回值不同或形参个数不同",我们可以得出上述结论:
第一:Javascript函数的声明是没有返回值类型这一说法的;
第二:JavaScript中形参的个数严格意义上来讲只是为了方便在函数中的变量操作,实际上实参已经存储在arguments对象中了。
另外,从JavaScript函数本身深入理解为什么JavaScript中函数是不能重载的:在JavaScript中,函数其实也是对象,函数名是关于函数的引用,或者说函数名本身就是变量。对于如下所示的函数声明与函数表达式,其实含以上是一样的(在不考虑函数声明与函数表达式区别的前提下),非常有利于我们理解JavaScript中函数是不能重载的这一特性。
编后语
那么问题来了,为什么我们要学JavaScript?尤其是当你已经掌握了某些其他编程语言如Java、C++的情况下。
简单粗暴的回答就是:因为你没有选择。在Web世界里,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
本人工作从事后端开发,属于一个“半吊子”的前端攻城狮,不会切图,不会设计,CSS和HTML会一些,但这些丝毫不能影响我对JavaScript 热爱。
JavaScript 和nodejs 的大前端时代即将来临,不管你学不学,它就在那里!
《无所不能的JavaScript编程系列:arguments 参数对象》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- OPENCV形态学算法-2
一.漫水填充算法 该算法通过一个指定的种子点,来分析整张图片上的像素,并设置像素差异阈值,在阈值类的点,最后变成相同的颜色.该方法通过上下限和连通方式来达到不同的连通效果. 该方法常用与标记和分离图像 ...
- mysql的python api
我采用的是MySQLdb操作的MYSQL数据库.先来一个简单的例子吧: 1 2 3 4 5 6 7 8 9 10 import MySQLdb try: conn=MySQLdb.conn ...
- 苹果App Store开发者帐户从申请,验证,到发布应用(1)
app store为开发者提供四种类型的申请: 个人ios开发者计划$99/年 公司ios开发者计划$99/年 企业ios开发者计划$299/年 高校ios开发者计划免费 在这里主要介绍一下公司ios ...
- java线程 — 创建和启动线程
创建和启动线程,传统有两种方式: 方式1:继承Thread类: 方式2:实现Runnable接口: 线程类(java.lang.Thread):Thread类和Thread的子类才能称之为线程类.阅读 ...
- iOS开发网络数据之AFNetworking使用 分类: ios技术 2015-04-03 16:35 105人阅读 评论(0) 收藏
http网络库是集XML解析,Json解析,网络图片下载,plist解析,数据流请求操作,上传,下载,缓存等网络众多功能于一身的强大的类库.最新版本支持session,xctool单元测试.网络获取数 ...
- BZOJ1119[POI2009]SLO && BZOJ1697[Usaco2007 Feb]Cow Sorting牛排序
Problem J: [POI2009]SLO Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 622 Solved: 302[Submit][Sta ...
- Oracle数据库用户权限和管理员权限
一.如何查看权限 查看用户权限 1. oracle用户查看自己的权限和角色 select * from user_tab_privs; select * from user_role_ ...
- jq动态添加的元素触发绑定事件无效
<div class='a'> <div class='b'> </div> 其中$('.a')是html页面的元素,$('.b')是jq动态添加的元素.$(&qu ...
- 用JS添加文本框案例代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- php分页原理教程及简单实例
<?php //连接数据库 $con = mysql_connect("localhost","root",""); mysql_se ...