zoukankan      html  css  js  c++  java
  • Function类型

    在ES中,函数实际上是对象,和其他引用类型一样具有属性和方法。
    函数名实际上是一个指向函数对象的指针,指向函数而不绑定函数,也就是说一个函数可能有多个函数名。

    ES中没有函数重载,如果声明了两个同名函数,那后面的函数会覆该前面的函数。

    函数的定义:

    //声明式定义函数
    function sum(num1,num2){
        ……
    }
    
    //函数表达式定义
    var sum = function(num1,num2){
        ……
    }
    

    两种定义方式几乎一样,唯一的区别是:

    解析器在执行环境中加载数据时,解析器会率先读取函数声明,并使其在执行任何代码前可用。
    而函数表达式,则必须等到解析器执行到它所在的代码行,才会被解释执行。

    例:  
    
    //声明式
    console.log(sum(10,10));
    function sum(num1,num2){
        return num1 + num2;
    }
    /* 输出 20 */
    
    
    //函数式
    console.log(sum(10,10));
    var sum = function(num1,num2){
        return num1 + num2;
    }
    
    /* 输出报错  sum is not a function */
    

    作为值的函数
    1. 把一个函数作为参数传递给另一个函数
    function callSomeFunction(someFunction, someArgument){
        return someFunction(someArgument);
    }
    
    function add10(num){
        return num + 10;
    }
    
    function getGreeting(name){
        return "hello, " + name;
    }
    
    var result1 = callSomeFunction(add10, 10);
    console.log('result1 = ', result1);
    
    var result2 = callSomeFunction(getGreeting, 'cat');
    console.log('result2 = ', result2);
    
    /* 输出 
    result1 =  20
    result2 =  hello, cat
    */
    
    1. 将一个函数作为另一个函数的结果返回
    function createComparisonFunction(propertyName){
        return function(object1,object2){
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
    
            if(value1 < value2){
                return -1;
            }else if(value1 > value2){
                return 1;
            }else{
                return 0;
            }
        }
    }
    
    
    var data = [{name:'Tuanzi', age:'1'}, {name:'Weiwei', age: '0.8'}, {name:'Lanlan', age:'0.4'}];
    
    data.sort(createComparisonFunction('age'));
    console.log(data);
    
    /* 输出1:
    [ { name: 'Lanlan', age: '0.4' },
      { name: 'Weiwei', age: '0.8' },
      { name: 'Tuanzi', age: '1' } ]
    */
    
    
    data.sort(createComparisonFunction('name'));
    console.log(data);
    
    /* 输出2:
    [ { name: 'Lanlan', age: '0.4' },
      { name: 'Tuanzi', age: '1' },
      { name: 'Weiwei', age: '0.8' } ]
    */
    
    

    注:要访问函数的指针而不调用函数就去掉后面的圆括号,函数名加上圆括号就是使用(调用)函数;


    函数内部属性

    在函数内部,有两个特殊的对象: ①arguments 和 ②this。

    arguments

    arguments是一个类数组对象,包含着传入函数中的所有参数。
    这个对象还有个callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

    //例子1:  
    
    function factorial(num){
        if(num <= 1){
            return 1;
        }else{
            return num * factorial(num - 1);
        }
    }
    
    console.log(factorial(3));
    //输出 6
    
    //例子2:
    
    function factorial(num){
        if(num <= 1){
            return 1;
        }else{
            return num * arguments.callee(num - 1);
        }
    }
    
    console.log(factorial(3));
    //输出 6
    

    从以上两种方法可以看出,他们的结果相同。但最好用例2,因为假设在阶乘函数中,如果和函数名紧紧耦合在一起,那么如果后面遇到函数名变了的情况,就会报错或者运算出错,而使用arguments.callee就可以避免这种情况。

    this

    this引用的是函数据以执行的环境对象——也可以说是this的值。

    global.color = 'red';
    var o = {color:'blue'};
    
    function sayColor(){
        console.log(this.color);
    }
    
    o.sayColor = sayColor;
    
    sayColor();             //输出 'red'
    o.sayColor();           //输出 'blue'
    

    在上例中,sayColor()在全局环境中调用就指向全局执行性环境global,o.sayColor()在o对象中调用就指向o;
    this——谁调用函数就指向谁,也可以说this指向当前函数的执行环境。


    那在看一个额外的点,涉及到作用域问题,如下例:

    global.color = 'red';
    var o = {color:'blue'};
    
    function sayColor(){
        color = 'yellow'; //这里相当于一个隐式声明,隐式声明定义的是全局变量,var声明定义的是局部变量
        console.log(this.color);
    }
    
    o.sayColor = sayColor;
    
    sayColor();             //输出 'yellow'
    o.sayColor();           //输出 'blue'
    

    在函数内容,我新增了个赋值,调用后发现,sayColor的值改变了,o.sayColor输出的值还是没变,开始没想通,后来想通了:
    相当于是在函数内声明了个隐式变量,隐式声明定义的是全局变量,var声明定义的是局部变量,因此,这里改变的是全局global的color 值,而o对象中的值没受影响。

    注:函数名仅仅是一个包含指针的变量,即使不同的环境中执行,它们指向的仍是同一个函数


    函数的属性和方法

    每个函数都包含两个属性:①length ②prototype

    length

    表示函数希望接收的命名参数的个数

    function sayName(name){
        console.log(name)
    }
    
    function sum(num1, num2){
        return num1 + num2;
    }
    
    function sayHi(){
        console.log('hi~');
    }
    
    
    console.log('sayName: ', sayName.length);
    console.log('sum: ', sum.length);
    console.log('sayHi: ', sayHi.length);
    
    
    /* 输出 
    sayName:  1
    sum:  2
    sayHi:  0
    */
    
    

    prototype

    对于ES中的引用类型而言,prototype是保存它们所有实例方法的真正所在。例如toString()vualeOf()等方法都保存在prototype名下。


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

    apply()
    接收两个参数: ①在其中运行函数的作用域; ②参数数组(可以试array实例,也可以是arguments对象);

    //第二个参数的使用例子
    
    function sum(num1,num2){
        return num1 + num2;
    }
    
    function callSum(num1,num2){
        return sum.apply(this, arguments);
    }
    
    function callSum2(num1,num2){
        return sum.apply(this, [num1,num2]);
    }
    
    console.log('callSum = ', callSum(5,5))
    console.log('callSum2 = ', callSum2(5,5))
    
    /* 输出 
    callSum =  10
    callSum2 =  10
    */
    

    从上例可以看出,在传入第二个参数时,无论传入arguments对象还是一个参数数组,两个函数都会正常执行并返回正确结果。

    call()

    call()的作用和apply()相同,他们唯一的区别是:apply()的第二参数可接收一个参数数组或者arguments对象,而call()的第二参数需要逐个列出来, 例:

    //call() 和 apply() 的使用区别  
    
    function sum(num1,num2){
        return num1 + num2;
    }
    function callSum3(num1,num2){
        return sum.call(this, num1,num2);
    }
    
    console.log('callSum3 = ', callSum3(5,5));
    
    /* 输出 
    callSum3 =  10
    */
    

    对于call()方法来说,假设你第二个参数传入了一个数组,那么,它只会把这个数组当做第二个参数的第一个元素,剩下的如果没有传入,则会输出undefined

    使用 apply() 还是使用 call() ?

    取决你采用哪种函数传递参数的方式最方便。
    如果你打算直接传入arguments或者接受一个参数数组则用 apply()
    否则就用call()


    apply()call() 最大的用途是扩充函数赖以运行的作用域:

    window.color = 'red';
    var o = {color: 'blue'};
    
    function sayColor(){
        console.log(this.color);
    }
    
    sayColor.call(this);
    sayColor.call(window);
    sayColor.call(o);
    
    /* 输出 
    red
    red
    blue
    */
    

    这样就可以直接扩展作用域。
    这里需要注意的是: 如果在node中全局调用,由于node和ES6,this返回的当前模块,所以这是this会返回undefined。

    global.color = 'red';
    var o = {color: 'blue'};
    
    function sayColor(){
        console.log(this.color);
    }
    
    sayColor.call(this);
    sayColor.call(global);
    sayColor.call(o);
    
    /* 输出 
    undefined
    red
    blue
    */
    
  • 相关阅读:
    频率计数器简介
    电力时钟厂家简介
    linux mail命令详解
    /etc/postfix下 main.cf 配置文件详解
    linux tar
    Linux find命令详解
    Python with
    Python 多进程概述
    python paramiko模块简介
    python 全局变量和局部变量
  • 原文地址:https://www.cnblogs.com/mlcat/p/11269036.html
Copyright © 2011-2022 走看看