Js函数的扩展

更新日期: 2019-07-17阅读: 2.4k标签: 函数

这篇文章主要介绍了函数的扩展,函数的扩展只要有三个方面:

参数的默认值
箭头函数
关于尾调用的优化


1:参数的默认值(会形成一个单独的作用域)

可以在直接定义函数的时候,定义好参数如果没传或者传错 undefined。

//解构的基本用法
//用法1:
function log(x, y = 'World') {
    console.log(x, y);
}

log('Hello');
//Hello World

log('Hello', 'China');
/* Hello China */

log('Hello', '');
/* Hello */

参数的默认值只有在没传时才会生效。
//用法2:
function week({ x, y = 5 }) {
    console.log(x, y);
}

week({});
/* undefined 5 */

week({x: 1});
/* 1 5 */

week({x: 1, y: 2});
/* 1 2 */

week();
/* TypeError: Cannot read property 'x' of undefined */

//用法3:
function week({x, y = 5} = {}) {
    console.log(x, y);
}

week();
/* undefined 5 */

解构和参数的默认值需要注意的点:

参数的变量已经默认声明,不能用let或const再次声明

 function week(x = 5) {
     let x = 1;
     const x = 2;
 }
 /* SyntaxError: Identifier 'x' has already been declared */

函数不能有同名参数,因为参数的变量已经默认声明所以不能再次声明

 function week(x, x, y = 1) {
     /* ... */
 }
 /* SyntaxError: Duplicate parameter name not allowed in this context */

参数默认值是惰性求值
当我们真正运算走这个函数的时候,它才会去处理默认的参数

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

参数默认值一般用于尾部,比如一个函数
length属性,也就是函数的name和let,返回没有指定默认值的参数个数

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

设置了参数的默认值,参数会形成一个单独的作用域

 var x = 1;
 function f(x, y = x) {
     console.log(y);
 }
 
 f(2);
 //2
 
 let x = 1;
 function f(y = x) {
     let x = 2;
     console.log(y);
 }
 
 f();
 //1

2:rest参数,只能有一个参数,部分场景可以替代argument、类似于argument。

比如一个函数的argument我们知道这是函数的参数,argument实际上是官方不推荐的一种用法。

  function add(...values) {
  let sum = 0;
  
  for (var val of values) {
      sum += val;
  }
  
  return sum;
  }
  
  add(2, 5, 3);
  /* 10 */
  
  function sortNumbers() {
      return Array.prototype.slice.call(arguments).sort();
  }
  
  const sortNumbers = (...numbers) => numbers.sort();

3:严格模式,在严格模式下,使用了默认值、解构赋值或者扩展不能使用严格模式。


4:name 返回函数名

function week() {}

week.name;

// "week" *

var f = function () {};

f.name // ""

// ES6

f.name // "f"


5:箭头函数

箭头函数主要的两点是:第一点它的this指向是在它当时定义所在的作用域,第二个是它没有一个作用域的提升。

// 单个参数 
var f = v => v;
var f = function (v) {
    return v;
};

// 多个参数 
var sum = (num1, num2) => num1 + num2;
var sum = function(num1, num2) {
    return num1 + num2;
};
   
// return,有两种场景,箭头函数里面直接写return
// 或者不写的话箭头函数就会默认把这个结果当成一个return。
// 也就是说当我们返回一个对象时,没有return语句的时候我们需要再对象外面再包一个括号
var sum = (num1, num2) => { return num1 + num2; }

// 1 返回对象
let getTempItem = id => { id: id, name: "Temp" };
// 2 Unexpected token :
let getTempItem = id => ({ id: id, name: "Temp" });

// 结合解构
const full = ({ first, last }) => first + ' ' + last;

// rest
const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5);
// [1,2,3,4,5] 

箭头函数使用的注意点:

