Es6 函数的扩展

2018-07-05  本文已影响0人  CodeGod007

1.函数的默认值

function fn(x,y){
    y=y||'world'
}
fn('Hello') // Hello World
fn('Hello', 'China') // Hello China
fn('Hello', '') // Hello World
function fn(x=0,y=10){
     return x+y
}
fn() // 0
fn(10) // 20
fn(10,20) // 30
function fn(x){
    let x=10;
}
//error

上面代码中,参数变量x是默认声明的,在函数体中,不能用let或const再次声明,否则会报错。

function fn(x,x,y){
}

上边的代码不会报错,因为并没有设置默认值,但是第二个的x的值会覆盖第一个x

function fn(x=5,x,y=10){
//error
}

let x= 10;
function fn (x,y=x){ 
    console.log(y)
}
fn(1) // 1

上面代码中,参数y的默认值等于变量x。调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。

let x = 1;

function fn(y = x) {
  let x = 2;
  console.log(y);
}

fn() // 1

在上边的代码中,虽然函数里有变量x,但是这个作用域是在函数声明初始化的时候形成的,所以里边里边的x指向全局的x.

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // ReferenceError: x is not defined

报错是因为在全局中没有找到全局变量x

var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: x is not defined

上面代码中,参数x = x形成一个单独作用域。实际执行的是let x = x,由于暂时性死区的原因,这行代码会报错”x 未定义“。

2.rest参数

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

function add(...values) {
  let sum = 0;

  for(var i = 0;i < values.length;i++){
    num+=values[i]
  }

  return sum;
}

add(2, 5, 3) // 10
function fn(x,...values,y){
}
//error
function fn(x,y=2,...values){

}
console.log(fn.length)

3.严格模式

从 ES5 开始,函数内部可以设定为严格模式 , ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。

下边是报错的一些例子:

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

// 使用啦参数设置默认值报错
const a= function ({a, b}) {
  'use strict';
  // code
};

// 使用啦解构赋值报错
const a= (...a) => {
  'use strict';
  // code
};
// 报错
function doSomething(value = 070) {
  'use strict';
  return value;
}

上面代码中,参数value的默认值是八进制数070,但是严格模式下不能用前缀0表示八进制,所以应该报错。但是实际上,JavaScript 引擎会先成功执行value = 070,然后进入函数体内部,发现需要用严格模式执行,这时才会报错。

解决办法
1.设置全局的严格模式

'use strict';

function a(a, b = a) {
  // code
}

2.套在一个无参数的自执行函数里

let a =(function(){
      'use strict';
    retuen function (x=2,y){
        console.log(x,y)
    }
}())

4.name 属性

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

// ES5
f.name // ""

// ES6
f.name // "f"
var a = function fn(){
 
};
//Es5
console.log(a.name) // fn
//Es6
console.log(a.name) // fn
(new Function).name // "anonymous"

5.Es6允许使用“箭头”(=>)定义函数。

var f = v => 1;
f() //1
// v 函数的形参, 1 函数的实参和返回值
var f = () => 5;
// 等同于
var f = function () { return 5 };

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

//报错
let obj= id => { id: id, name: "Temp" };
//不报错
let obj= id => ({ id: id, name: "Temp" });
 var f = ({name,age}) => name+' '+age
 f({name:'suo',age:28}) //"suo 20"

箭头函数使用注意事项

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

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。

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

6.双冒号运算符

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

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

7尾调用

情况一 : 调用之后有操作;
情况二 : 调用之后有操作;
情况三 : function(){g(x) return undefined;};

上一篇 下一篇

猜你喜欢

热点阅读