es6快速入门(3)--函数的扩展

来源:互联网 发布:电脑磁盘数据恢复 编辑:程序博客网 时间:2024/05/16 07:44

function

1、函数参数的默认值▲▲

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

function log(x, y = 'World') {  console.log(x, y);}log('Hello') // Hello Worldlog('Hello', 'China') // Hello Chinalog('Hello', '') // Hello

除了简洁,ES6 的写法还有两个好处:首先,阅读代码的人,可以立刻意识到哪些参数是可以省略的,不用查看函数体或文档;其次,有利于将来的代码优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行。

function foo(x = 5) {  let x = 1; // error  const x = 2; // error}

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

let x = 99;function foo(p = x + 1) {  console.log(p);}foo() // 100x = 100;foo() // 101

上面代码中,参数p的默认值是x + 1。这时,每次调用函数foo,都会重新计算x + 1,而不是默认p等于 100。

2、与解构赋值默认值结合使用

function foo({x, y = 5}) {  console.log(x, y);}foo({}) // undefined 5foo({x: 1}) // 1 5foo({x: 1, y: 2}) // 1 2foo() // TypeError: Cannot read property 'x' of undefined

3、参数默认值的位置

定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。

// 例一function f(x = 1, y) {  return [x, y];}f() // [1, undefined]f(2) // [2, undefined])f(, 1) // 报错f(undefined, 1) // [1, 1]// 例二function f(x, y = 5, z) {  return [x, y, z];}f() // [undefined, 5, undefined]f(1) // [1, 5, undefined]f(1, ,2) // 报错f(1, undefined, 2) // [1, 5, 2]

上面代码中,有默认值的参数都不是尾参数。这时,无法只省略该参数,而不省略它后面的参数,除非显式输入undefined。

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

上面代码中,x参数对应undefined,结果触发了默认值,y参数等于null,就没有触发默认值。

4、rest 参数▲▲

替代arguments对象

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

function add(...values) {  let sum = 0;  for (var val of values) {    sum += val;  }  return sum;}add(2, 5, 3) // 10

上面代码的add函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。

5、name属性

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

function foo() {}foo.name // "foo"

6、箭头函数▲▲▲

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

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

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

const isEven = n => n % 2 == 0;const square = n => n * n;

上面代码只用了两行,就定义了两个简单的工具函数。如果不用箭头函数,可能就要占用多行,而且还不如现在这样写醒目。

// 正常函数写法[1,2,3].map(function (x) {  return x * x;});// 箭头函数写法[1,2,3].map(x => x * x);

箭头函数的一个用处是简化回调函数。▲▲

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]]

上面是 rest 参数与箭头函数结合的例子。▲▲

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

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

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

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

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

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

var s3 = 30;function Timer() {  this.s1 = 10;  this.s2 = 20;  // 箭头函数  setInterval(() => console.log('s1:' + this.s1), 1000);    //s1:10  //箭头函数内this总是指向函数定义生效时所在的对象,即timer  // 普通函数  setInterval(function () {    console.log('s2:' + this.s2);    //s2:undefined       //this指向windowwindow没有s2这个属性    console.log('s3:' + this.s3);    //s3:30    //this指向windowwindow有s3这个属性  }, 1000);}let timer = new Timer();

如果是普通函数,执行时this应该指向全局对象window。▲▲
但是,箭头函数导致this总是指向函数定义生效时所在的对象,所以输出的是10。▲▲

7、双冒号运算符

箭头函数并不适用于所有场合。

函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

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);

8、尾调用

原创粉丝点击