搜索
首页web前端js教程Javascript函数式编程简单介绍_javascript技巧

几十年来,函数式编程一直是计算机科学狂热者的至爱,由于数学的纯洁性和谜一般的本质, 它被埋藏在计算机实验室,只有数据学家和有希望获得博士学位的人士使用。但是现在,它正经历一场复兴, 这要感谢一些现代语言比如Python,Julia,Ruby,Clojure以及——但不是最后一个——Javascript。

你是说Javascript?这个WEB脚本语言?没错!

Javascript已经被证明是一项长期以来都没有消失的重要的技术。这主要是由于它扩展的一些框架和库而使其具有重生的能力, 比如backbone.js,jQuery,Dojo,underscore.js等等。这与Javascript函数式编程语言的真实身份直接相关。 对Javascript函数式编程的理解很重要,并且在相当长的一段时间会对各种水平的程序员很有用。

为什么呢?函数式编程非常强大、健壮并且优雅。它对于大型数据结构非常有用并且高效。 Javascript作为一个客户端脚本语言,在应对日益复杂的网站时,函数式地操作DOM、 组织API响应以及完成一些其它任务会非常有好处。

在这本书里,你将会学习用Javascript进行函数式编程所需要知道的一切:如何用函数式编程构建你的Javascript web应用, 如何解锁Javascript隐藏的力量,如何编写更强大的代码,并且由于程序更小,使得代码更容易维护,能够更快被下载, 并且花费更少的开支。你还会学到函数式编程的核心概念,以及如何将它们应用到Javascript, 还有将Javascript作为函数式语言时如何回避一些问题,如何在Javascript中混合使用函数式编程和面向对象编程。

不过在我们开始前,先来做个实验。

例子

也许快速举个例子是介绍Javascript函数式编程最好的方式。我们将用Javascript完成一些任务—— 一个使用传统、原生的方法,另一个使用函数式编程。然后我们将会比较这两种方法。

应用——一个电子商务网站

为了追求真实感,我们来做一个电子商务网站,一个邮购咖啡豆的公司。这个网站会销售好几种类型的咖啡, 有不同的品质,当然也有不同的价格。

命令式方法

首先,我们开始写程序。为了让这个例子接地气,我们需要创建一些对象来保存数据。如果需要的话我们可以从数据库里取值。 但是现在我们假设他们是静态定义的: 

 // create some objects to store the data.
var columbian = {
 name: 'columbian',
 basePrice: 5
};
var frenchRoast = {
 name: 'french roast',
 basePrice: 8
};
var decaf = {
 name: 'decaf',
 basePrice: 6
};
// 我们将使用辅助函数计算价格
// 根据size打印到一个HTML的列表中
function printPrice(coffee, size) {
 if (size == 'small') {
  var price = coffee.basePrice + 2;
 }
 else if (size == 'medium') {
  var price = coffee.basePrice + 4;
 }
 else {
  var price = coffee.basePrice + 6;
 }
 // create the new html list item
 var node = document.createElement("li");
 var label = coffee.name + ' ' + size;
 var textnode = document.createTextNode(label+' price: $'+price);
 node.appendChild(textnode);
 document.getElementById('products').appendChild(node);
}
// 现在我们只需根据咖啡的各种价格和size的组合调用printPrice函数
printPrice(columbian, 'small');
printPrice(columbian, 'medium');
printPrice(columbian, 'large');
printPrice(frenchRoast, 'small');
printPrice(frenchRoast, 'medium');
printPrice(frenchRoast, 'large');
printPrice(decaf, 'small');
printPrice(decaf, 'medium');
printPrice(decaf, 'large');

如你所见,这个代码非常基础。如果现在有更多的咖啡种类而不只是这三个改怎么办?如果有20个,甚至50个? 如果有更多的size呢?如果有有机和无机之分呢?这将会很快将代码量变得巨大无比!

采用这种方法,我们让机器去打印每一种咖啡类型和每一个size。这就是采用这种命令式方法的基本问题。

函数式编程

