微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

函数式 JavaScript 简介

2016-03-14 20:11 前端大全

(点击上方,可快速关注)


原文:M. David Green

译者:伯乐在线 - Delostik

网址:http://web.jobbole.com/85266/


你肯定听说过JavaScript是一个函数式语言,或者至少知道他支持函数式编程。但是究竟什么是函数式编程?对于这个问题,如果你打算比较通用的编程范式,函数式的实现跟我们平时写的JavaScript又有什么不同?


好消息是在编程范式方面JavaScript没有那么讲究,你可以混入命令式(Imperative Programming)、面向对象、原型和函数式代码等等,只要你觉得合适,都能得到一样的结果。但是坏消息也因它而起,JavaScript在同样的代码库下同时提供了众多编程风格,所以你需要根据代码的可维护性、可读性和性能选择合适的编程方式。


函数式JavaScript并不是一定要用于整个项目中来体现它的价值。学习一点函数式的方法可以在我们构建项目时提供一些参考和帮助,而不论我们喜欢哪种方式。学习一些函数式模式和技术可以帮助我们写出更整洁、优雅的JavaScript代码,不论我们是不是真的用它。


var result;

function getText() {

  var someText = prompt("Give me something to capitalize");

  capWords(someText);

  alert(result.join(" "));

};

function capWords(input) {

  var counter;

  var inputArray = input.split(" ");

  var transformed = "";

  result = [];

  for (counter = 0; counter < inputArray.length; counter++) {

    transformed = [

      inputArray[counter].charAt(0).toUpperCase(),

      inputArray[counter].substring(1)

    ].join("");

    result.push(transformed);

  }

};

document.getElementById("main_button").onclick = getText;


这一小段代码中做了很多事:定义了一个全局变量;字符串值被传来传去,并被函数修改;还夹杂着原生JavaScript的DOM方法。函数名不是很有描述力,一定程度上因为这一切都依赖于不确定存在或不存在的上下文。但是如果你碰巧在浏览器执行了这段代码,而且网页中定义了一个<button id="main_button">,你会收到可输入文本的对话框提示,会看到那串被首字母大写了的文本。


像这种命令式代码会从顶部开始执行(如果不考虑variable hoisting的情况)。但是我们仍然可以利用JavaScript的面向对象能力来提高代码的可读性和整洁度。


面向对象的JavaScript


几年后,开发者开始注意到像浏览器这样的共享环境下的命令式编程的问题。一段JavaScript代码中定义的全局变量可能会破坏另一个全局变量。代码执行的顺序和效果无法预测,尤其在网络延迟和渲染时间的影响下。


后来出现了一些好办法来封装JS代码,让它能更好地跟DOM工作。比如下面这段代码是前面代码的一种改写,使用了面向对象的方法:


(function() {

  "use strict";

  var SomeText = function(text) {

    this.text = text;

  };

  SomeText.prototype.capify = function(str) {

    var firstLetter = str.charAt(0);

    var remainder = str.substring(1);

    return [firstLetter.toUpperCase(), remainder].join("");

  };

  SomeText.prototype.capifyWords = function() {

    var result = [];

    var textArray = this.text.split(" ");

    for (var counter = 0; counter &lt; textArray.length; counter++) {

      result.push(this.capify(textArray[counter]));

    }

    return result.join(" ");

  };

 

  document.getElementById("main_button").addEventListener("click", function(e) {

    var something = prompt("Give me something to capitalize");

    var newText = new SomeText(something);

    alert(newText.capifyWords());

  });

}());


在面向对象的版本中,构造函数模拟了一个类供我们设计我们想要的对象,方法定义在对象的原型中来降低内存使用。所有的代码都封闭在一个匿名的及时调用函数表达式中,所以它不会污染全局作用域。”use strict”强制使用最新的JavaScript引擎,onclick方法被新引入的addEventListner代替,毕竟没人再使用比IE8还古董的浏览器了。这段代码可以被插入在<body>段的最后,使得所有的DOM加载完成后才执行,这时候<button>才可用。


函数式JavaScript


相比我们开始说的命令式代码,面向对象确实能使代码更整洁、模块化更好,但我们看能否通过解决它的一些缺点来使它更完美。如果我们能通过JavaScript的一些内建特性,把函数当“第一类对象”看待,我们的代码会更加干净、稳定、易拓展。


(function() {

  "use strict";

  var capify = function(str) {

    return [str.charAt(0).toUpperCase(), str.substring(1)].join("");

  };

  var processWords = function(fn, str) {

    return str.split(" ").map(fn).join(" ");

  };

  document.getElementById("main_button").addEventListener("click", function(e) {

    var something = prompt("Give me something to capitalize");

    alert(processWords(capify, something));

  });

}());


发现这个版本短了多少没?我们制定一了capify和processWords两个函数,每个函数都是pure的,也就是说他们不依赖于调用他们的代码的状态。函数不会改变他们之外的变量。针对给定的任意参数,返回唯一的结果。由于这些改进,新的函数易于测试,也很容易被移植。


刚才那段代码中可能有个函数你没见过,我们在Array上使用map方法,可以对Array上每个元素应用fn函数(fn是传入的参数)。运行在现代浏览器和服务端的实现了ES5的JavaScript为我们提供了这个方便的函数。这里不需要使用for循环,只使用一个map,可以避免使用循环变量,提高代码的整洁度和可读性。


对函数式的思考


你用为了函数范式而抛弃使用的一切,而是在你做下一个项目的时候,可以用函数的思维来考虑一下下面的问题:


  • 我的函数依赖调用上下文吗?他们是独立的吗?

  • 我可以把函数写成对某个输入总有相同返回值的吗?

  • 我的函数不改变函数外的变量吗?

  • 如果我想要在其他项目中使用这个函数,我需要修改他们吗?


这篇介绍仅仅是揭露了函数式JavaScript的表面,但希望它能引起你的探究欲望而学到更多。



【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!



 
前端大全 更多文章 详解Javascript中的Object对象 结合个人经历总结的前端入门方法 前端不为人知的一面–前端冷知识集锦 一份优秀的前端开发工程师简历是怎么样的? 浅谈Web缓存
猜您喜欢 网络架构、云平台与微信公众平台开发接入 网络营销行业众生相:准CIO们的尴尬 向威胁与侵害说不!超越基础架构的安全防护 敏捷实践Showcase的七宗罪|TW洞见 自己编写Android Studio插件 别停留在用的程度了