zoukankan      html  css  js  c++  java
  • 《无所不能的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和值都存在的情况下,两者值是同步的,但是针对其中一个无值的情况下,对于此无值的情形值不会得以同步。

      如下代码可以得以验证:

     1 function test(arg1, arg2, arg3){
     2     console.log(arguments.length);   // result: "2"
     3     arg1 = 100;
     4     console.log(arguments[0]);       // result: "100"
     5     arguments[0] = "200";
     6     console.log(arg1);               // result: "200"
     7 
     8     console.log(arg3);               // result: "undefined"
     9     arg3 = true;
    10     console.log(arguments[2]);       // result: "undefined"
    11     console.log(arg3)                // result: true
    12 }
    13 test(1, 2);

      根据代码我们可以得到JS实参对象的一些规则:

      规则1:当传入的实参比形参个数少的时候,剩下的形参都将设置为undefined;

      规则2:利用arguments.length可以获取调用函数的参数个数,它的值取决于调用处(实参),不一定等于形参个数;

      规则3:需要使用可选实参的时候,需要将可选实参放在实参列表的最后,但应对这些可选形参加以控制,代码如下:

     
    1 function getName(param1, /* optional */ param2) {
    2     if(param2 === undefined) param2 = "";  // 严格相等,防止null;不需要判断空的话,param2 = param2 || ""
    3     dosomething();4 }

    arguments.callee 与函数形参

      说了半天的实参,那么形参在哪里?先看arguments 对象的callee 属性,callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名,该属性仅当相关函数正在执行时才可用。

      arguments.callee 得到函数本身,arguments.callee() 是调用自己,arguments.callee.length 是获取形参个数(PS:当然,函数名.length 亦可)。

      好,有了这些知识,我们能做什么?

      形参的作用无非就是在JS组件编程中,配合实参做一些校验处理和程序分支处理。arguments.callee 的作用就大了,利用它可以在函数内部进行递归逻辑。

      代码如下:

    1 function test(n){
    2     if(n>0){
    3         arguments.callee(n - 1);
    4         alert(n);
    5     }
    6 }
    7 var n = 5;
    8 test(n);

      如果知道结果是多少,那就OK了。

      注:callee在严格模式下被禁用。

    arguments 与类数组对象

      arguments 对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments 非常类似Array,但实际上又不是一个Array实例。

      我们称呼这类对象为类数组对象。《JS权威指南》中提到过这一概念。

      JS数组的一些特性是其他对象所没有的:

      1.当有新的元素加进来的时候,自动更新length属性;
      2.设置length为一个较小值将截断数组;
      3.从Array.prototype中继承一些有用的方法;
      4.其类属性为”Array“;
      这些属性让数组和常规对象有所区别,称为”特殊的对象“。当然,这不是我们这边要关心的,上面这些属性并不是数组的本质特性。

      一种完全合理的看法是:"把拥有一个数值length属性和对应非负整数属性的对象看做一种类型的数组,即类数组对象"。
      这些类数组对象(参数对象arguments),并不能调用数组的方法或者期望length属性有什么特殊的行为,但是仍然可以类似数组那样遍历它们,并且可以使用call来操作数组的方法。

      上一段代码,验证一下:

     1 function ArgTest(a, b)
     2   var numargs = arguments.length; 
     3   alert(numargs); //获取实际传递参数长度
     4 
     5   var expargs = ArgTest.length; 
     6   alert(expargs); // 获取应该传递参数长度,使用 arguments.callee.length 可以获得同样的效果
     7 
     8   alert(arguments.callee); //可以打印函数本身
     9 
    10   Array.prototype.selfvalue = 1;
    11   alert(new Array().selfvalue);
    12 }
    13 function testAguments(){
    14     alert(arguments.selfvalue);
    15 }

      运行代码你会发现第一个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 的大前端时代即将来临,不管你学不学,它就在那里!

     
  • 相关阅读:
    Spring Tool Suite 配置和使用
    自动提示在线/离线状态
    Excel数据导入数据库的SQL快速生成
    MySQL查询和删除重复数据
    内存不足时,调用ajax报的错
    订单支付成功后存储过程
    下订单存储过程
    课程表,订单表(统计报名人数),评论表(统计评论的人数),点赞表(点赞人数)
    更改浏览器的滚动条样式
    自定义文本选中样式
  • 原文地址:https://www.cnblogs.com/shanrengo/p/6386713.html
Copyright © 2011-2022 走看看