zoukankan      html  css  js  c++  java
  • 引用类型-Function类型

    Function类型


    定义函数的三种方式:

    1、函数声明

    function sum(num1,num2){
                return num1 +num2;
            }

    2、函数表达式

    var sum = function(num1,num2){
                return num1 + num2;
            }

    3、Function构造函数(不推荐)
    //最后一个参数始终都被认作函数体,会导致解析两次代码

    var sum =new Function("num1","num2","return num1 + num2");

    注意:函数名仅仅是指向函数的指针,因此函数名与其他包含对象的指针没有设么区别

    function sum(num1,num2){
                return num1 + num2;
            }
    alert(sum(10,10)); //20
    
    var another = sum;
    alert(another(10,10)); //20
    
    sum = null;
    alert(another(10,10)); //20
    sum和another都指向同一个函数,所以讲sum设置为null并不影响another

    注意:使用不带圆括号的函数名是访问函数指针,并不是调用函数

    没有重载


    将函数名理解为指针有利于理解为什么没有重载

    function addSomeNumber(num){
                return num + 100;
            }
    function addSomeNumber(num){
                return num + 200;
            }
    alert(addSomeNumber(100)); //300

    第二个函数将addSomeNumber指向新的函数

    函数声明与函数表达式


    解析器在向执行环境中加载数据时,对函数声明和函数表达式不是一时同仁。解析器会率先读取函数声明,并使其在执新行任何代码之前可用。对于函数表达式,则必须等到执行到它所在的代码行,才会真正被解析。

    alert(sum(10.10)); //20
    function sum(num1,num2){
                return num1 +num2;
            }

    在代码执行环境之前,解析器会通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境当中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部

    alert(sum(10,10)); //产生错误,因为在与函数位于一个初始化语句中,而不是一个函数声明
    var sum = function(num1,num2){
                return num1 + num2;
            }

    作为值的函数


    可以像传递参数一样把一个函数传递给另一个函数,也可以将一个函数作为另一个函数的结果返回。

    function callSomeFunction(someFunction,someArugment){
                return someFunction(someArugment);
            }
    
    function add10(num){
                return num + 10;
            }
    
    var result = callSomeFunction(add10,10);
    alert(result);//20

    可以从一个函数中返回另一个函数

    function createComparisonFunction(propertyName){
                return function(object1,object2){
                    var values1 = object1[propertyName];
                    var values2 = object2[propertyName];
                    if(values1<values2)
                        return -1;
                    else if(values1>values2)
                        return 1;
                    else
                        return 0;
                };
            }
    var data = [{name:"qunzhu",age:21},{name:"huishuai",age:22},{name:"kuolang",age:23}];
    data.sort(createComparisonFunction(name));
    alert(data[1].name); //huishuai

    函数内部属性


    在函数内部,有两个特殊的对象:arguments和this。
    arguments他是一个类数组对象,包含着传入函数中所有的参数,他有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。

    function factorial(num){
                if(num<=1)
                    return 1;
                else
                    return num * factorial(num-1);
            }

    函数有一个问题,函数的执行与函数名耦合在了一起
    改进

    function factorial(num){
                if(num<=1)
                    return 1;
                else
                    return num * arguments.callee(num-1);
            }
    var trueFactorial = factorial;
    factorial = function(){
                return 0;
            }
    alert(trueFactorial(5)); //120
    alert(factorial(5)); //0

    this引用的是函数数据以执行的环境对象或者也可以说是this值(当在网页的全局作用域中调用函数时this对象引用的是window)

    window.color = "red";
    var o = {color:"blue"};
    function sayColor(){
                alert(this.color);
            }
    sayColor(); //red
    o.sayColor = sayColor;
    o.sayColor(); //blue

    ECMAScript5也规范化了另一个函数对象的属性:caller,这个属性保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,则返回null。

    function outer(){
                inner();
            }
    function inner(){
                alert(inner.caller);
            }
    outer();//会弹出警告框,显示outer()的源代码

     

    函数属性和方法


    每个函数都有两个属性:length和prototype
    length属性表示函数希望接受的命名参数

    function sum(num1,num2){
                return num1 + num2;
            }
    alert(sum.length); //2

    对于ECMAScript中的引用类型而言,prototype是保存他们所有实例方法的真正所在,prototype的属性是不可枚举的,因此使用for-in无法发现


    每个函数都包含两个非继承的方法:apply()和call()。这两个方法的用途都是在指定的作用域中调用函数,实际上等于设置函数体内的this对象的值

    function sum(num1,num2){
                return num1 + num2;
            }
    
    function callSum1(num1,num2){
                return sum.apply(this,arguments);
            }
    
    function callSum2(num1,num2){
                return sum.apply(this,[num1,num2]);
            }
    alert(callSum1(10,10)); //20
    alert(callSum2(10,10)); //20

    call()方法与apply()方法的作用相同,他们的区别在于接受参数的方式不同,call()方法,第一个参数时this值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来

    function sum(num1,num2){
                return num1 + num2;
            }
    function callSum(num1,num2){
                 return sum.call(this,num1,num2);
             }
     alert(callSum(10,10)); //20

     其实call()和apply()真正强大的地方在于能够扩充函数赖以运行的作用域

     window.color = "red";
     var o = {color:"blue"};
     function sayColor(){
                 alert(this.color);
             }
     sayColor(); //red
     sayColor.call(this); //red
     sayColor.call(window); //red
     sayColor.call(o); //blue

     ECMAScript5还定义了一个方法bind()。这个方法会创建一个函数的实例,起this值会绑定到传给bind()函数的值

     window.color = "red";
    var o = {color:"blue"};
    function sayColor(){
                alert(this.color);
            }
    var objectSayColor = sayColor.bind(o);
    objectSayColor(); //blue

    每个函数继承的toLocaleString()和toString()方法会始终返回函数的代码。

    不要在该奋斗的年纪而选择了安逸
  • 相关阅读:
    什么是HTTP?
    什么是OSI的第7层
    OSI7层模型
    什么是WAF?
    什么是Mirai僵尸网络
    什么是僵尸网络?
    洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    如何给数组的结构体排序 关于sort用法
    洛谷 P1803 凌乱的yyy / 线段覆盖
    洛谷 P1007 独木桥
  • 原文地址:https://www.cnblogs.com/qqandfqr/p/5528680.html
Copyright © 2011-2022 走看看