要努力啊小汤!
当你的才华还不足以撑起你的野心时,你应该静下心学习!!!

函数

2020-10-29 09:35:19


函数的声明:

  1. 命令式声明:
    1 function print(s) {
    2   console.log(s);
    3 }
    4 //调用
    5 print()
  2. 变量赋值式声明:
    【匿名函数】
    var print = function(s) {
      console.log(s);
    };

    【构造函数】

    var add = new Function(
      'x',
      'y',
      'return x + y'
    );
    
    // 等同于
    function add(x, y) {
      return x + y;
    }

    【加上函数名,函数名只在函数内部有效,函数体外部失效】

    1 var print = function x(){
    2   console.log(typeof x);
    3 };
    4 
    5 x
    6 // ReferenceError: x is not defined
    7 
    8 print()
    9 // function

    var f = function f() {};
  3. 函数名的提升:
    命令声明函数,会将函数当做一个变量,相当于变量的声明;
    var 变量=function 变量(){}======重复声明了,所以报错


 

函数的属性和方法

  1. name属性:返回函数名

     承认自己菜吧!!!这特么就是一个传参,你墨迹了半天!!!
    test函数用了一个方法f.name;test(myFunc)值就是myFunc.name

  2. length属性:返回函数预期传入的参数个数
  3. toString()方法:返回一个函数源码的字符串

     

     


 

函数作用域

  1. 作用域:全局作用域+函数作用域(ES6块级作用域)
      变量存在的范围

    在其他区块中声明的都是全局变量(比如if(){})

  2. 函数内部的变量提升:
    和外部一样,在函数内部中,如果是其他区块声明一个变量,那这个变量就是在这个函数内部的一个全局变量

  3. 函数本身的作用域:

     

     f函数,return x();x函数输出的是变量a


 

 参数:允许省略

  1. 参数就是函数运行时候提供的外部数据,length属性是指函数预定的参数个数【function x(a,b,c){...}】
  2. 传递方式(传参)
  3. 同名参数:取最后出现的值
    function f(a, a) {
      console.log(a);
    }
    
    f(1, 2) // 2
    f(1)// undefined
  4. arguments对象:在函数体内读取所有的参数,只有在函数体内可以使用
    arguments[0]读取函数体第一个参数;
    严格模式下(在函数体内部使用'use strict'),argument对象和函数参数无关,不会影响到实际的函数内参数;
    arguments.length可以查看调用函数的时候带了几个参数;

    将arguments对象转为数组:
    创建一个变量,数组  变量或者方法添加  返回数组选定的元素  使用arguments对象 
    var
    args = Array.prototype.slice.call(arguments);
    创建一个数组,遍历arguments,输出元素到数组
    var args = []; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
    callee属性:调用函数自身;在严格模式禁用!

闭包:读取函数内部的变量,在函数的内部再定义一个函数,这个函数就是闭包;

外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题

  1.  函数f1的返回值就是函数f2,由于f2可以读取f1的内部变量,所以就可以在外部获得f1的内部变量了;
    函数f2
    function f1() {
      var n = 999;
      function f2() {
        console.log(n);
      }
      return f2;
    }
    
    var result = f1();
    result(); // 999
  2. 闭包的另一个用处,是封装对象的私有属性和私有方法
    function Person(name) {
      var _age;
      function setAge(n) {
        _age = n;
      }
      function getAge() {
        return _age;
      }
    
      return {
        name: name,
        getAge: getAge,
        setAge: setAge
      };
    }
    
    var p1 = Person('张三');
    p1.setAge(25);
    p1.getAge() // 25

     


函数立即调用:通常是对匿名函数这么做;
  目的:不必为函数命名,避免污染全局变量;形成一个作用域,封装一些外部无法读取的私有变量

  1. 函数名():print();
  2. 表达式: var f = function f() {}()
  3. 不要让function出现在行首【function出现在行首说明是语句,不是表达式】:
    (function(){ /* code */ }());
    // 或者
    (function(){ /* code */ })();

 


eval命令:接受字符串作为一个参数,并将字符串作为语句执行,命令里面不能是其他命令,否则报错

  1. 案例
    eval('var a = 1;');
    a // 1
  2. 如果字符串无法作为语句执行,那么报错
    eval('3x') // Uncaught SyntaxError: Invalid or unexpected token
  3. 如果参数不是字符串,那么会原样返回
    eval(123) // 123

     

不推荐使用,在当前作用域内注入代码,容易造成风险,修改当前作用域的变量值,

因此规定,使用eval命令的函数内部必须是严格模式下'use strict'使用

eval最常见的场合是解析 JSON 数据的字符串,不过正确的做法应该是使用原生的JSON.parse方法


 

eval别名调用:作用域是全局作用域,调用的是全局的变量

  1. 凡是使用别名的,内部一律是全局作用域,保证不影响代码的优化

 

eval是别名调用,所以即使它是在函数中,它的作用域还是全局作用域,因此输出的a为全局变量。这样的话,引擎就能确认e()不会对当前的函数作用域产生影响,优化的时候就可以把这一行排除掉。

 

posted on 2020-10-29 19:54  做一个有趣的妞儿  阅读(105)  评论(0)    收藏  举报