ES6规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,编程
那么函数内部就不能显式设定为严格模式,不然会报错数组
1. 参数的默认值app
ES6 容许为函数的参数设置默认值,即直接写在参数定义的后面函数式编程
函数不能有同名参数函数
let a = 1;
每次调用函数foo
,都会从新计算x + 1
,而不是默认p
等于 100优化
let x = 99; function foo(p = x + 1) { console.log(p); } foo(); // 100
x = 100; foo(); // 101
function log(x, y = 'World') { console.log(x, y); } log('Hello'); // Hello World
log('Hello', 'China'); // Hello China
log('Hello', ''); // Hello
function Point(x = 0, y = 0) { this.x = x; this.y = y; } const p = new Point(); console.log(p); // { x: 0, y: 0 }
返回没有指定默认值的参数个数this
3. 参数初始化做用域spa
一旦设置了参数的默认值,函数进行参数声明初始化时,参数会造成一个单独的做用域(context)。prototype
等到初始化结束,这个做用域就会消失。rest
这种语法行为,在不设置参数默认值时,是不会出现的。
参数初始化,实际上,执行的是 let 关键字声明
4. rest 多余 实参数组
...args x, ...args
...数组名 实参, 多余参数数组
实参列表,是一个真数组
用于获取函数的多余参数
push
方法的例子function push(arr, ...items) { items.forEach(function(item) { arr.push(item); console.log(item); }); }; var arr = []; push(arr, 1, 2, 3)
length
属性,不包括 rest 参数,由于 rest 参数表示 多余的实参列表console.log((function(a) {}).length); // 1
console.log((function(...a) {}).length); // 0
console.log((function(a, ...b) {}).length); // 1
5. 箭头函数 const func = () => {};
简化原来的 const func = function(){};
箭头函数 没有本身的显式原型属性,即 func.prototype = undefined;
箭头函数 不能做为构造函数使用,即不能 new 调用
箭头函数 的 this 指向最近的包裹函数的 this 一致,若是没有函数包裹,则 this 指向 window
箭头函数 可让 this
指向固定化,这种特性颇有利于封装回调函数
实际缘由是箭头函数根本没有本身的 this,致使内部的 this 就是外层代码块的 this。
正是由于它没有 this,因此也就不能用做构造函数
于箭头函数没有本身的 this,因此固然也就不能用call()、apply()、bind()这些方法去改变this的指向
其实箭头函数也没有 arguments
、super
、new.target
箭头函数的函数体内 不能够使用 arguments 对象,该对象在函数体内不存在。若是要用,能够用 rest 参数代替
不能够使用 yield 命令,所以箭头函数不能用做 Generator 函数
var handler = { id: '123456', init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: function(type) { console.log('Handling ' + type + ' for ' + this.id); } };
const func = (x) => {};
const func = x => {};
const func = x => { x += 1;};
const func = x => x+=1;
let getTempItem = id => ({ id: id, name: "Temp" });
// 正常函数写法
[1,2,3].map(function (x) { return x * x; }); // 箭头函数写法
[1,2,3].map(x => x * x);
rest 参数 与 箭头函数的结合使用
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]]
定义函数的方法,且该方法内部包括 this
const cat = { lives: 9, jumps: () => { this.lives--; // this 指向 window ,因此结果确定是有问题的 }; };
须要动态this
的时候,也不该使用箭头函数
var button = document.getElementById('press'); button.addEventListener('click', () => { this.classList.toggle('on'); });
6. 双冒号运算符——函数绑定运算符——"对象::函数(参数列表)"
背景:
箭头函数能够绑定 this 对象,大大减小了显式绑定 this 对象的写法(call、apply、bind)。
可是,箭头函数并不适用于全部场合,因此如今有一个提案,提出了“函数绑定”(function bind)运算符,
用来取代 call、apply、bind 调用箭头函数能够绑定 this 对象,大大减小了显式绑定 this 对象的写法(call、apply、bind)
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); };
函数调用 会在内存造成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。
若是在函数 A 的内部调用函数 B ,那么在 A 的调用帧上方,还会造成一个 B 的调用帧。
等到 B 运行结束,将结果返回到 A,B 的调用帧才会消失。若是函数 B 内部还调用函数 C,
那就还有一个 C 的调用帧,以此类推。全部的调用帧,就造成一个“调用栈”(call stack)
指某个函数的最后一步操做是调用另外一个函数
是函数式编程的一个重要概念
只在严格模式下开启,正常模式是无效的
function f(x){ return g(x); };
// 状况一
function f(x){ let y = g(x); return y; }; // 状况二
function f(x){ return g(x) + 1; }; // 状况三
function f(x){ g(x); };
即只保留内层函数的调用帧。若是全部函数都是尾调用,那么彻底能够作到每次执行时,调用帧只有一项,这将大大节省内存。
内层函数 若是用到了 外层函数 的变量
若是尾调用自身,就称为尾递归
递归很是耗费内存,由于须要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)
尾递归的实现: 每每须要改写 递归函数,确保最后一步只调用自身。
把全部用到的内部变量改写成函数的参数。
采用 ES6 的函数默认值
函数式编程有一个概念,叫作柯里化(currying),意思是: 将多参数的函数转换成单参数的形式。
function factorial(n, total) { if (n === 1){ return total; }; return factorial(n - 1, n * total); }; factorial(5, 1); // 120
function Fibonacci2 (n , ac1 = 1 , ac2 = 1) { if( n <= 1 ){ return ac2; }; return Fibonacci2 (n - 1, ac2, ac1 + ac2); } Fibonacci2(100); // 573147844013817200000
Fibonacci2(1000); // 7.0330367711422765e+208
Fibonacci2(10000); // Infinity
容许定义和调用时,尾部直接有一个逗号
函数参数与数组和对象的尾逗号规则,保持一致了
function clownsEverywhere(param1, param2, ) { /* ... */ } clownsEverywhere('foo', 'bar', );