JS和函数式语言的三特性

首先要有一个概念:并不是一个语言支持函数,这个语言就可以叫做“函数式语言”。函数式语言中的函数(function),除了能被调用之外,还具有一些其他性质。有以下三点:
1. 函数是运算元
2. 在函数内保存数据
3. 函数内的运算对函数外无副作用
一、函数是运算元
普通的函数调用时,可以抽象的理解为:函数就是一个运算符,传入的参数是运算元;
但当JavaScript中的函数作为另一个函数的参数使用时,是传递引用的,这个“传入参数”就可以被理解为是一个运算元。由此的结论是,(作为“传入参数”的)函数具有运算元的含义,“函数参数”与普通参数并没有什么不同。

二、在函数内保存数据
在命令式语言中,函数内部的私有变量(局部变量)是不能被保存的。从程序的执行方式上来讲,局部变量在栈上分配,在函数执行结束后,所占用的栈被释放。因此函数内的数据不可能被保存。
在JavaScript的函数中,函数内的私有变量可以被修改,而且当再次“进入”到该函数内部时,这个被修改的状态仍将持续。下面的例子说明了这个特性:


代码如下:

var set,get;
  function MyFunc(){
      var value = 100;

function set_value(v){
          value = v;
      }
      function get_value(){
          return value;
      }

set = set_value;
      get = get_value;
  } 
  MyFunc();
  console.log(get()); //100
  set(300);
  console.log(get()); //300

显而易见的一个好处是,如果一个数据能够在函数内持续保存,那么该函数(作为构造器)赋给实例时就可以使用这些数据进行运算;而在多个实例之间,由于数据存在于不同的闭包中,由此相互不会产生影响。
以面向对象的术语来解释,就是说不同的实例有各自的私有数据(复制自某个公共的数据)。下面的例子说明了这个特性:


代码如下:

function MyObject(){
      var value = 100;
      this.setValue = function(){
          value = v;
      }
      this.showValue = function(){
          console.log(value);
      }
  }
  var obj1 = new MyObject();
  var obj2 = new MyObject();

obj2.setValue(300);
  obj1.showValue(); //100;

三、函数内的运算对函数外无副作用
这一特性的含义在于:
* 函数使用入口参数进行运算,而不修改它(作为值参数而不是变量参数使用)
* 在运算过程中不会修改函数外部的其他数据的值(例如全局变量)
* 运算结束后通过“函数返回”向外部系统传值

这样的函数在运算过程中对外部系统是无副作用的。然而我们注意到,JavaScript允许在函数内部引用和修改全局变量,甚至可以声明全局变量。这一点其实是破坏它的函数式特性的。
除此之外,JavaScript也允许在函数内修改对象和数组成员————这些成员应该由对象方法而非对象系统外的其他函数来修改。
所以:JavaScript这项特性只能通过开发人员的编程习惯来保证。

(0)

