文章目录
前言
此系列文章用于记录小萌新的ES6的学习经历如有什么错误或者不好的地方请各位大佬多多指教
一、函数闭包
1.1.函数闭包的基本概念
JavaScript采用词法作用域(lexical scoping)。
- 概念:简单说就是函数中嵌套函数,嵌套在这里面的函数叫做闭包函数,外面的函数叫做闭包环境
- 作用:通过闭包函数,可以访问到闭包函数所在局部作用域中的变量及参数
- 特点:闭包的特点或本质:将局部变量常驻内存,这既是它的优点也是它的缺点,使用不当还会造成内存泄漏
1.2.函数闭包的原理
{
var scope = "globle scope";
function checkscope() {
var scope = "local scope";
function f() {
return scope;
}
return f();
}
console.log(checkscope()); //local scope
}
{
var scope = "globle scope";
function checkscope() {
var scope = "local scope";
function f() {
return scope;
}
return f;
}
var ff = checkscope();
console.log(ff()); //local scope
}
分析这两端代码它们可以捕捉到局部变量(和参数),并一直保存下来,看起来像这些变量绑定到了在其中定义它们的外部函数。
闭包的原理:
- 每次调用JavaScript函数的时候,都会为之创建一个新的对象
(活动对象Activation Object)
用来保存局部变量,把这个对象添加至作用域链中。 - 闭包是利用JS中的垃圾回收机制,当一个函数被调用时,会开辟空间,函数调用结束,会释放空间,但如果被释放空间时,发现其中有变量正在被其他函数使用时,则这个变量会常驻内存而不被回收
二、函数式编程
2.1.高阶函数
在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:(1)接受一个或多个函数作为输入;(2)输出一个函数;
如Array
对象中的forEach()
和map()
方法.
2.2.函数的链式调用
在设计函数(作为对象方法)返回值时,将处理后的当前对象(上下文)返回,以便进行紧凑的方法调用
2.3.call(),apply(),bind()
这三个方法的作用是什么?
- 我认为它们的作用可以用一句话来描述:就是改变this的指向。或者说 强行用其他对象来调用一个函数。
代码如下(示例):
{
function show(sex){
console.log("姓名为"+this.yourname+",性别为"+sex);
}
var person={
yourname:"张三",
age:14
};
show.call(person,"男");//姓名为张三,性别为男
show("男");//姓名为undefined,性别为男
person.show("男");//报错
}
在上面的代码块中,我们可以看到person对象并没有show方法,直接地用person.show()会报错。但是我们可以通过call方法来实现person对象来调用show方法。所以这种情况我认为就是改变了this的指向。
call,apply和bind的区别
它们在功能上是没有区别的,都是改变this的指向,它们的区别主要是在于方法的实现形式和参数传递上的不同
- 函数.call(对象,arg1,arg2…)
- 函数.apply(对象,[arg1,arg2,…])
- 函数.bind(对象,arg1,arg2,…)() 注:bind返回的是一个函数体,并不会直接执行函数
代码如下(示例):
{
function show(sex){
console.log("姓名为"+this.yourname+",性别为"+sex);
}
var person={
yourname:"张三",
age:14
};
show.call(person,"男");//姓名为张三,性别为男
show.apply(person,['女']);//姓名为张三,性别为女
show.bind(person,"未知")();//姓名为张三,性别为未知
}
通过观察上面的代码,很明显的就可以得出它们三者的区别,仅仅是函数传递的不同以及bind方法可以更加的方便的使用。
2.4.偏函数
在设计函数(作为对象方法)返回值时,将处理后的当前对象(上下文)返回,以便进行紧凑的方法调用
代码如下(示例):
{
let sum = function (x, y) {
return x + y;
};
let succ = sum.bind(null, 1);
// succ被称为偏函数
console.log(succ(2));
}
偏函数的好处
- 通过创建一个名称易懂的独立函数,调用是无需每次传入第一个参数,因为第一个参数通过bind提供了固定值。
- 当有一个很通用的函数,为了方便提供一个较常用的变体。
- 例如:有函数send(from, to, text),可以创建一个针对当前用户的send函数的变体:sendTo(to, text)。
2.5.函数柯里化
函数柯里化就是利用函数闭包对函数进行一个一个参数的传递调用。
代码如下(示例):
{
let sum = function (x, y) {
return x + y;
};
let succ = sum.bind(null, 1);
// succ被称为偏函数
console.log(succ(2));
}
高级函数柯里化针对n个参数的情况
代码如下(示例):
{
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function pass(...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}
function sum(a, b, c) {
return a + b + c;
}
let curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); //6
console.log(curriedSum(1)(2, 3)); //6
console.log(curriedSum(1)); //[Function: pass]
}
利用函数curry进行函数柯里化的创建,在你自己的函数进行调用时可以进行多个参数一个一个的传递执行。
总结
本文主要讲述了ES6中的函数式编程方面如果又不好的地方希望大家多多提意见。