JavaScript学习笔记(三)

JavaScript学习笔记(三)

  • 仅为个人学习记录所用,学习内容为菜鸟联盟JavaScript

JavaScript 函数定义

  • JavaScript 使用关键字 function 定义函数。
  • 函数可以通过声明定义,也可以是一个表达式。

函数声明

  •   function functionName(parameters) {
        执行的代码
      }
    

函数表达式

  • JavaScript 函数可以通过一个表达式定义。

  • 函数表达式可以存储在变量中

  • var x = function (a, b) {return a * b};

  • 在函数表达式存储在变量后,变量也可作为一个函数使用:

    •   var x = function (a, b) {return a * b};
        var z = x(4, 3);
      
  • 以上函数实际上是一个 匿名函数 (函数没有名称)。

  • 函数存储在变量中,不需要函数名称,通常通过变量名来调用。

Function()构造函数

  • 除了通过关键字function定义,函数同样可以通过内置的 JavaScript 函数构造器(Function())定义。

  •   var myFunction = new Function("a", "b", "return a * b");
      var x = myFunction(4, 3);
      
      //也可以写成
      var myFunction = function (a, b) {return a * b};
      var x = myFunction(4, 3);--
    
  • 在 JavaScript 中,很多时候需要避免使用 new 关键字。

函数提升(Hoisting)

  • 提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为。

  • 提升(Hoisting)应用在变量的声明与函数的声明。

    • 因此,函数可以在声明之前调用

    •   myFunction(5);
        
        function myFunction(y) {
            return y * y;
        }
      

自调用函数

  • 函数表达式可以 “自调用”。

  • 自调用表达式会自动调用。

  • 如果表达式后面紧跟 () ,则会自动调用。

  • 不能自调用声明的函数。

  • 通过添加括号,来说明它是一个函数表达式

  •   (function () {
          var x = "Hello!!";      // 我将调用自己
      })();
      //以上函数实际上是一个 匿名自我调用的函数 (没有函数名)。
    

函数可作为一个值使用

  • JavaScript 函数作为一个值使用

    •   function myFunction(a, b) {
            return a * b;
        }
        
        var x = myFunction(4, 3);
      
  • JavaScript 函数可作为表达式使用

    •   function myFunction(a, b) {
            return a * b;
        }
        
        var x = myFunction(4, 3) * 2;
      

函数是对象

  • 在 JavaScript 中使用 typeof 操作符判断函数类型将返回 “function” 。

  • 但是JavaScript 函数描述为一个对象更加准确。

  • JavaScript 函数有 属性方法

  • arguments.length 属性返回函数调用过程接收到的参数个数

    •   function myFunction(a, b) {
            return arguments.length;
        }
      
  • toString()方法将函数作为一个字符串返回

    •   function myFunction(a, b) {
            return a * b;
        }
        
        var txt = myFunction.toString();
      
  • 函数定义作为对象的属性,称之为对象方法。 函数如果用于创建新的对象,称之为对象的构造函数。

箭头函数

  • ES6 新增了箭头函数。

  • 箭头函数表达式的语法比普通函数表达式更简洁。

  • 语法

    •   (参数1, 参数2,, 参数N) => { 函数声明 }
        
        (参数1, 参数2,, 参数N) => 表达式(单一)
        // 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
      
  • 当只有一个参数时,圆括号是可选的

    •   (单一参数) => {函数声明}
        单一参数 => {函数声明}
      
  • 没有参数的函数应该写成一对圆括号

    • () => {函数声明}

    •   // ES5
        var x = function(x, y) {
             return x * y;
        }
         
        // ES6
        const x = (x, y) => x * y;
      
  • 有的箭头函数都没有自己的 this。 不适合定义一个 对象的方法

  • 当使用箭头函数的时候,箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的。

  • 箭头函数是不能提升的,所以需要在使用之前定义。

  • 使用 const 比使用 var 更安全,因为函数表达式始终是一个常量。

  • 如果函数部分只是一个语句,则可以省略 return 关键字和大括号 {},这样做是一个比较好的习惯

  • const x = (x, y) => { return x * y };

JavaScript 函数参数

  • JavaScript 函数对参数的值没有进行任何的检查。