相关推荐

  • JS和函数式语言的三特性

    首先要有一个概念:并不是一个语言支持函数,这个语言就可以叫做"函数式语言".函数式语言中的函数(function),除了能被调用之外,还具有一些其他性质.有以下三点:1. 函数是运算元2. 在函数内保存数据3. 函数内的运算对函数外无副作用一.函数是运算元普通的函数调用时,可以抽象的理解为:函数就是一个运算符,传入的参数是运算元:但当JavaScript中的函数作为另一个函数的参数使用时,是传递引用的,这个"传入参数"就可以被理解为是一个运算元.由此的结论是,(作为

  • JS轻量级函数式编程实现XDM三

    目录 前言 组合函数 含义 封装盒子 任意组合 compose 变体 抽象能力 阶段小结 前言 这是[JS如何函数式编程]系列文章第三篇.点赞关注,持续追踪 前两篇传送门: <XDM,JS如何函数式编程?看这就够了!(一)> <XDM,JS如何函数式编程?看这就够了!(二)> 在第二篇,我们谈了基础之基础,重要之重要——“偏函数”,偏函数通过函数封装,实现了减少传参数量的目的,解决了手动指定实参的麻烦. 更具重要意义的是: 当函数只有一个形参时,我们能够比较容易地组合它们.这种单元

  • JS实现网络请求的三种方式梳理

    目录 背景 前言 XMLHttpRequest Promise async/await 结语 背景 为了应对越来越多的测试需求,减少重复性的工作,有道智能硬件测试组基于 electron 开发了一系列测试提效工具. 随着工具的快速开发迭代,代码中出现了越来越多的嵌套的回调函数,工具崩溃的几率也越来越大.为了解决这些问题, 我们用 async/await 对这些回调函数进行了重构, 使得代码量下降,代码的可读性和可理解性都有了大幅度提高. 本文介绍了 基于 XMLHttpRequest.Promi

  • 详解C语言快速排序三种方法的单趟实现

    目录 交换排序的思想 冒泡排序的思想 快速排序的整体框架 快速排序单趟实现逻辑 1. hoare版本单趟实现(左右指针法) 2.挖坑法单趟排序实现 3.前后指针法 交换排序的思想 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排 序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 冒泡排序的思想 冒泡排序比较简单,我们之前使用也很多,简单讲解,就是比较两个数,如果比他大就交换,没有他大就接着向后比,一直到数组结束,这是单趟

  • JS轻量级函数式编程实现XDM二

    目录 前言 偏函数 传参现状 封装 partial 运行机制 拓展 partial 柯里化 阶段小结 前言 承接上一篇<XDM,JS如何函数式编程?看这就够了!(一)>,我们知道了函数式编程的几个基本概念. 这里作简要回顾: 函数式编程目的是为了数据流更加明显,从而代码更具可读性: 函数需要一个或多个输入(理想情况下只需一个!)和一个输出,输入输出是显式的代码将更好阅读: 闭包是高阶函数的基础: 警惕匿名函数: 弃用 this 指向: 本篇将着重介绍第 2 点中函数的输入,它是 JS 轻量函数

  • js改变css样式的三种方法推荐

    共用代码: <div id="div"> this is a div </div> var div=document.getElementById('div'); 第一种:用cssText div.style.cssText='width:250px;height:250px;border:1px red solid;'; 第二种:用setProperty() div.style.setProperty('width','250px'); div.style.s

  • 网页中JS函数自动执行常用三种方法

    本文为大家分享了在网页中JS函数自动执行常用方法,供大家参考,具体内容如下 一.JS方法 1.最简单的调用方式,直接写到html的body标签里面: <body onload="myfunction()"> <html> <body onload="func1();func2();func3();"> </body> </html> 2.在JS语句调用: <script type="text

  • 详解JS异步加载的三种方式

    一:同步加载 我们平时使用的最多的一种方式. <script src="http://yourdomain.com/script.js"></script> <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作.所以默认同步执行才是安全的.但这样如果js中有输

  • Java语言通过三种方法实现队列的示例代码

    目录 队列 图解 数组模拟队列 队列优化—循环队列 代码 使用java内部队列 代码 队列 队列是一种特殊的线性表,只允许在表的前端进行删除操作,在表的后端进行插入操作. 队列是一个有序列表,可以用数组或是链表来实现. 遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的要后取出. 就相当于我们日常生活中的排队,先来先服务,后来的只能在后面进行排队等待. 图解 数组模拟队列 通过对定义的了解,发现队列很像我们的数组,那我们是不是可以通过数组来模拟队列,下面我们来实践一下. 首先先分析一下

  • C语言通过三步翻转法实现单词倒置详解

    目录 一.解题思路 二.完整代码与注释 三.代码剖析 1.实现字符串整体的翻转 2.一个单词的翻转 3.字符串中的每一个单词的翻转 一.解题思路 如何将一句话的单词倒置,而标点不倒置? 例如:I like beijing. 倒置成:beijing. like I 可以利用三步翻转法,先将整句话倒置,再将每个单词倒置.前面的例子中输入的内容有空格,如果使用 scanf() 函数的话,scanf 检测到空格后就停止录入了:所以要使用 gets() 函数,gets 可以直接录入一行,包括空格. 代码示

随机推荐