命令式的代码一步一步地告诉电脑需要做什么来解决问题,相反,函数式编程追求用数学方式来描述问题, 其余的交给电脑来做。

通过更函数式一些的方式,同样的应用可以这样来写:

// 从接口中分解数据和逻辑
var printPrice = function(price, label) {
 var node = document.createElement("li");
 var textnode = document.createTextNode(label+' price: $'+price);
 node.appendChild(textnode);
 document.getElementById('products 2').appendChild(node);
}
// 为每种咖啡创建函数对象
var columbian = function(){
 this.name = 'columbian';
 this.basePrice = 5;
};
var frenchRoast = function(){
 this.name = 'french roast';
 this.basePrice = 8;
};
var decaf = function(){
 this.name = 'decaf';
 this.basePrice = 6;
};
// 为每种size通过字面量创建对象
var small = {
 getPrice: function(){return this.basePrice + 2},
 getLabel: function(){return this.name + ' small'}
};
var medium = {
 getPrice: function(){return this.basePrice + 4},
 getLabel: function(){return this.name + ' medium'}
};
var large = {
 getPrice: function(){return this.basePrice + 6},
 getLabel: function(){return this.name + ' large'}
};
// 将所有咖啡的种类和size放到数组里
var coffeeTypes = [columbian, frenchRoast, decaf];
var coffeeSizes = [small, medium, large];
// 创建由上面内容组成的新对象,并把它们放到一个新数组里
var coffees = coffeeTypes.reduce(function(previous, current) {
 var newCoffee = coffeeSizes.map(function(mixin) {
  // `plusmix`是函数式的minxin, 见第7章
  var newCoffeeObj = plusMixin(current, mixin);
  return new newCoffeeObj();
 });
 return previous.concat(newCoffee);
},[]);
// 现在我们已经定义了如何获得所有咖啡种类和size组合方式的价格,现在可以直接打印它们了
coffees.forEach(function(coffee){
 printPrice(coffee.getPrice(),coffee.getLabel());
});

首先需要明确的是这个代码更加模块化了。现在新增一种size或者信新增一个咖啡种类就像下面的代码这样简单:

var peruvian = function(){
 this.name = 'peruvian';
 this.basePrice = 11;
};
var extraLarge = {
 getPrice: function(){return this.basePrice + 10},
 getLabel: function(){return this.name + ' extra large'}
};
coffeeTypes.push(Peruvian);
coffeeSizes.push(extraLarge);

咖啡对象的数组和size对象的数组混合(mix)到了一起,也就是他们的方法和成员变量被组合到了一块儿 ——通过一个叫“plusMinxin”的自定义函数(详见第七章)。这些咖啡类型的类(columbian, frenchRoast, decaf)包含了成员变量, 而这些size对象(small, medium, large)包含了获取名称和计算价格的方法。 ”混合”(minxing)这个动作通过一个map操作来起作用,也就是对数组中的每一个成员执行一个纯函数并返回一个新的函数, 然后这些返回的函数被放到了一个reduce函数中被操作,reduce也是一个高阶函数,和map有些像, 只是reduce把数组里的所有元素处理后组合到了一个东西里面。最终,新的数组包含了所有可能的种类和size的组合, 这个数组通过forEach方法遍历,forEach也是一个高阶函数,它会让数组里面每一个对象作为参数执行一遍回调函数。 在这个例子里,这个回调函数是一个匿名函数,它获取这些对象后,以对象的getPrice()和getLabel() 两个方法的返回值作为参数调用printPrice函数。

实际上,我们可以让这个例子更加函数式:去掉coffees变量,并将函数串到一起链式调用,这也是函数式编程的一个小技巧。

coffeeTypes.reduce(function(previous, current) {
 var newCoffee = coffeeSizes.map(function(mixin) {
  // `plusMixin` function for functional mixins, see Ch.7
  var newCoffeeObj = plusMixin(current, mixin);
  return new newCoffeeObj();
 });
 return previous.concat(newCoffee);
},[]).forEach(function(coffee) {
 printPrice(coffee.getPrice(),coffee.getLabel());
});

