ES —(函数扩展)

1)函数参数的默认值

  ES6 之前,不能直接为函数的参数指定默认值。只能采用变通的方法,即在函数体内部通过判断来赋默认值。
  ES6 允许为函数的参数设置默认值(可以是值,也可以是表达式),即直接写在参数定义的后面。

 function foo (x = 0, y = 0){}

注意:
  (1)使用参数默认值时,函数不能有同名参数。

 function foo (x, x, y = 1){} //报错

  (2)参数默认值不是传值的,而是每次调用函数时重新计算默认值。

 let x = 1;
 function foo (y = x + 1){
    console.log(y);
 }
 foo(); // y => 2
 x = 2;
 foo(); // y => 3;

  (3)参数默认值可以与解构赋值的默认值,结合起来使用。详见解构赋值
  (4)通常情况下,定义了默认的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了那些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。

 function foo (x = 1, y) {}
 foo(); // x => 1, y => undefined
 foo(2); // x => 2, y => undefined
 foo(,2); // 报错
 foo(null,2); // x => null, y => 2
 foo(undefined,2); // x => 1, y => 2

  (5)指定了默认值后,函数的 length 属性,将返回没有指定默认值的参数个数,也就是说,指定了默认值后,length属性将失真。 length 属性忽略默认值后面的参数以及 rest 参数。

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

  (6)一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域。默认值表达式计算时变量遵循作用域链。

let x = 1;
function f(y = x) { let x = 2;}
f(); // y => 1;

上面代码中,参数 y = x 形成了一个单独的作用域。这个作用域里面,变量 x 本身没有定义,所以指向外层的全局变量 x。函数调用时,函数体内部的局部变量 x 影响不到默认变量x。若外层未定义 x 则报错。

let x = 1;
function f(x = x) {} 
f(); // 报错,参数 x = x 为一个单独作用域,
     //实际执行 let x = x ,由于暂时性死区原因,报错: x 未定义。

2)rest参数

  ES6引入 rest 参数(形式为 ...变量名),用于获取函数的多余参数,这样就不需要使用 arguments 对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

function f(...values){}
f(1,2,3);

  rest 参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。
注意:rest 参数后面不能再有其他参数(即 rest 参数为最后一个参数),否则会报错。
   函数的 length 属性,不包括 rest 参数。

3)严格模式

  ES2016 规定只要函数参数使用了默认值、解构赋值、或者扩展运算,那么函数内部就不能显式设定为严格模式(use strict),否则会报错。

4)name属性

  函数的 name 属性,返回该函数的函数名。 Function构造函数返回的函数实例, name 属性的值为 anonymousbind 返回的函数, name 属性会加上 bound 前缀。

function foo(){}    foo.name => "foo"
var f = function (){}   f.name => "f"
var f = function baz(){}  f.name => "baz"
(new Function).name => "anonymous" 
function foo(){}
foo.bind({}).name => "bound foo"

5)箭头函数

  ES6 允许使用“箭头”(=>)定义函数。如果箭头函数不需要参数或者需要多个参数,使用圆括号代表参数部分。如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用 return 语句返回。

var f = v => v;
var f = () => s;
var f = (num1,num2) => num1 + num2;
var f = (num1,num2) => {return num1 + num2;}

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

var get = id => ({id : id, name : 'get'});

  (2)箭头函数体内的 this 对象,就是定义使所在的对象,而不是使用时所在的对象。this 指向的固定化,并不是箭头函数内部有绑定 this 的机制,实际原因是箭头函数根本没有自己的 this 对象,导致内部的 this 就是外层代码块的 this。由于箭头函数没有自己的 this ,所以也就不能用 callapplybind 这些方法去改变 this 的指向。

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id); // this 指向最外层的foo函数的对象{id: 1}
      };
    };
  };
}

var f = foo.call({id: 1});  // 给foo指定对象{id: 1}
// 以下如何给 f 指定对象,箭头函数内部 this 对象不会改变。
// 因为 f 是一个箭头函数,该函数的对象指向 foo 。
var t1 = f.call({id: 2})()(); // id: 1 
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1    
---------------------------------------------------------------------------
(function() {
   return [
      (() => this.x).bind({ x: 'inner' })() // bind无效
    ];
}).call({ x: 'outer' }); // ['outer']

  (3)不可以当做构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误。,这是因为箭头函数没有 this,所以也就不能用作构造函数。
  (4)除了 this ,以下三个变量在箭头函数中也是不存在的,argumentssuppernew.target ,它们都指向外层函数的对应变量。

function foo(){
    setTime(() => {
                console.log("args:", arguments);
            },100);
}
foo(2,3,4,5); // args:[2,3,4,5]

  (5)不可以使用 yield 命令,因此函数不能用作 Generator 函数。
  (6)箭头函数内部,还可以再使用箭头函数,即嵌套的箭头函数。

阮一峰:ECMAScript 6入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值