zoukankan      html  css  js  c++  java
  • 函数的扩展

    1、函数参数的默认值

    es6 之前不能直接为函数的参数指定默认值,只能采用变通方法

    function fun (x, y) {
        y = y || 'world'
        console.log( x ,y)
    }
    
    fun ('hello')   // hello world
    fun ('hello', 'china')  // hello china
    fun ('hello', '')  // hello world

    以上代码的缺陷在于,当参数 y 所赋值的类型为 false时,该赋值不起作用,就像 y 赋值为空字符,结果被改成了 'world'

    为了避免这个问题,通常需要先判断一下参数y是否被赋值,如果没有,再等于默认值

    if (typeof y === 'undefined') {
      y = 'World';
    }

    es6 允许为函数的参数设置默认值,直接写在参数定义的后面

    function test(x, y = 'world'){
        console.log('默认值',x,y);
      }
      test('hello');   // 默认值 hello world
      test('hello','kill');  // 默认值 hello kill
        test('hello', false) // es6 参数默认值: hello, false
        test('hello', '') // es6 参数默认值: hello,
        test('hello', undefined) // es6 参数默认值: hello, world
        test('hello', null) // es6 参数默认值: hello, null




    这里需要注意以下 4点

    (1)、参数变量是默认声明的,所以不能用let或const再次声明

    function foo(x = 5) {
      let x = 1; 
    }
    foo ()   // Uncaught SyntaxError: Identifier 'x' has already been declared

    (2)、使用参数默认值时,函数不能有同名参数

    // 不报错
    function foo(x, x, y) {
      // ...
    }
    
    // 报错
    function foo(x, x, y = 1) {
      // ...
    }
    // SyntaxError: Duplicate parameter name not allowed in this context

    (3)、参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值的

    let x='test';
    function test2(x,y=x){
       console.log(x,y);   // x = test or x = kill
    }
     test2('kill');   // kill kill

    (4)、如果传入undefined,将触发该参数等于默认值,null则没有这个效果

    function foo(x = 5, y = 6) {
      console.log(x, y);
    }
    
    foo(undefined, null)   // 5 null

    2、rest 参数

    rest 参数(形式为 ...arg),用于获取函数多余的参数,存放到数组中

    function test3(...arg){
        for(let v of arg){
          console.log('rest',v);
        }
      }
      test3(1,2,3,4,'a');
    
    // rest 1
    // rest 2
    // rest 3
    // rest 4
    // rest a

    再来看一个给类数组对象排序的例子

    // es5
    function sortNumbers() {
      return Array.prototype.slice.call(arguments).sort();
    }
    
    // es6
    const sortNumbers = (...numbers) => numbers.sort();

    rest 参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。下面是一个利用 rest 参数改写数组push方法的例子

    function push(array, ...items) {
      items.forEach(function(item) {
        array.push(item);
        console.log(item);
      });
    }
    
    var a = [];
    push(a, 1, 2, 3)  // 1 2 3

    注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错

    // 报错
    function f(a, ...b, c) {
      // ...
    }

    函数的length属性,不包括 rest 参数

    (function(a) {}).length  // 1
    (function(...a) {}).length  // 0
    (function(a, ...b) {}).length  // 1

    3、箭头函数

    es6 允许使用“箭头”(=>)定义函数

    let arrow = v => v*2
    
    // 等同于
    function arrow (v) {
        return v*2
    }
    
    let arrow2 = () => 5
    // 等同于
    function arrow2 () {
        return 5
    }

    如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回

    var sum = (num1, num2) => { return num1 + num2; }

    由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号

    var getTempItem = id => ({ id: id, name: "Temp" })

    箭头函数可以与变量解构结合使用

    const full = ({ first, last }) => first + ' ' + last;
    
    // 等同于
    function full(person) {
      return person.first + ' ' + person.last;
    }

    箭头函数有几个使用注意点。

    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

    (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误

    (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替

    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数

    上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的

    function foo() {
      setTimeout(() => {
        console.log('id:', this.id);
      }, 100);
    }
    
    var id = 21;
    
    foo.call({ id: 42 });   // id: 42

    箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子

    function Timer() {
      this.s1 = 0;
      this.s2 = 0;
      // 箭头函数
      setInterval(() => this.s1++, 1000);
      // 普通函数
      setInterval(function () {
        this.s2++;
      }, 1000);
    }
    
    var timer = new Timer();
    
    setTimeout(() => console.log('s1: ', timer.s1), 3100);   // s1:  3
    setTimeout(() => console.log('s2: ', timer.s2), 3100);   // s2:  0

    上面代码中,Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(即Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100毫秒之后,timer.s1被更新了3次,而timer.s2一次都没更新

  • 相关阅读:
    Tool工具页面代码
    Tool工具生成代码数据库Model生成代码
    类别切换 分页
    ASP.NET AJAX无刷新验证用户名
    VSS的配置和使用
    js 常用方法大全
    灵异——1995年北京330路公交车失踪案
    C#用HttpWebRequest通过代理服务器验证后抓取网页内容 。。。。。
    win2003远程 客户端无法连接到远程计算机。
    .net中点击button按钮显示下一条记录(上一条 下一条)
  • 原文地址:https://www.cnblogs.com/rogerwu/p/7455734.html
Copyright © 2011-2022 走看看