笔记索引
声明
1 2 3 4 5 6 7 8 9 10 11 12
| var x = function (a) { alert(a); };
function y(a) { alert(a); }
new Function(arguments, functionBody);
|
调用
可以任意传参,注意参数类型
可以默认传参
另有 argument 代表所有传入参数,类似数组
1 2 3 4
| function z(a = 12, b, ...rest) { rest; arguments[0]; }
|
对象方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| var xiaoming = { age: function () { var y = new Date().getFullYear(); return y - this.birth; }, };
y.apply(对象, [参数1, 参数2]); y.call(对象, 参数1, 参数2); y.bind(对象, 参数1, 参数2);
|
对象 getter & setter
在对象内定义 getter setter 函数
每次访问、修改都会触发相应函数
1 2 3 4 5 6 7 8
| const obj = { get getter() { return "getter"; }, set setter() { return "setter"; }, };
|
一种装饰器
1 2 3 4 5 6 7
| var count = 0; var oldParseInt = parseInt;
window.parseInt = function () { count += 1; return oldParseInt.apply(null, arguments); };
|
高阶函数
接受函数作为参数的函数
1 2 3 4 5
| let arr = [1, 2, 3, 5, 9, 0]; arr.map(x); arr.reduce(x); arr.filter(z); arr.sort(y);
|
另外的高阶函数:
every()
判断数组的所有元素是否满足测试条件,
find()
查找返回符合条件的第一个元素,否则返回 undefined
findIndex()
返回第一个找到元素的位置
forEach()
把每个元素依次作用于传入的函数,但不会返回新的数组,用于遍历
箭头函数
其实就是匿名函数
使得 apply() 方法的第一个参数始终指向相应对象
没有 this、arguments,如果能调用,一定来自父级函数作用域
1 2 3 4 5
| var Power2 = (argu) => x _ x;
var Power2 = function (argu) { return argu _ argu; };
|
如果想要返回对象
创建一个匿名函数并立刻执行
1 2 3
| ((i) => { console.log(i); })(i);
|
对于创建匿名函数并即刻运行也可以使用声明式,+ 可以换为其他运算符
1 2 3
| (function name(params) { console.log(params); })(params);
|
生成器
生成可迭代对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| function* fib(max) { (a = 0), (b = 1), (n = 0); while (n < max) { yield a; yield* [1, 2, 3]; [a, b] = [b, a + b]; n++; } return; }
new GeneratorFunction(arguments, functionBody);
|
异步函数
async function name([param[, param[, ... param]]]) { statements }
可以结合 Promise 使用
返回的 Promise 对象会运行执行(resolve)异步函数的返回结果,或者运行拒绝(reject)
跨浏览器性能注意
1 2 3 4 5 6 7 8
| async function async() {} async () => {};
async function async() { return await 20; }
|
链式回调重写
从
1 2 3 4 5 6 7 8 9
| function getProcessedData(url) { return downloadData(url) .catch((e) => { return downloadFallbackData(url); }) .then((v) => { return processDataInWorker(v); }); }
|
到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| async function getProcessedData(url) { let v; try { v = await downloadData(url); } catch (error) { v = await downloadFallbackData(url); } return processDataInWorker(v); }
var parallel = async function () { await Promise.all([ (async () => { return console.log(await resolveAfter2Seconds()); })(), (async () => { return console.log(await resolveAfter1Second()); })(), ]); };
|
闭包
- 在一个内部函数中对外部作用域的变量进行引用,内部函数即形成闭包
- 闭包可以使函数有 固定 的 “私有环境”,外部无法访问
- 高阶函数返回值是一个函数,可以返回闭包
1 2 3 4 5 6 7 8 9
| function generateClosure() { let x = 1; return function f() { return x; }; } let closure = generateClosure();
|
循环闭包
1 2 3 4 5 6 7 8 9 10 11
| function generateFunctions() { let f_list = []; for (var i = 0; i < 5; i++) { function f() { return i; } f_list.push(f); } return f_list; } f_list = generateAnotherClosure();
|
f_list[0]()
直到 f_list[4]()
都返回 5,而不是 0、1、2、3、4,f 内的 i 是在 for 结束时确定的,所以为 5
闭包解决,创建一个函数并执行形成闭包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function generateFunctionsWithClosure() { let f_list = []; for (var i = 0; i < 5; i++) { function g(i) { return function f() { return i; }; } f_list.push(g(i)); } return f_list; } f_list = generateFunctionsWithClosure();
|
不过,闭包对性能不友好
let
如果不使用闭包,可以用 let 解决,使每个块有自己的作用域
1 2 3 4 5 6
| for (var i = 0; i < 5; i++) { let item = i; setTimeout(function () { console.log(item); }, 1000 _ i); }
|
同样地:
1 2 3 4 5
| for (let i = 0; i < 5; i++) { setTimeout(function () { console.log(item); }, 1000 \_ i); }
|