函数js原有的:

属性:arguments[]、caller(调用该函数的引用,注意与callee分别开,callee指的是调用函数本身经常在递归中出现)、length(形参个数)、prototype

方法:apply()、call()、bind()、toString()

函数的扩展:

  • 函数参数的默认值

    在es6之前不能给函数的参数给定默认值,一般会采用这样的方法:

function a(x,y){
if(typeof y === 'undefined'){
y = 'world';
}
console.log(x,y);
}

es6允许设置默认值,在解构的时候使用模式匹配

    

function log(x, y = 'World') {
console.log(x, y);
} log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
function foo({x, y = 5}) {
console.log(x, y);
} foo({}) // undefined, 5
foo({x: 1}) // 1, 5
foo({x: 1, y: 2}) // 1, 2
foo() // TypeError: Cannot read property 'x' of undefined
// 写法一:设置了参数对象的解构默认值,但是对象默认为空对象
function m1({x = 0, y = 0} = {}) {
return [x, y];
} // 写法二:设置了参数对象默认是一个不为空的对象
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
} m1() //[0,0]
m2() //[0,0]
m1({x:1}) //[1,0]
m2({x:1}) //[1,undefined]

如果设定了默认参数不在arguments的尾部则在引用函数的时候不能省略,可以用undefined代替

这时函数的length就不是全部的arguments的长度了,而是没有设定默认值的长度

函数作用域:一般而言函数作用域大于全局作用域,但是如果函数的参数为另一函数,则这个另一函数的作用域还是全局作用域

  • rest参数(...变量名)<=> arguments 用于获取函数多余的参数

rest是一个数组,arguments是一个类数组(对象)

rest只能是最后一个参数,length属性不包括rest参数

  • 扩展运算符(...)将一个数组转为用逗号分隔的参数序列

console.log(1, ...[2, 3, 4], 5)         // 1 2 3 4 5

可以代替apply方法,将数组转为参数

代替concat <=> [1,2,...[]]

生成数组:[a,...rest] = [1,2,3,4,5]; a= 1;rest = [2,3,4,5];

可以返回多个值,正常函数只能返回数组和对象,但是扩展运算符可以将数组转化

可以将字符串转为数组:[...'he'] = ['h','e'];

  • name:返回函数名,若为匿名函数则es5返回空字符串,es6返回赋给引用它的变量

构造函数返回函数实例

bind函数返回'bound'+name

  • 箭头函数‘=>’

var f = v => v;
等价于
var f = function(v) {
return v;
};
不需要参数或多个则:用()表示
执行部分不只有返回值,用{},但是如果返回值为对象则需要在外部加() // 正常函数写法
[1,2,3].map(function (x) {
return x * x;
}); // 箭头函数写法
[1,2,3].map(x => x * x);

使用箭头注意点:

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

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

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

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

没有参数的时候就调用外部函数的,同时这时的this也是外部的

  • 函数绑定'::'左边对象右边函数 <=>bind

foo::bar;    // 等同于    bar.bind(foo);
  • 尾调用优化

尾调用:某函数最后一步调用另一函数不一定要出现在函数尾部

调用帧:函数调用会在内存形成一个“调用记录”,保存调用位置和内部变量等信息

调用栈:如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。

尾调用优化:只保留内层函数的调用帧,节省内存

注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。

如下代码进行尾调用优化
function f() {
let m = 1;
let n = 2;
return g(m + n);
}
f(); // 等同于
function f() {
return g(3);
}
f(); // 等同于
g(3); 如下代码则不会
function addOne(a){
var one = 1;
function inner(b){
return b + one;
}
return inner(a);
}

尾递归:尾调用自身,不会发生栈溢出

递归非常耗内存,需要同时保存多个调用帧,解决方法:

法一: 确保最后一步只调用自己,把所有用到的内部变量改写成函数的参数

function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
} function factorial(n) {
return tailFactorial(n, 1);
} factorial(5) //

法二:采用ES6的函数默认值

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

尾调用优化只在严格模式下开启,正常模式是无效的。

因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

  • func.arguments:返回调用时函数的参数。
  • func.caller:返回调用当前函数的那个函数。
