zoukankan      html  css  js  c++  java
  • 转载自chaos_JS 的JavaScript中的Function类型浅析

    1. Function类型是js中引用类型之一,每个函数实际上都是Function类型的实例对象,具有自己的属性和方法。正因为函数式对象,所以函数名实际上也是一个指向函数对象的指针。

    2. 常用的函数定义方式

    复制代码
    1. 函数声明:
    function sum(a , b ){
      return       a+b;
    }
    
    2. 表达式:
    var sum = function(){
           return       a+b;   
    };    //注意分号


     //两种方式的区别:
     //解释器会率先读取函数声明,并使其在执行之前可以访问,而使用表达式则必须等到解析器执行到它所在的代码行,才会真正被解释执行(变量声明提前,而值留在原地)

    alert (sum (10 ,10));
    function sum(a ,b){
      return a+b;
    }
    //↑上面的代码会正常执行,因为在代码执行前,解析器通过函数声明提升,读取并将函数声明添加到执行环境中,放到代码树的顶部


    alert (typeof sum);
    alert(sum(10 , 10));
    var sum = function (a ,b){
      return a+b;
    }
    //↑报错,原因在于函数位于一个初始化语句中,不是一个函数声明,不会被提前,而只会把var sum提前,用typeof操作符显示sum是undefined,所以报错
     
    复制代码

    3. 函数名仅仅保存指向函数对象的指针,因此函数名与包含对象指针的其他变量没什么不同,也就是说,一个函数对象可以有多个名字:

    复制代码
    function sum(a , b ){
      return       a+b;
    }
    console.log(sum(2 ,3));  //5
    
    var anotherSum = sum;     //变量anotherSum也指向了同一个函数对象
    console.log(anotherSum(4  , 5));    //9
    
    sum = null;    //sum变量不再保存函数对象的指针了
    console.log(anotherSum(1  , 3));    //anotherSum这个变量仍能调用
    复制代码

    4. JS为何没有重载这个概念。

    复制代码
    function add(a){
      return a+3  ;
    }
    function add(a){
        return a+5;
    }
    var result = add(3);    //8
    
    //两个函数同名了,结果只能是后一个函数覆盖前一个,所以不能重载
    复制代码

    5. 函数的内部属性:函数内部,有两个特殊的对象,arguments和this

      1. arguments:

        arguments是个类数组对象,包含着传入函数的所有参数,这个对象有一个叫callee的属性,属性值是一个指针,指向拥有这个arguments对象的函数本身

    复制代码
    function foo (){
    var a =arguments.callee;     
    return a.toString();
    }
    foo();
    /*
    返回结果:
      "function sum(){   var a =arguments.callee;   return a.toString();   }"
    也就是说,一个函数内部,arguments.callee指的就是这个函数本身。这个函数在递归调用时有点用,有许多缺陷,在ES5严格模式被移除
    */
    复制代码

      2. this:简单来说,this指的就是函数执行的环境对象,在哪个对象中执行,this就指哪个对象。展开来说比较复杂,单开一篇

    //TODO:

      3. ES5规范了函数的另一个属性:caller,这个函数属性指的是调用当前函数的函数

    复制代码
    function inner(){
          console.log(inner.caller);
    } 
    function outer(){
         inner();
    }
    
    outer();    
    //function outer(){
         inner();
    }
    复制代码

      4. length属性:表示函数希望接受的参数个数

    function add(a ,b ,c){
        return a+b+c;
    }
    add.length;    //3

      5. 著名的prototype属性,简单来说,是一个对象,是通过调用构造函数而创建的一个对象,包含可以由特定类型的所有实例共享的属性和方法。展开来说比较复杂,单开一篇

    //TODO:

    6. 函数的两个方法:call()和apply(),作用都是在特定的作用域中调用函数,实际上就是设置函数内部的this值

      1. call():与apply()方法类似,区别在接收参数的方式不同,参数必须逐个列出来。

      2. apply():接收两个参数,一个是函数运行的作用域,另一个是参数数组,可以是数组,也可以是arguments这个类数组对象

    复制代码
    function sum(a , b){
      return   a+b;
    }
    
    function callSum(a  ,  b){
        return sum.apply(this , arguments);
    }//第二个参数是一个类数组对象arguments
    
    function callSum1(a  , b){
        return sum.apply(this,  [a  , b]);
    }    //第二个参数是一个数组
    console.log(callSum(2 , 3)); //5   
    console.log(callSum1(3 ,5));    //8
    复制代码

      3. 传递参数并调用函数并非call()和apply()的用武之地,二者真正强大的地方是扩充函数运行的作用域

    复制代码
    var color = 'red';
    var obj = {
      color  :'blue'  
    }
    function foo(){
      console.log(this.color);  
    }
    
    foo();    //'red'
    foo.call(this);//'red'
    foo.call(obj);    //'blue'
    //最后一次调用foo()函数的执行环境变了,其中的this指向了obj对象,所以是'blue'
    复制代码

       使用call()和apply()扩充作用域的最大好处,就是使对象与方法之间解耦

      4. ES5定义了一个新方法:bind(),返回一个函数,这个函数中this值会被绑定到传给bind()函数的值

    复制代码
    var x = 9; 
    var module = {
      x: 81,
      getX: function() { return this.x; }
    };
    
    module.getX(); // 81
    
    var retrieveX = module.getX;
    retrieveX(); // 9, 因为在这种情况下, "this" 指向全局变量
    
    
    var boundGetX = retrieveX.bind(module);//把retrieveX()函数中的this永远与module绑定,再调用这个函数永远都是在module对象中运行
    boundGetX(); // 81
    复制代码
  • 相关阅读:
    失衡天平
    简单 hash 入门题目
    美团codem 数列互质
    最小圆覆盖
    求1-n 中与 m 互质的素因子 (容斥原理)
    格式化输出;while循环;运算符
    python的历史 常量 注释 基础数据类型等基本操作 和if 判断语句
    异常的概念
    isinstance与issubclass
    面向对象——内置函数
  • 原文地址:https://www.cnblogs.com/shenyuelong/p/5654821.html
Copyright © 2011-2022 走看看