函数体内的this对象指向定义时所在的对象而不是使用时所在的对象

 function week() {
     setTimeout(() => {
         console.log('id:', this.id);
     }, 100);
 }
 //定义全局id(使用时的所在id)
 var id = 21;
 //调用,改变了this的值
 week.call({ id: 42 });
 // 42
 
 function week() {
     return () => {
         return () => {
             return () => {
                 console.log('id:', this.id);
             };
         };
     };
 }
 //定义时的id=1,决定了它的作用域,因此下面的t1,t2,t3的输出结果均为1
 var f = week.call({id: 1});
 
 var t1 = f.call({id: 2})()();
 var t2 = f().call({id: 3})();
 var t3 = f()().call({id: 4});
 // 1 
 
 // 对象不构成作用域 
 const cat = {
     lives: 9,
     jumps: () => {
         this.lives--;
     }
 }
不可以当作构造函数,因为定义的时候是全局的
不可以使用argument对象,这是一个规定,需要使用rest来代替
不可以使用yield命令


6:尾调用

一般用于严格模式,也就是说在严格模式下面,ES6做了一个尾调用的优化;但是在非严格模式下虽然也可以使用尾调用,但是没有优化。

尾调用基本概念:最后一步是调用另一个函数,不适用于外部变量时只保留内层函数的调用帧(外部的变量不应该保存在return这个函数里面,也就是返回的return并不使用这个作用域)。

function f(x){
    return g(x);
}

7:尾递归(会有一个调用栈的堆积)

function factorial(n) {
    if (n === 1) return 1;
    return n * factorial(n - 1);
}

factorial(5);

// 尾递归
function factorial(n, total) {
    if (n === 1) return total;
    return factorial(n - 1, n * total);
}

factorial(5, 1)

8:函数参数的尾逗号,方便代码版本管理

func(
    'week',
    'month',
);

链接: https://fly63.com/article/detial/4771

JavaScript 函数式编程

我理解的 JavaScript 函数式编程,都认为属于函数式编程的范畴,只要他们是以函数作为主要载体的。

Js函数式编程,给你的代码增加一点点函数式编程的特性

给你的代码增加一点点函数式编程的特性,最近我对函数式编程非常感兴趣。这个概念让我着迷:应用数学来增强抽象性和强制纯粹性,以避免副作用,并实现代码的良好可复用性。同时,函数式编程非常复杂。

让我们来创建一个JavaScript Wait函数

Async/await以及它底层promises的应用正在猛烈地冲击着JS的世界。在大多数客户端和JS服务端平台的支持下,回调编程已经成为过去的事情。当然,基于回调的编程很丑陋的。

JavaScript函数创建的细节

如果你曾经了解或编写过JavaScript,你可能已经注意到定义函数的方法有两种。即便是对编程语言有更多经验的人也很难理解这些差异。在这篇博客的第一部分,我们将深入探讨函数声明和函数表达式之间的差异。

编写小而美函数的艺术

随着软件应用的复杂度不断上升,为了确保应用稳定且易拓展,代码质量就变的越来越重要。不幸的是,包括我在内的几乎每个开发者在职业生涯中都会面对质量很差的代码。这些代码通常有以下特征:

javascript回调函数的理解和使用方法(callback)

在js开发中,程序代码是从上而下一条线执行的,但有时候我们需要等待一个操作结束后,再进行下一步操作,这个时候就需要用到回调函数。 在js中,函数也是对象,确切地说:函数是用Function()构造函数创建的Function对象。

js调用函数的几种方法_ES5/ES6的函数调用方式

这篇文章主要介绍ES5中函数的4种调用,在ES5中函数内容的this指向和调用方法有关。以及ES6中函数的调用,使用箭头函数,其中箭头函数的this是和定义时有关和调用无关。

JavaScript中函数的三种定义方法

函数的三种定义方法分别是:函数定义语句、函数直接量表达式和Function()构造函数的方法,下面依次介绍这几种方法具体怎么实现,在实际编程中,Function()构造函数很少用到,前两中定义方法使用比较普遍。

js在excel的编写_excel支持使用JavaScript自定义函数编写

微软 称excel就实现面向开发者的功能,也就是说我们不仅可以全新定义的公式,还可以重新定义excel的内置函数,现在Excel自定义函数增加了使用 JavaScript 编写的支持,下面就简单介绍下如何使用js来编写excel自定义函数。

js中的立即执行函数的写法,立即执行函数作用是什么?

这篇文章主要讲解:js立即执行函数是什么?js使用立即执行函数有什么作用呢?js立即执行函数的写法有哪些?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!