函数显式参数(Parameters)与隐式参数(Arguments

  • functionName(parameter1, parameter2, parameter3) { // 要执行的代码…… }
  • 函数显式参数在函数定义时列出。
  • 函数隐式参数在函数调用时传递给函数真正的值。

参数规则

  • JavaScript 函数定义显式参数时没有指定数据类型。
  • 对隐式参数没有进行类型检测。
  • 对隐式参数的个数没有进行检测。

默认参数

  • ES5 中如果函数在调用时未提供隐式参数,参数会默认设置为: undefined

  • 建议最好为参数设置一个默认值:

    •   function myFunction(x, y) {
            if (y === undefined) {
                  y = 0;
            } 
        }
        
        function myFunction(x, y) {
            y = y || 0;
        }
        
        //	如果y已经定义 , y || 返回 y, 因为 y 是 true, 否则返回 0, 因为 undefined 为 false。
      
  • 如果函数调用时设置了过多的参数,参数将无法被引用,因为无法找到对应的参数名。 只能使用 arguments 对象来调用。

自带参数

  • ES6 支持函数带有默认参数,就判断 undefined 和 || 的操作:

  •   function myFunction(x, y = 10) {
          // y is 10 if not passed or undefined
          return x + y;
      }
       
      myFunction(0, 2) // 输出 2
      myFunction(5); // 输出 15, y 参数的默认值
    

arguments 对象

  • JavaScript 函数有个内置的对象 arguments 对象。

  • argument 对象包含了函数调用的参数数组。

  •   //找到最大的一个参数的值
      x = findMax(1, 123, 500, 115, 44, 88);
       
      function findMax() {
          var i, max = arguments[0];
          
          if(arguments.length < 2) return max;
       
          for (i = 0; i < arguments.length; i++) {
              if (arguments[i] > max) {
                  max = arguments[i];
              }
          }
          return max;
      }
      
      //用来统计所有数值的和
      x = sumAll(1, 123, 500, 115, 44, 88);
       
      function sumAll() {
          var i, sum = 0;
          for (i = 0; i < arguments.length; i++) {
              sum += arguments[i];
          }
          return sum;
      }
    

通过值传递参数

  • 在函数中调用的参数是函数的隐式参数。
  • JavaScript 隐式参数通过值来传递:函数仅仅只是获取值。
  • 如果函数修改参数的值,不会修改显式参数的初始值(在函数外定义)。
  • 隐式参数的改变在函数外是不可见的。

通过对象传递参数

  • 在JavaScript中,可以引用对象的值。
  • 因此我们在函数内部修改对象的属性就会修改其初始的值。
  • 修改对象属性可作用于函数外部(全局变量)。
  • 修改对象属性在函数外是可见的。

JavaScript 函数调用

  • JavaScript 函数有 4 种调用方式。
  • 每种方式的不同在于 this 的初始化。

this 关键字

  • this指向函数执行时的当前对象。

作为一个函数调用

  •   function myFunction(a, b) {
          return a * b;
      }
      myFunction(10, 2);           // myFunction(10, 2) 返回 20
    
  • 以上函数不属于任何对象。但是在 JavaScript 中它始终是默认的全局对象。

  • 在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTML 页面。

  • 在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数。

  • 这是调用 JavaScript 函数常用的方法, 但不是良好的编程习惯。

  • 全局变量,方法或函数容易造成命名冲突的bug。

  • 全局对象

    • 当函数没有被自身的对象调用时 this 的值就会变成全局对象。

    • 在 web 浏览器中全局对象是浏览器窗口(window 对象)。

    • 该实例返回 this 的值是 window 对象

      •   function myFunction() {
              return this;
          }
          myFunction();                // 返回 window 对象
        
    • 函数作为全局对象调用,会使 this 的值成为全局对象。 使用window 对象作为一个变量容易造成程序崩溃。

函数作为方法调用

  • 可以将函数定义为对象的方法。

  •   //创建了一个对象 (myObject), 对象有两个属性 (firstName 和 lastName), 及一个方法 (fullName)
      var myObject = {
          firstName:"John",
          lastName: "Doe",
          fullName: function () {
              return this.firstName + " " + this.lastName;
          }
      }
      myObject.fullName();         // 返回 "John Doe"
      
      //fullName 方法是一个函数。函数属于对象。 myObject 是函数的所有者。
      
      //this对象,拥有 JavaScript 代码。实例中 this 的值为 myObject 对象。
      
      
      //修改 fullName 方法并返回 this 值
      var myObject = {
          firstName:"John",
          lastName: "Doe",
          fullName: function () {
              return this;
          }
      }
      myObject.fullName();          // 返回 [object Object] (所有者对象)
    
  • 函数作为对象方法调用,会使得 this 的值成为对象本身。

使用构造函数调用函数

  • 如果函数调用前使用了 new 关键字, 则是调用了构造函数。

  • 这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象

    •   // 构造函数:
        function myFunction(arg1, arg2) {
            this.firstName = arg1;
            this.lastName  = arg2;
        }
         
        // This    creates a new object
        var x = new myFunction("John","Doe");
        x.firstName;                             // 返回 "John"
      
  • 构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。

    • 构造函数中 this 关键字没有任何的值。 this 的值在函数调用实例化对象(new object)时创建。

作为函数方法调用函数

  • 在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。

  • call()apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。

  •   function myFunction(a, b) {
          return a * b;
      }
      myObject = myFunction.call(myObject, 10, 2);     // 返回 20
      
      function myFunction(a, b) {
          return a * b;
      }
      myArray = [10, 2];
      myObject = myFunction.apply(myObject, myArray);  // 返回 20
    
    • 两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
    • 在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
    • 在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
    • 通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。

JavaScript 闭包

  • JavaScript 变量可以是局部变量或全局变量。
  • 私有变量可以用到闭包。

全局变量与局部变量

  • 全局变量可应用于页面上的所有脚本。
  • 局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。
  • 全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
  • 变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。

变量生命周期

  • 全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
  • 而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。

JavaScript 内嵌函数

  • 所有函数都能访问全局变量。
  • 实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。
  • JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

JavaScript 闭包

  • 函数自我调用

    •   var add = (function () {
            var counter = 0;
            return function () {return counter += 1;}
        })();
         
        add();
        add();
        add();
         
        // 计数器为 3
        
        // 变量 add 指定了函数自我调用的返回字值。
        
        // 自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
        
        // add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
        
        // 这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
        
        // 计数器受匿名函数的作用域保护,只能通过 add 方法修改。
      
    • 闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。

r += 1;}
})();

    add();
    add();
    add();
     
    // 计数器为 3
    
    // 变量 add 指定了函数自我调用的返回字值。
    
    // 自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
    
    // add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
    
    // 这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
    
    // 计数器受匿名函数的作用域保护,只能通过 add 方法修改。
    ```

- 闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。

- 直观的说就是形成一个不销毁的栈环境。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值