这样,控制流没有像命令式代码那样从头到尾的顺序进行。在函数式编程里,map函数和其它高阶函数代替了for和while循环, 只有少量关键的代码是在顺序执行。 这使得新接触的人在阅读这样范式的代码有些困难,但是一旦你能够欣赏它,你就会发现这根本没啥难的, 而且这样写看起来更好。

这个例子仅仅是刚开始展露Javascript中函数式编程能做什么。通过这本书,你将会看到更多函数式实现的强悍的例子。

总结

首先,采用函数式风格的优点已经明确了。 其次,不要害怕函数式编程。的确,它往往被认为是编程语言的纯逻辑形式,但是我们不需要理解lambda演算也能够在日常任务中应用它。 实际上,通过把我们的程序拆分成小的片段,它们变得更容易被理解、维护,也更加可靠。 map和reduce函数是Javascript中不太被知道的内建函数,然而我们将要关注它们。

Javascript是一个脚本语言,可交互,易使用,不需要编译。我们甚至不需要下载任何开发软件, 你最喜欢的浏览器就可以作为开发环境的解释器。

感兴趣吗?好,我们开始!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
在JavaScript中替换字符串字符在JavaScript中替换字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

构建您自己的Ajax Web应用程序构建您自己的Ajax Web应用程序Mar 09, 2025 am 12:11 AM

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

10个JQuery Fun and Games插件10个JQuery Fun and Games插件Mar 08, 2025 am 12:42 AM

10款趣味横生的jQuery游戏插件,让您的网站更具吸引力,提升用户粘性!虽然Flash仍然是开发休闲网页游戏的最佳软件,但jQuery也能创造出令人惊喜的效果,虽然无法与纯动作Flash游戏媲美,但在某些情况下,您也能在浏览器中获得意想不到的乐趣。 jQuery井字棋游戏 游戏编程的“Hello world”,现在有了jQuery版本。 源码 jQuery疯狂填词游戏 这是一个填空游戏,由于不知道单词的上下文,可能会产生一些古怪的结果。 源码 jQuery扫雷游戏

如何创建和发布自己的JavaScript库?如何创建和发布自己的JavaScript库?Mar 18, 2025 pm 03:12 PM

文章讨论了创建,发布和维护JavaScript库,专注于计划,开发,测试,文档和促销策略。

jQuery视差教程 - 动画标题背景jQuery视差教程 - 动画标题背景Mar 08, 2025 am 12:39 AM

本教程演示了如何使用jQuery创建迷人的视差背景效果。 我们将构建一个带有分层图像的标题横幅,从而创造出令人惊叹的视觉深度。 更新的插件可与JQuery 1.6.4及更高版本一起使用。 下载

如何在浏览器中优化JavaScript代码以进行性能?如何在浏览器中优化JavaScript代码以进行性能?Mar 18, 2025 pm 03:14 PM

本文讨论了在浏览器中优化JavaScript性能的策略,重点是减少执行时间并最大程度地减少对页面负载速度的影响。

Matter.js入门:简介Matter.js入门:简介Mar 08, 2025 am 12:53 AM

Matter.js是一个用JavaScript编写的2D刚体物理引擎。此库可以帮助您轻松地在浏览器中模拟2D物理。它提供了许多功能,例如创建刚体并为其分配质量、面积或密度等物理属性的能力。您还可以模拟不同类型的碰撞和力,例如重力摩擦力。 Matter.js支持所有主流浏览器。此外,它也适用于移动设备,因为它可以检测触摸并具有响应能力。所有这些功能都使其值得您投入时间学习如何使用该引擎,因为这样您就可以轻松创建基于物理的2D游戏或模拟。在本教程中,我将介绍此库的基础知识,包括其安装和用法,并提供一

使用jQuery和Ajax自动刷新DIV内容使用jQuery和Ajax自动刷新DIV内容Mar 08, 2025 am 12:58 AM

本文演示了如何使用jQuery和ajax自动每5秒自动刷新DIV的内容。 该示例从RSS提要中获取并显示了最新的博客文章以及最后的刷新时间戳。 加载图像是选择

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),