• Javascript_函数


    JavaScript 三种声明函数的方法
    
    1. function 命令 
    function print(s) {
        console.log(s);
    }
    
    2. 函数表达式,这种写法将一个匿名函数赋值给变量。
    
    var print = function(s) {
        console.log(s);
    }
    
    3. Function 构造函数,几乎无人使用
    
    var add = new Function(
        'x',
        'y',
        'return x + y'
    
    );
    
    圆括号运算符,return 语句和递归
    function fib(num) {
      if (num === 0) return 0;
      if (num === 1) return 1;
      return fib(num - 2) + fib(num - 1);
    }
    
    第一等公民
    function add(x, y) {
      return x + y;
    }
    
    // 将函数赋值给一个变量
    var operator = add;
    
    // 将函数作为参数和返回值
    function a(op){
      return op;
    }
    a(add)(1, 1)
    // 2
    
    
    
    函数名的提升
    JavaScript 引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。
    
    函数的属性和方法
    
     function fib(num) {
      if (num === 0) return 0;
      if (num === 1) return 1;
      return fib(num - 2) + fib(num - 1);
    }
    undefined
    fib.name
    //"fib"
    fib.length
    //1
    
    
    
    
    
    函数作用域
    
    var v = 1; //全局变量
    //
    function f() {
        var v = 2; //局部变量,函数内部变量会覆盖全局变量
    }
    
    //注意,对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。
    
    if (true) {
        var x = 5;  // 这里的 x 是全局变量,因为它不在函数中
        
    }
    
    
    函数内部的变量提升
    
    //与全局作用域一样,函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
    function foo(x) {
      if (x > 100) {
        var tmp = x - 100;
      }
    }
    
    // 等同于
    function foo(x) {
      var tmp;
      if (x > 100) {
        tmp = x - 100;
      };
    }
    
    函数本身的作用域
    //函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
    var a = 1;
    var x = function () {
      console.log(a);
    };
    
    function f() {
      var a = 2;
      x();   //函数x是在函数f的外部声明的,所以它的作用域绑定外层,内部变量a不会到函数f体内取值,所以输出1,而不是2。
    }
    
    f() // 1
    
    
    function foo() {
      var x = 1;
      function bar() {
        console.log(x);
      }
      return bar;    
    }
    
    var x = 2;
    var f = foo();
    f() // 1
    
    
    参数
    //函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。
    var p = 2;
    
    function f(p) {
      p = 3;
    }
    f(p);
    
    p // 2
    //但是,如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
    
    
    var obj = { p: 1 };
    
    function f(o) {
      o.p = 2;
    }
    f(obj);
    
    obj.p // 2
    
    //注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
    
    var obj = [1, 2, 3];
    
    function f(o) {
      o = [2, 3, 4];
    }
    f(obj);
    
    obj // [1, 2, 3]
    
    同名参数
    
    
    如果有同名的参数,则取最后出现的那个值。
    
    function f(a, a) {
      console.log(a);
    }
    
    f(1, 2) // 2
    
    //调用函数f()的时候,没有提供第二个参数,a的取值就变成了undefined。这时,如果要获得第一个a的值,可以使用arguments对象。
    function f(a, a) {
      console.log(a);
    }
    
    f(1) // undefined
    
    function f(a, a) {
      console.log(arguments[0]);
    }
    
    f(1) // 1
    
    
    arguments 对象
    
    //由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。
    
    //arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。
    
    
    var f = function (one) {
      console.log(arguments[0]);
      console.log(arguments[1]);
      console.log(arguments[2]);
    }
    
    f(1, 2, 3)
    // 1
    // 2
    // 3
    
    
    var f = function(a, b) {
      arguments[0] = 3;
      arguments[1] = 2;
      return a + b;
    }
    
    f(1, 1) // 5
    
    
    //上面代码中,函数f()调用时传入的参数,在函数内部被修改成3和2。
    
    //严格模式下,arguments对象与函数参数不具有联动关系。也就是说,修改arguments对象不会影响到实际的函数参数。
    
    
    
    var f = function(a, b) {
      'use strict'; // 开启严格模式
      arguments[0] = 3;
      arguments[1] = 2;
      return a + b;
    }
    
    f(1, 1) // 2
    
    上面代码中,函数体内是严格模式,这时修改arguments对象,不会影响到真实参数a和b。
    
    通过arguments对象的length属性,可以判断函数调用时到底带几个参数。
    
    
    function f() {
      return arguments.length;
    }
    
    f(1, 2, 3) // 3
    f(1) // 1
    f() // 0
    
    
    
    
    函数的其他知识点
    
    
    //闭包
    //闭包(closure)是 JavaScript 语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
    
    //理解闭包,首先必须理解变量作用域。前面提到,JavaScript 有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。
    
    function f1() {
      var n = 999;
      function f2() {
        console.log(n);
      }
      return f2;
    }
    
    var result = f1();
    result(); // 999
    
    //闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
    //闭包的最大用处有两个,一个是可以读取外层函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。
    
    
    
    function createIncrementor(start) {
      return function () {
        return start++;
      };
    }
    
    var inc = createIncrementor(5);   // 将 createIncrementor 内部方法赋值给变量 inc 
    
    inc() // 5
    inc() // 6
    inc() // 7
    
    闭包的另一个用处,是封装对象的私有属性和私有方法
    function Person(name) {
      var _age;
      function setAge(n) {
        _age = n;
      }
      function getAge() {
        return _age;
      }
    
      return {    // return 通过 对象这个数据类型返回 函数内部的方法
        name: name,
        getAge: getAge,
        setAge: setAge
      };
    }
    
    var p1 = Person('张三');
    p1.setAge(25);
    p1.getAge() // 25
    
    
    立即调用的函数表达式(IIFE)
    
    var f = function f(){ return 1}();
    f // 1
    
    //函数定义后立即调用的解决方法,就是不要让function出现在行首,让引擎将其理解成一个表达式。最简单的处理,就是将其放在一个圆括号里面。
    
    (function(){ /* code */ }());
    // 或者
    (function(){ /* code */ })();
    
    
    
    
    eval 命令
    
    //eval命令接受一个字符串作为参数,并将这个字符串当作语句执行。
    
    eval('var a = 1;');
    a // 1
    
    
    //eval没有自己的作用域,都在当前作用域内执行,因此可能会修改当前作用域的变量的值,造成安全问题。
    
    var a = 1;
    eval('a = 2');
    
    a // 2
    
    (function f() {
      'use strict';
      eval('var foo = 123');
      console.log(foo);  // ReferenceError: foo is not defined
    })()
    
    
    eval 的别名调用,不推荐使用
  • 相关阅读:
    DB2 for Z/os Statement prepare
    Foreign key (referential) constraints on DB2 LUW v105
    复制Informational constraints on LUW DB2 v105
    DB2 SQL Mixed data in character strings
    DB2 create partitioned table
    MVC中使用EF的技巧集(一)
    Asp.Net MVC 开发技巧(二)
    Linq使用技巧及查询示例(一)
    Asp.Net MVC 开发技巧(一)
    Asp.Net MVC Identity 2.2.1 使用技巧(八)
  • 原文地址:https://www.cnblogs.com/zy09/p/14340223.html
Copyright © 2020-2023  润新知