码迷,mamicode.com
首页 > 其他好文 > 详细

函数的扩展

时间:2017-08-30 23:44:34      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:ram   个数   contex   绑定   func   syn   大括号   同名   fine   

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

这里需要注意以下 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一次都没更新

函数的扩展

标签:ram   个数   contex   绑定   func   syn   大括号   同名   fine   

原文地址:http://www.cnblogs.com/rogerwu/p/7455734.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!