JavaScript Allongé 第一呷 :基础函数 (2)
啊!我想要有一个参数
到现在为止,我们已经了解了没有参数的函数。只说我们的函数没有任何参数,甚至还没说参数是什么。
大多数程序员非常熟悉参数,中学数学就讨论这个了。所以你知道他们是什么,而我也知道你知道他们是什么,但是请耐心对待这个解释!
让我们写一个带参数的函数:
function (room) {}
这个函数有一个参数room,没有函数体。这里是一个带有两个参数但没有函数体的函数:
function (room, board) {}
我很确定,你非常适应这个函数有两个参数的想法,room和board。参数用来做什么呢?当然是用在函数体中。你觉得这是什么?
function (diameter) { return diameter * 3.14159265 }
这是一个给出直径来计算圆周长的函数。我这样解读"当被应用到一个表示直径的值,此函数返回直径乘以3.14159265"。
记得使用一个无参数的函数时,我们写 (function () {})()。使用带参数的函数时,我们把参数放在小括号中,像这样:
(function (diameter) { return diameter * 3.14159265 })(2)
//=> 6.2831853
你也不会对看到如何编写和使用带两个参数的函数而感到惊讶:
(function (room, board) { return room + board })(800, 150)
//=> 950
函数与函数体快速总结
从例子看,在函数体的表达式中如何使用参数对你而言大概是非常明显的,尤其是如果你已经使用过任何编程语言(除了BASIC方言,我记得是在中学,当你调用程序时不允许参数)。
表达式由任意的值(比如 3.14159265, true, 和 undefined),连接表达式的操作符(比如 3 + 2),一些特殊的形式如[1,2,3]用于从表达式中创建数组,或者function (参数) {体语句}用于创建函数组成。
可能其中一个重要的语句是return 语句。return 语句接收任何有效的javascript表达式。
这种松散的定义是递归的,所以我们可以直觉地这样理解(或者使用其他语言的表达式),既然函数可以包含带表达式的返回语句,我们可以写返回函数的函数,或者包含另一个数组表达式的数组,或者返回数组的函数,函数数组,返回函数数组的函数,等等。
function () {
return function () {}
} function () {
return [ 1, 2, 3]
} [1, [2, 3], 4] function () {
return [
(function () { return 1}),
(function () { return 2}),
(function () { return 3})
]
}
按值调用
就像大多数的现代编程语言一样,javascript使用“按值调用”求值策略。这意味着当你写了一些代码将函数应用到表达式时,javascript对所有这些表达式求值并将所得到的值应用于函数。
所以当你写:
(function (diameter) { return diameter * 3.14159265 })(1 + 1)
//=> 6.2831853
内部发生的是,表达式 1 + 1 首先被计算,产生2,然后我们的周长函数被应用于2。
变量和绑定
现在,一切看起来简单明了,我们可以继续前进更详细地讨论参数。我们打算从function (diameter) { return diameter * 3.14159265 }努力深入到像这样的函数:
function (x) { return (function (y) { return x }) }
function (x) { return (function (y) { return x }) }只是看起来疯狂而已,就像我们正在学习英文作为第二语言,而老师向我们保证我们很快就能使用类似antidisestablishmentarianism这样的单词,除了希望使用长单词听起来让人印象深刻以外,这看起来不再有吸引力,直到我们发现自己想要讨论在19世纪英国政治中英国教会中的角色。
但是这里有另外一个学习antidisestablishmentarianism这个单词的理由:我们也许会学习前缀和后缀在英文语法中如何工作。这和function (x) { return (function (y) { return x }) }是一样的,它本身具有一定的重要意义,它也是一个学习造函数的函数,环境,变量,等等的优秀借口。
为了讨论它是如何工作的,我们需要同意几个术语(你可能已经知道它们了,但我们还是一起检测一下然后“同步我们的词典”)。第一个x,是在function (x) ...中的x,它是一个参数,在function (y) ...中的y是另一个参数,第二个x,是在{ return x }中的x,它不是一个参数,它是一个指向值的表达式。参数和变量以同种方式工作,不管我们是在讨论 function (x) { return (function (y) { return x }) }还是仅仅讨论简单的function (x) { return x }。
每次,一个函数被调用(调用意味着被应用到零个或更多参数),一个新环境就被创建了。一个环境是一个(可能是空的)字典,根据名称将变量映射到值,在表达式中的x我们称之为一个变量,它自身是一个表达式,通过查找环境中的值来被计算。
值是怎样被放到环境中的呢?对参数而言,这很简单。当你将函数应用到参数时,就为字典中的每一个参数放了一个入口,所以当我们写:
(function (x) { return x })(2)
//=> 2
发生了这些事:
1 javascript将这个整体解析为一个由几个子表达式组成的表达式。
2 之后它开始对表达式求值,包括对子表达式求值。
3 一个子表达式,function (x) { return x },计算结果为一个函数。
4 另一个2,计算结果为数值2。
5 javascript现在计算将函数应用到参数2。下面就是它有趣的地方...
6 创建一个环境
7 值2在环境中被名称x所绑定。
8 表达式x(函数的右侧)在我们刚刚创建的环境中被计算。
9 我们在环境中计算的变量的值是在该环境中绑定给变量的名字的值,也就是2。
10 这就是我们的结果
当讨论环境时,我们将使用一个不令人吃惊的语法来显示绑定:{x: 2, ...}。意思是,这个环境是一个字典,而值2被绑定给了名称x,并且在字典中或许有其他的我们现在不讨论的东西。
按共享调用
早些时候,我们区分过javascript的值类型与引用类型。在那时,我们看javascript如何区分对象是否是相同的对象,现在是时候再看一下值和引用类型的区别了。
有一个属性javascript一直在维护:当一个值-任何值-被作为参数传递给函数,这个被绑定在函数环境中的值必须与原始的是相同的。
我们说过javascript把值绑定到名称,但未说过把值绑定到名称意味着什么。现在我们可以详细点了:当javascript把一个值类型绑定到名称时,它复制了这个值然后把副本放在环境中。正如你记得的,像字符串和数值的值类型如果有相同的内容它们是彼此相同的,所以javascript可以建很多字符串、数值或者布尔值的副本只要它想。
引用类型呢?javascript不会在任何环境中放引用类型的副本。javascript在环境中放引用类型的引用,当值需要被用到时,javascript根据引用获得原始值。
因为许多引用类型可以共享同样的值,并且因为javascript将引用作为参数传入,javascript可以说是实现了“按共享调用”的语义。按共享调用一般被理解为按值调用的特殊化。并且它解释了为什么一些值被称为值类型而其他值被称为引用类型。
有了这些,我们就准备好看闭包了。当我们将值类型、引用类型、参数和闭包的知识结合在一起的时候,我们就会理解为什么这个函数总是计算结果为true,不管你用了什么参数:
function (value) {
return (function (copy) {
return copy === value
})(value)
}
JavaScript Allongé 第一呷 :基础函数 (2)的更多相关文章
- JavaScript Allongé 第一呷 :基础函数 (1)
第一呷 :基础函数 关于函数,尽管少,但毫不逊色. 在javascript中,函数是值,但它们不仅仅是简单的数值,字符串,或者甚至复杂的数据结构树或者地图.函数表示要执行的运算.就像数值.字符串和数组 ...
- JavaScript Allongé 第一呷 :基础函数 (3) 未完
闭包与域是时候来看下一个带函数的函数是如何工作的: (function (x) { return function (y) { return x } })(1)(2) //=> 1 首先,我们使 ...
- 网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法:
转载自网络,非原创 1.输出语句:document.write(""); 2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head ...
- javascript常用的基础函数或方法——写给新手的我(持续补充)
1常用基础函数 alert函数:显示一个警告对话框,包括一个OK按钮.这就是传说中的警告框,此框一弹,世界就清静了.举例: alert("我一旦出现,之前出现的就算了,我屁股后面你们就歇 ...
- JavaScript 笔记(1) -- 基础 & 函数 & 循环 & ...
目录(代码编写): 显示数据 语法 变量 & 变量类型 对象 函数 事件 字符串 运算符 条件语句 循环语句 Break 和 Continue 使用 JS 近两年,现整理下一些基本: HTML ...
- 浅谈:javascript的面向对象编程之基础知识的介绍
在进入javascript的面对对象之前,我们先来介绍一下javascript的几个概念. 1.javascript的面向对象的基本概念 function aa(){ } /* * 这里的aa,在我们 ...
- 更优雅的方式: JavaScript 中顺序执行异步函数
火于异步 1995年,当时最流行的浏览器--网景中开始运行 JavaScript (最初称为 LiveScript). 1996年,微软发布了 JScript 兼容 JavaScript.随着网景.微 ...
- JavaScript 面向对象开发知识基础总结
JavaScript 面向对象开发知识基础总结 最近看了两本书,书中有些内容对自己还是很新的,有些内容是之前自己理解不够深的,所以拿出来总结一下,这两本书的名字如下: JavaScript 面向对象精 ...
- javascript学习4、Function函数、伪数组arguments
一.Function函数基础 函数:就是将一些语句进行封装,然后通过调用的形式,执行这些语句. 1.函数的作用: 将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动. ...
随机推荐
- iOS端使用二维码扫描(ZBarSDK)和生成(libqrencode)功能
如今二维码随处可见,无论是实物商品还是各种礼券都少不了二维码的身影.手机中二维码使用也很广泛,如微信等.正好最近收集总结了下二维码的使用方法 下面介绍一下如何在iOS设备上使用二维码 首先在githu ...
- 编辑xml文件时不能自动提示问题的解决
在编辑xml文件时,eclipse总是不能自动提示,在网上找了一些资料,大部分都是说关于xml editor配置的,下面也把这个方法罗列在下面,以供参考: 解决办法:在eclipse的菜单里,找到wi ...
- 物理机装kali复盘
复盘总结 最近把旧电脑想刷成kali的单系统,便下载了最新版本的kali 2018.1 的镜像文件.由此出现了很多问题. 首先在制作启动盘的时候,我用了很多软件,比如Ultriso,rufus,uni ...
- js 弹出QQ对话框
首先打开下面链接,开通QQ推广. http://shang.qq.com/v3/index.html 然后在页面代码中写入 <a target="_blank" href=& ...
- POJ1163(基础线性DP)
The Triangle Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 42547 Accepted: 25721 De ...
- 微信小程序 实现websocket长连接 以及断开连接之后自动重连
app.js let socketMsgQueue = [] let isLoading = false App({ globalData: { userInfo: null, localSocket ...
- wannafly test D
题意: 给定n,m求满足: 1.a[i][j]互不相同,且有$1<=a[i][j]<=n*m$ 2.对于$a[i1][j1],a[i2][j2]$,如果有 $i1 \oplus j1 &g ...
- 2.7-2.8 导入、导出数据(进/出)hive表的方式
一.导入数据进hive表 1.语法 LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (p ...
- C/C++学习笔记1
namespace: 通过命名空间防止变量冲突. 定义 namespace nsl { class Student { public: Student(int n,string nam,int a) ...
- wmware7安装xp错误:虚拟CPU已经入关闭状态
wm7安装xp错误提示: 虚拟CPU已经入关闭状态.这会造成物理计算机重新启动.这可能是虚拟机操作系统的错误或VMware Workstation软件中的一个配置不正确. 这种情是硬盘模式为AHCI模 ...