zoukankan      html  css  js  c++  java
  • ES6新语法之---函数扩展(7)

    这节学习ES6中对函数新增的方法和属性。

    1.新增函数的参数默认值

    参考S6系列第二篇:http://www.cnblogs.com/diweikang/p/8976854.html

    2.新增了函数的rest参数

    参考ES6系列第二篇:http://www.cnblogs.com/diweikang/p/8976854.html

    3.length属性

      作用:获取函数预期传入的参数个数。

      指定默认值后,length属性将返回没有指定默认值参数的个数。

        (function (a) {}).length // 1
        (function (a = 5) {}).length // 0
        (function (a, b, c = 5) {}).length // 2

      注意:如果设置了默认值的参数不是尾参数,length属性也不再计入后面的参数。

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

    4.严格模式

      严格模式是ES5中新增语法的,限制指定的代码在更严格的模式下执行。通常在脚本开头或函数头部添加"use strict"表达式来声明。

      <1>ES5开始,函数内部可以显示声明严格模式。

        function doSomething(a, b) {
          'use strict';
          // ...
        }

      ES2016中规定,只要函数中使用了参数默认值、解构赋值、或者扩展运算符,函数内部就不允许显示声明严格模式,否则报错。

        // 参数默认值
        function doSomething(a, b = a) {
             'use strict';
              // code
        }
    
        // 解构赋值
        const doSomething = function ({a, b}) {
          'use strict';
          // code
        };
    
        // 扩展运算符
        const doSomething = (...a) => {
          'use strict';
          // code
        };
    
        const obj = {
          // 解构赋值
          doSomething({a, b}) {
            'use strict';
            // code
          }
        };

      规定原因:函数内部声明的严格模式,限制函数参数和函数体都必须是严格模式执行。只有执行函数体的时候才能知道函数是否是严格模式,但是函数时先执行函数参数,再执行函数体的。这就导致参数如果不遵守严格模式,函数体中又显示声明严格模式,函数进行就会报错。

        // 严格模式八进制使用0o前缀表示
        function doSomething(value = 070) {
          'use strict';
          return value;
        }

      上面函数执行就会报错。

      如何规避这种限制:

        <1>、设定全局性的严格模式。

        'use strict';
    
        function doSomething(a, b = a) {
          // ...
        }

        <2>、把函数包装在一个无参数的立即执行函数里面。

        const doSomething = (function () {
          'use strict';
          return function(value = 42) {
            return value;
          };
        }());

    5.name属性

      ES6新增函数的name属性,返回该函数的函数名。

      <1>将一个匿名函数赋值给一个变量,ES5的name属性会返回空字符创,ES6的name属性会返回实际的函数名称。

        var f = function () {};
        // ES5
        f.name // ""
        // ES6
        f.name // "f"

      <2>将一个具名函数赋值给一个变量,ES5和ES6的name属性都会返回这个具名函数的名称。

        const bar = function baz() {};
        // ES5
        bar.name // "baz"
        // ES6
        bar.name // "baz"

      <3>构造函数返回的函数实例,name属性值为anonymous

        (new Function).name // "anonymous"

      <4>将bind返回的函数,name属性值会加上bound前缀。

        function foo() {};
        foo.bind({}).name // "bound foo"
    
        (function(){}).bind({}).name // "bound "

    6.箭头函数

      ES6允许使用"箭头"(=>)定义函数。

      <1>箭头函数需要一个参数

        var f = v => v;
    
        // 等同于
        var f = function (v) {
          return v;
        };

      <2>箭头函数不需要或者需要多个参数,使用括号将参数部分括起来。

        var f = () => 5;
        // 等同于
        var f = function () { return 5 };
    
        var sum = (num1, num2) => num1 + num2;
        // 等同于
        var sum = function(num1, num2) {
          return num1 + num2;
        };

      <3>箭头函数代码块多余一条语句,就要使用大括号括起来,并使用return语句返回。

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

      <4>如果箭头函数需要返回一个对象对象外面需要小括号括起来,否则会被当成代码块返回。

        // 报错
        let getTempItem = id => { id: id, name: "Temp" };
    
        // 不报错
        let getTempItem = id => ({ id: id, name: "Temp" });

      <5>如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法。

        let fn = () => void doesNotReturn();

      <6>箭头函数与变量解构结合使用。

        const full = ({ first, last }) => first + ' ' + last;
    
        // 等同于
        function full(person) {
          return person.first + ' ' + person.last;
        }
        const numbers = (...nums) => nums;
    
        numbers(1, 2, 3, 4, 5)
        // [1,2,3,4,5]
    
        const headAndTail = (head, ...tail) => [head, tail];
    
        headAndTail(1, 2, 3, 4, 5)
        // [1,[2,3,4,5]]

      <8>箭头函数中的this对象。

      注意:箭头函数中的this总是指向函数定义生效时所在的对象。

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

      上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42

      再看一个例子:

        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);
        setTimeout(() => console.log('s2: ', timer.s2), 3100);
        // s1: 3
        // s2: 0

      分析:箭头函数中的this指向箭头函数定义生效时所在的对象,第一个定时器中的this指向timer对象,第二个定时器指向调用它的对象(全局对象),3100ms后s1更新了3次,而s2并没有更新,所以结果是3和0。

      总结:箭头函数没有自身的this对象。

        1.函数体中this对象,定义时所在的对象,不是函数调用时所在对象。

        2.不可以当构造函数,也就是不可以使用new命令。

        3.不可以使用arguments对象,该对象在箭头函数体内不存在。

      <9>双冒号运算符

      ES6中提出使用双冒号(::)函数绑定的运算符,替代call、apply、bind调用。

      双冒号左边是一个对象,右边是一个方法,表示将右边的函数绑定到左边的对象上。

        foo::bar;
        // 等同于
        bar.bind(foo);
        
        foo::bar(...arguments);
        // 等同于
        bar.apply(foo, arguments);
    
        const hasOwnProperty = Object.prototype.hasOwnProperty;
        function hasOwn(obj, key) {
          return obj::hasOwnProperty(key);
        }

      双冒号左边为空,右边是一个对象的方法,表示将函数绑定到这个对象上。

        var method = obj::obj.foo;
        // 等同于
        var method = ::obj.foo;
    
        let log = ::console.log;
        // 等同于
        var log = console.log.bind(console);

    总结:

      上面这些就是我们在开发中,可能会用到的ES6中关于函数的扩展的属性和方法,还是需要多练习多理解。

      

  • 相关阅读:
    搜狗图片抓取,主要以图集类进行抓取
    使用mongo进行去重操作
    爬虫实战01_淘宝模拟登录
    Linux常用命令02(远程管理)
    Linux常用命令01(文件和目录)
    Linux终端命令格式
    常用Linux命令的基本使用
    闭包与私有变量
    三栏布局的几种方法
    redux和react-redux小记
  • 原文地址:https://www.cnblogs.com/diweikang/p/9388321.html
Copyright © 2011-2022 走看看