function restricted() {
"use strict";
restricted.caller; // 报错
restricted.arguments; // 报错
}
restricted();
  • 函数内部的最后一个参数可以有尾逗号

ES6入门之函数的扩展的更多相关文章

  1. ES6 入门系列 - 函数的扩展

    1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...

  2. ES6中对函数的扩展

    ES6一路扩展,字符串.数组.数值.对象无一“幸免”,ES6说要雨露均沾,函数也不能落下,今天,就来讲解ES6对函数的扩展. 参数的默认值 在开发中,给函数的参数指定默认值,是很普遍很常见的一个需求, ...

  3. ES6入门箭头函数

    箭头函数: 箭头函数可以与变量结构相结合(箭头函数返回对象的时候必须要在对象外边加()) 注意: 1️⃣函数体内的this是定义时所在的对象,而不是使用时的对象 2️⃣不可以当成构造函数,不可用new ...

  4. ES6学习笔记(6)----函数的扩展

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 函数的扩展 函数的默认值 : ES6可以为函数指定默认值 (1)指定默认值的两种方式 a.函数参 ...

  5. ES6入门——函数的扩展

    1.函数参数的默认值 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法.现在ES6可以为函数的参数添加默认值,简洁了许多. ES5 function show(a,b){ b = b ...

  6. 《ES6标准入门》(阮一峰)--8.函数的扩展

    1.函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log ...

  7. ES6新特性3:函数的扩展

    本文摘自ECMAScript6入门,转载请注明出处. 一.函数参数默认值 1. ES6允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') ...

  8. ES6 - Note3:数组、对象与函数的扩展

    一.数组的扩展,ES6在数组扩展了一些API,以实现更多的功能 1.Array.from:可以将类数组和可遍历的数据结构转换成真正的数组,如下所示 var a = { '0':1,'1':1,leng ...

  9. es6入门3--箭头函数与形参等属性的拓展

    对函数拓展兴趣更大一点,优先看,前面字符串后面再说,那些API居多,会使用能记住部分就好. 一.函数参数可以使用默认值 1.默认值生效条件 在变量的解构赋值就提到了,函数参数可以使用默认值了.正常我们 ...

随机推荐

  1. linux内核分析之fork()

    从一个比较有意思的题开始说起,最近要找工作无意间看到一个关于unix/linux中fork()的面试题: #include<sys/types.h> #include<stdio.h ...

  2. Careercup - Google面试题 - 5634470967246848

    2014-05-06 07:11 题目链接 原题: Find a shortest path ,) to (N,N), assume is destination, use memorization ...

  3. 01.JSP基础语法

        本章主要讲解Java Web与JSP的入门内容,适合有JSP或Java Web基础的读者学习. 1.Web应用与web.xml文件 (1)Java Web应用程序的结构     Java We ...

  4. ngcordova 监控网络制式改变

    ngcordova 监控网络制式改变 keywords cordova,phonegap,ionic,network,网络制式 API参考 http://ngcordova.com/docs/plug ...

  5. short-path problem (Spfa) 分类: ACM TYPE 2014-09-02 00:30 103人阅读 评论(0) 收藏

    #include <cstdio> #include <iostream> #include <cstring> #include <queue> #i ...

  6. phyreengine 3.12.0 安装遇到的问题

    发现他们文档都是旧的....略渣阿 需要安装vs2012 update4 vs2013update4 nvdia cg toolkits 3.1 以及 windows SDK 8.1 编译运行第一个s ...

  7. Java Api与HBase交互实例

    import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hb ...

  8. ubuntu安装后没有root密码

    新安装的ubuntu没有设置root密码,也就不能登录到root账户下.要想设置root密码需要在当前账户下输入sudo passwd,然后输入当前用户的密码,然后输入两次root的新密码,即可完成r ...

  9. C# 对动态编辑的一些学习笔记

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Comp ...

  10. PHP 使用 Redis

    PHP 使用 Redis 安装 开始在 PHP 中使用 Redis 前, 我们需要确保已经安装了 redis 服务及 PHP redis 驱动,且你的机器上能正常使用 PHP. 接下来让我们安装 PH ...