• JavaScript对象(一)——Function对象


    写在最前面:

    对象只是带有属性方法的特殊数据类型(js的7种数据类型:字符串,数字,布尔,数组,对象,null,undefined)。

    JavaScript是面向对象的语言,但是JavaScript和其他面向对象语言不同,它没有类的概念。没有类自然也不会通过类来创建对象,JavaScript基于prototype,而不是基于类。

    JavaScript 中的所有事物都是对象:字符串、数值、数组、函数...此外,JavaScript 允许自定义对象。

    JavaScript 提供多个内建对象,比如 String、Date、Array 等等,先从Function开始。

    对象是带有属性和方法的特殊数据类型,从这句话入手,从三方面看一看Function对象:1、声明(数据类型)2、属性 3、方法 

    一、声明

      1、函数声明  

    function foo(argname1,argname2,...){
       body// do something       
    }

      2、函数表达式

    var foo = function(argname1,argname2,...){
        body// do something
    }

      3、Function构造函数

    var foo = new Function(argname1,argname2,...,body);

     

    二、属性(不包括继承来的属性)

      1、arguments属性 

        获取当前正在执行的 Function 对象的参数(arguments对象)。

      示例:

     1 function ArgTest(arg1, arg2){
     2           var s = "";
     3            s += "The individual arguments are: "
     4           for (n = 0; n < arguments.length; n++){//arguments是对象属性,它本身也是对象,有length属性
     5                   s += ArgTest.arguments[n];
     6                   s += " ";
     7            }
     8            return(s);
     9 }
    10 console.log(ArgTest("yuanliang","shuai"));

      输出结果:The individual arguments are: yuanliang shuai 

      2、caller属性

        获取调用当前函数的函数。

        caller 属性只有当函数正在执行时才被定义。 如果函数是从 JavaScript 程序的顶层调用的,则 caller 包含 null。

      示例:

     1 function callerFun(){
     2         console.log(callerFun.caller);//只有函数正在执行时才被定义
     3 }
     4 
     5 function init(){
     6         callerFun();
     7 }
     8 
     9 init();
    10 callerFun();

      输出结果:function init(){callerFun();}  null  //第一次调用callerFun()是通过init函数调用的,故返回init函数,第二次直接调用故返回null

      3、length属性

        获取函数的参数数目

        创建函数的实例后,脚本引擎将该函数的 length 属性初始化为该函数定义中的参数数量。

      示例:

    1 function lengthFun(arg1,arg2,arg3,arg4){
    2                  console.log("lengthFun's length="+lengthFun.length);
    3                  console.log("arguments' length="+arguments.length);
    4 }
    5 
    6 lengthFun(1,2,3);

      输出结果:lengthFun's length=4   arguments' length=3

      从示例中能够看到,Function对象的length和arguemnts的length不一定相同。

     

    三、方法(不包括继承自Object对象的方法)

      1、apply() 和 call()方法

      见上一篇博客:http://www.cnblogs.com/wangyuanliang/p/4264505.html

      2、bind()方法

      对于给定函数,创建与原始函数相同的主体的绑定函数。 在绑定函数中,this 对象将解析为传入的对象。 绑定函数具有指定的初始参数。

      function.bind(thisArg[,arg1[,arg2[,argN]]])

        function

          必选。 一个函数对象。

        thisArg

          必选。 this 关键字可在新函数中引用的对象。//一个对象,

        arg1[,arg2[,argN]]]

          可选。 要传递到新函数的参数的列表。

      示例1:

     1 function bindFun(value){
     2                       if(typeof value !== 'number')
     3                           console.log("not a number");
     4                       else
     5                           value>=this.min&&value<=this.max?console.log("number is correct!"):console.log("number is wrong!");
     6     }
     7 var option = {max:50,min:10};
     8 var judgeFun = bindFun.bind(option);
     9 judgeFun(30);
    10 judgeFun(80);

      输出结果:number is correct! number is wrong!   //第一个在范围之内返回correct 第二个不在范围返回wrong

      这里的参数option对应thisArg为必填参数

      示例2:

    1 function bindParamFun(arg1,arg2,arg3,arg4){
    2         console.log("bindParamFun params are : "+arg1+arg2+arg3+arg4);
    3     }
    4 var emptyObject = {};
    5 
    6 var bindParamFun2 = bindParamFun.bind(emptyObject,"a","b");
    7 bindParamFun2("c","d","e");

      输出结果:bindParamFun params are : abcd  //在bindParamFun2中第一个参数是一个空的对象,充当thisArg,如果没有此参数,“a”将被当做thisArg,输出结果将是:bindParamFun params are : bcde

    四、一些需要特别注意的地方

      1、如何选择声明方式?

      在(一、声明)中的三种方式中我们应该选择哪一种才是合适的呢?

      大多数javascript书籍里面不推荐使用第三种,原因第三种存在严重的性能问题,这种定义会解析两次代码,第一次是常规的解析这条语句,第二次要把函数里的字符串解析成实际的函数。我们可以通过第三种方式可以理解到:javascript的函数其实是对象(object),而函数名是指向对象的地址。

      函数声明和函数表达式:

      这两个方式在性能上没有太大的去区别,但由于JavaSctipt预加载顺序的不同,在定义函数时需要注意一下。

      代码执行之前,解析器就已经读取函数声明并将其添加到执行环境中,要早于基础基础数据类型的定义。

      示例1:

     1 function foo2(){
     2         console.log("foo1");
     3 }
     4 
     5 var fun = foo2;
     6 function foo2(){
     7         fun();
     8         console.log("foo2");
     9 }
    10 foo2();

      输出结果:too much recursion  //出现递归,内存溢出

      如果改为:

      示例2:

    1 var foo2 = function(){
    2     console.log("foo1");
    3 };
    4 var fun = foo2;
    5 var foo2 = function(){
    6          fun();
    7          console.log("foo2");
    8 };
    9 foo2();

      输出结果:foo1 foo2 

      原因就是在代码执行前,JavaScript会将function提前定义,即:funciton=>var 

                                                       对比

      function foo2(){console.log("foo1");};   //old                var foo2 = function(){console.log("foo1)};    //foo2指向旧的方法

      function foo2(fun();console.log("foo2"));   //new                 var fun  = foo2;                                   //将foo2的地址给fun 即fun指向旧的方法                                

      var fun = foo2;              //fun指向的地址是新的foo2         foo2 = function(){fun();console.log("foo2)};   //foo2指向新的方法的地址 fun不变

      foo2();                //此时就会出现内存溢出         foo2();                     //执行foo2

      2、没有重载

      JavaScript中的function没有重载,后面的定义将会覆盖前面的定义。

    1 function foo(arg1,arg2,arg3){
    2         console.log("This is a function:"+arg1+arg2+arg3);
    3 }
    4 function foo(arg1,arg2){
    5         console.log("Be Better:"+arg1+arg2);
    6 }
    7 foo("hello","world","leon");  //没有区执行三个参数的方法

      输出结果:Be Better:helloworld

      明显,在传入三个参数的情况下,仍然执行了后面定义的方法,原因是发生了覆盖而不是重载。相当于:

    1 var foo = function(arg1,arg2,arg3){
    2         console.log("This is a function:"+arg1+arg2+arg3);
    3 }
    4 
    5 foo = function(arg1,arg2){
    6         console.log("Be Better:"+arg1+arg2);
    7 }
    8 foo("hello","world","leon"); 

      

  • 相关阅读:
    java继承
    c#中委托和事件区别
    c#委托中的匿名方法和lambda表达式
    c#中内置委托
    iOS消息推送获取不到deviceToken解决方案
    python+appium+iOS自动化测试case如何写?
    Xcode查看iOS崩溃与崩溃日志分析
    iOS性能检测工具instrunments简单介绍
    python实现使用代码进行代理配置
    python+locust性能测试-最简单的登录点击次数
  • 原文地址:https://www.cnblogs.com/wangyuanliang/p/4280354.html
Copyright © 2020-2023  润新知