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.函数的作用: 将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动. ...
随机推荐
- 限制远程桌面登录IP的方法
转自:http://www.cnblogs.com/vaexi/articles/2106623.html 限制远程桌面登录IP的方法 第一种方法: 1.打开Windows自带的防火墙2.开放允许例外 ...
- ubuntu16.04 ROS安转及RVIZ启动
1.软件中心配置 首先打开软件和更新对话框,打开后按照下图进行配置(确保你的"restricted", "universe," 和 "multiver ...
- 使用Rest api管理Ceph网关
背景 开发基于Ceph RadosGW的微服务,需要实现调用方可以通过rest api就能创建用户,获取用户信息等功能. 实现 Ceph的RadosGW自身就有该功能,这些创建用户.获取用户信息.获取 ...
- Struts文件上传下载
Struts配置文件: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PU ...
- Eclipse+Maven+TestNg+ReportNg 生成测试报告
http://blog.csdn.net/a542551042/article/details/46729585
- table对象
- 微信小程序 设置宽度是100%,然后图片能成为正方形的方法。小程序按屏幕比例的正方形
1.在全局app.js中获取设备的宽度 globalData: { userInfo: null, sysWidth:wx.getSystemInfoSync().windowWidth, //图片宽 ...
- [开源]OSharpNS - .net core 快速开发框架 - 快速开始
什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...
- lightoj1063【求割点】
题意不懂啊...... 只知道求割点. #include <bits/stdc++.h> using namespace std; typedef long long LL; typede ...
- Lightoj 1067【逆元模板(求C(N,M))】
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ...