【JavaScript进阶之旅 函数式编程篇 第三十三章】JS函数、特点、函数式编程、纯函数

本文深入探讨JavaScript中函数作为一等公民的概念,展示了不同实现计算函数的方法,并讨论了JavaScript的编程特点,包括其混合了函数式和面向对象的特性。此外,文章还详细解释了函数式编程中的纯函数,通过实例说明了纯函数的定义、特点和重要性,以及如何编写和应用纯函数。最后,文章探讨了面向对象编程与函数式编程的关系,强调了函数式编程在易读性和维护性上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、JS函数

1、 函数的一等公民

JavaScript世界当中的 「一等公民」 -> 函数

  • JavaScript一等公民:声明、调用、赋值、传参、返回、构造函数、类实例、立即执行
  1. 第一级函数:First-class Function
function test() {}

var test = function() {}

2、计算函数的不同实现

  • 方法一
	function add(a, b) {
		return a + b;
	}

	function minus(a, b) {
		return a - b;
	}

	function compute(a, b, fn) {
		return fn(a, b);
	}

	console.log(compute(1, 2, add)); // 3
  • 方法二
	function Compute(a, b) {
		this.a = a;
		this.b = b;

		this.add = function() {
			return this.a + this.b;
		}

		this.minus = function() {
			return this.a - this.b;
		}
	}

	var computed = new Compute(1, 3);
	console.log(computed.add()); // 4
  • 方法三
	var test = (function() {
		function Compute(a, b) {
			this.a = a;
			this.b = b;

			this.add = function() {
				return this.a + this.b;
			}

			this.minus = function() {
				return this.a - this.b;
			}
		}

		return new Compute(10, 1);

	})();

	console.log(test.add()) // 11

3、JS编程特点

  • 函数式编程和面向对象编程的混编语言
  • 可扩展性强

优点:编程灵活、易学
缺点:不可控

4、面向对象与函数式编程关系

  • 面向对象中存在复杂的this指向,面向对象是需要大量的使用、大量的复用才有必要使用
  • 函数式编程:易读、易维护

二、函数式编程

  • 概念:函数是第一类对象,不依赖任何其他对象独立存在

1、纯函数

  • 相同的输入得到相同的输出,不依赖且不影响外部环境也不产生任何副作用

输出完全取决于输入

var a = 1;

function test(num) {
	console.log(num);
}

test(a); // 纯函数
  • 副作用:
    1. 只要跟函数外部环境发生了交互就是副作用
    2. 发送数据请求
    3. 改变数据
    4. console.log() 是Javascript引擎 控制台的方法
    5. DOM操作
    6. 数据的存取:cookie、storage

	function add(obj) {
		return obj.a + obj.b;
	}

	function minus(obj) {
		return obj.a - obj.b;
	}

	function compute(num) {
		return {
			add: add(num),
			minus: minus(num)
		}
	}

	var nums = {
		a: 1,
		b: 2
	}

	console.log(compute(nums).add);
	console.log(compute(nums).minus);

// 请问compute是纯函数吗?
// 他不是,因为compute依赖了外部函数,一旦外部函数发生错误,就影响到了compute
  • splice与slice
  • splice:改变原数组,不是纯函数
  • slice:返回新数组,不改变原数组,是纯函数
	var arr1 = [1, 2, 3, 4, 5],
			arr2 = [1, 2, 3, 4, 5];

	var spArr = arr1.splice(0, 3),
			slArr = arr2.slice(0, 3);

	console.log('arr1', arr1);
	console.log('arr2', arr2);

	console.log('spArr', spArr);
	console.log('slArr', slArr)

2、手写第一个纯函数

	var obj = {
		a: 1, 
		b: 2,
		c: 3
	}


	// 改变了原对象obj -> 所以他不是纯函数
	function test(obj) {
		obj.d = 4;
		return obj;
	}
	
	console.log(test(obj));
  • 深拷贝obj,那么test就是纯函数
// 函数test不可以影响obj

	var obj = {
		a: 1, 
		b: 2,
		c: 3
	}


	// 改变了原对象obj -> 所以他不是纯函数
	function test(obj) {
		// 深拷贝obj
		var newObj = deepClone(obj, {});
		console.log(newObj);

		newObj.d = 4;


		function deepClone(obj,cloneObj) {
			debugger
      var cloneObj = cloneObj || {},
          toStr = Object.prototype.toString,
          objArr = '[object Array]'

      for(var i in obj) {
        // console.log(obj[i]);
        // 判断i是不是自己的属性
        if(!obj.hasOwnProperty[i]) {
        	// i有可能在自己的原型上面
					if(typeof obj[i] === 'object' && obj[i] !== null){
			          // cloneObj[i] = Array.isArray(obj[i]) ? [] : {};
			          // cloneObj[i] = obj[i] instanceof Array ? [] : {};
			
			          cloneObj[i] = toStr.call(obj[i]) === Object ? [] : {}
			
			          deepClone(obj[i], cloneObj[i])
			          
	        }else {
	          cloneObj[i] = obj[i]
	        }
				} 

      }
      return cloneObj
    }


		return newObj;
	}

	console.log(test(obj));
 

3、纯函数的特点

可移植性
  • 拿到哪里都可以用
	function compute(a, b, type) {
		if(typeof(a) === 'number' && typeof(b) === 'number') {
			switch(type) {
				case 'add':
					return a + b;
					break;
				case 'minus':
					return a - b;
					break;
				default: 
					return a + b;

			}
		}else {
			return 'a跟b必须是数字';
		}
	}

	console.log(compute(1, 3, 'add'));

引用合理,透明性
function add(a, b) {
	return a + b;
}

// 或者

function add() {
	var a = 1,
			b =2;
	return a + b;
}
可缓存性
	function test(fn) {
		var cache = {}; // 缓冲池

		return function() {
			var args = JSON.stringify(arguments);

			cache[args] = cache[args]
				? cache[args] + '(来自缓冲池)'
				// : fn(arguments);
				: fn.apply(fn, arguments);

			return cache[args];
		}
	}

	// var add = test(function(arguments) {
	var add = test(function() {
		var argLen = arguments.length,
				item,
				res = 0;

		for(var i = 0; i < argLen; i ++) {
			item = arguments[i];
			res += item;
		}

		return res;
	});

	console.log(add(1, 3)); // 4
	console.log(add(1, 3)); // 4(来自缓冲池)
	console.log(add(1, 3)); // 4(来自缓冲池)(来自缓冲池)
	console.log(add(1, 4));	// 5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值