译文:Javascript-Functions
个人理解+google翻译+有道翻译。如有错误,请指正。原文来自MDN:Functions
Functions是javascript基本构建模块之一。每一个function是一个javascript程序--一组执行任务或计算值的语句。要使用一个function,必须在调用该function范围某处先作定义。
functions 定义(函数定义)
一个函数的定义(也成为函数声明)由关键字function设定,然后是:
- 函数的名字
- 传递给函数的的参数列表,这些参数用括号括起来,使用逗号分隔。
- 定义函数的javascript语句,使用花括弧({})括起来。
例如下面的代码中,定义了一个名为square的简单函数:
function square(number) {
return number * number;
}
square函数接收一个参数,名为number。该函数由一条语句组成,即返回参数number的乘积。
return number * number;
初始参数(如一个数字)通过值传递给函数,传递给函数的值如果被被函数修改了,这种情况下值的修改不反映到全局环境或函数调用中(this change is not reflected globally or in the calling function.)。
如果传递一个对象(即非原始值,如Array或用户自定义对象)参数,函数修改对象的属性,这种修改对于函数外部是可见的,看下面的用例演示:
function myFunc(theObject) {
theObject.make = "Toyota";
} var mycar = {make: "Honda", model: "Accord", year: 1998},
x,
y;
x = mycar.make; // x 取值 "Honda"
myFunc(mycar);
y = mycar.make; // y 取值 "Toyota"
// (make 属性已经被函数修改)
注意:赋值一个新的对象给参数对函数外部没有任何影响,因为这种情况改变了参数的值,而不是改变了对象的属性值:
function myFunc(theObject) {
theObject = {make: "Ford", model: "Focus", year: 2006};
} var mycar = {make: "Honda", model: "Accord", year: 1998},
x,
y;
x = mycar.make; // x 取值 "Honda"
myFunc(mycar);
y = mycar.make; // y 一直取值 "Honda"
在第一个例子中,对象mycar传给函数myFunc,并改变了对象mycar。
对于原文有不同看法:
原文:In the second case, the function did not alter the object that was passed; instead, it created a new local variable that happens to have the same name as the global object passed in,
翻译:在第二个例子中,函数没有改变传过来的对象;函数创建了一个新的局部变量,只不过这个新的局部变量与传入的全局对象名称相同。
此处函数并不是创建了一个新的局部变量,而是,theObject作为函数的参数,本身就是个局部变量,在函数体内的theObject = {make: "Ford", model: "Focus", year: 2006};
其实是该参数指向了一个新的对象而非创建了一个新的局部变量。传入的对象在函数内被“改变”。
所以对传入的全局对象没有任何影响。
以上的函数声明是语法上地函数声明,函数也可以通过函数表达式创建。函数可以是匿名的,不必有一个名称。例如,函数square能被定义为:
var square = function(number) {return number * number};
var x = square(4) //x 取值 16
此外,函数名可以提供一个函数表达式,并且可以用于在函数内部指向本身,或在调试器中堆栈跟踪过程确定函数:
var factorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};
console.log(factorial(3));//6 函数的递归
当函数作做为参数传递给另一个函数时,函数表达式非常方便。下面的例子中展示了一个名为map的函数,调用它使用一个匿名函数作为其第一个参数:
function map(f,a) {
var result = [],
i;
for (i = 0; i != a.length; i++){
result[i] = f(a[i]);
}
return result;
}
下面的代码:
map(function(x) {return x * x * x}, [0, 1, 2, 5, 10]);
返回 0,8,125,1000
在JavaScript中,函数可以根据条件来定义。例如,下面的函数定义中只有当num等于0时定义myFunc:
var myFunc;
if (num == 0){
myFunc = function(theObject) {
theObject.make = "Toyota"
}
}
除了描述性的定义函数,也可以在程序运行时使用 Function constructor(函数构造)和一个字符串创建函数,与eval()很相似;例如
var setBGColor = new Function("document.bgColor = 'antiquewhite'");//将一个函数分配给变量setBGColor。该函数设置当前文档的背景颜色
一个方法是一个函数,这个函数方法也可以作为对象的属性。关于objects和methods更多信息参考Working with Objects
调用函数
定义一个函数而不运行它。则定义的函数只是为该函数命名和指定该函数被调用的时候去做什么事情。调用函数时实际是通过指定的参数执行指定的动作。例如,定义了一个函数square,你会按下面的方式调用:
square(5);
前面的语句是以5为参数调用square函数。该函数执行内部语句返回值25。
函数被调用时肯在一个作用域内,但函数的声明可以在函数调用下面,例如:
print(square(5));
/* ... */
function square(n){return n*n}
函数的作用域由其在声明时所在的范围,或是整个程序如果在顶级范围声明。注意这种运行方式只在上例的语法下定义函数(即fucnction funName(){})。下面的代码不会运行。
print(square(5));
square = function (n) {
return n * n;
}
函数的参数不只局限于字符串和数字类型。也可以传一个对象到函数。例子show_prop函数(定义在Working with Objects)接收一个对象作为参数。
函数可以是递归的,也就是说,它可以调用本身。例如,这里是一个函数,递归计算阶乘:
function factorial(n){
if ((n == 0) || (n == 1))
return 1;
else
return (n * factorial(n - 1));
}
然后可以通过下面的代码计算1到5的阶乘:
var a, b, c, d, e;
a = factorial(1); // a gets the value 1
b = factorial(2); // b gets the value 2
c = factorial(3); // c gets the value 6
d = factorial(4); // d gets the value 24
e = factorial(5); // e gets the value 120
还有其他的方法来调用函数.经常有函数需要动态调用或变化函数的参数数量,或在运行时的函数上下文中设置一个指定的确定对象。证明functions是它们自己,也是对象,对象反过来含有方法(参见Function object)。【It turns out that functions are, themselves, objects, and these objects in turn have methods (see the <i>Function object</i>). 】 apply()能够实现这一目标。
函数作用域
定义在函数内的变量不能被函数外部任何地方访问,因为只是定义在函数范围内。然而在已定义的函数内,一个函数可以使用所有的定义的变量和函数。也就是说,全局作用域内定义的函数可以使用全局作用域内所有定义的变量。在另一个函数内定义的函数也可以使用其在父函数内定义的和其它父函数可访问的所有变量。
// 下面的变量定义在全局作用域内
var num1 = 20,
num2 = 3,
name = "Chamahk";
// 这个函数定义在全局作用域内
function multiply() {
return num1 * num2;
}
multiply(); // Returns 60
// 一个内嵌函数示例
function getScore () {
var num1 = 2,
num2 = 3;
function add() {
return name + " scored " + (num1 + num2);
}
return add();
}
getScore(); // Returns "Chamahk scored 5"
闭包
闭包是Javascript非常强大的功能之一。JavaScript允许函数嵌套,此外,授予内部函数访问所有其外包函数内定义的变量和函数(其它变量和函数需要能被父函数访问。)但外包函数不能访问其内部函数定义的变量和函数。这样使内部函数的变量得到了安全。此外,因为内部函数可以在外包函数的作用域内访问,所以当内部函数管理周期超过外包函数生存期时,在外包函数内定义的变量和函数将会比外包函数存在时间更长。当内部函数在外包函数外部任意范围以某种方式变为有效代码时就创建了一个闭包。
var pet = function(name) { // 外包函数定义name变量
var getName = function() {
return name; // 内部函数访问外包函数的name变量
}
return getName; // 返回内部函数,从而暴露到外部作用域
},
myPet = pet("Vivie");
myPet(); // Returns "Vivie"
也可以比上面的代码复杂得多。可以返回一个包含处理外包对象内部变量的方法的对象。
var createPet = function(name) {
var sex;
return {
setName: function(newName) {
name = newName;
},
getName: function() {
return name;
},
getSex: function() {
return sex;
},
setSex: function(newSex) {
if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
sex = newSex;
}
}
}
}
var pet = createPet("Vivie");
pet.getName(); // Vivie
pet.setName("Oliver");
pet.setSex("male");
pet.getSex(); // male
pet.getName(); // Oliver
在上面的代码中,外包函数的变量名可以被内部函数访问,而且没有其他方式访问内部变量除非通过内部函数访问。内部函数的变量作为内部函数的安全存储。它们保持特殊的“持久状态”,但为内部函数的运行提供安全的数据(They hold "persistent", yet secure, data for the inner functions to work with)。这些内部函数甚至可以不分配一个变量或拥有一个名称。
var getCode = (function(){
var secureCode = "0]Eal(eh&2"; // 一处代码不希望被外部修改...
return function () {
return secureCode;
};
})(); getCode(); // 返回保密的代码
但是要提防使用闭包时的一些陷阱。如果一个闭包函数定义了一个与外部作用域变量同名的变量,将没有任何办法再次指向外部作用域的同名变量。
var createPet = function(name) { // 外包函数定义了一个名为name的变量
return {
setName: function(name) { // 闭包函数也定义了一个名为name的变量
name = name; // ??? 我们如何访问外包函数定义的name变量 ???
}
}
}
闭包内的this变量非常神奇及不可捉摸。他们必须小心使用,因为this的指向完全取决于函数的调用,而非取决在哪定义。关于闭包的精品文章在这可以找到:closures(闭包)。
使用 arguments 参数对象
函数的参数保存在一个类似数组的对象内。可以像下面的代码在函数中寻址传递给函数的参数。
arguments[i];
其中i是参数的起始值为0索引序号。所以传递给函数的第一个参数会是argument[0]。参数的总数用的arguments.length表示。
使用arguments参数对象时,可以使用比函数声明接收的参数数量更多的参数来调用函数。通常在你事先不知道有多少参数将被传递给函数时是很有用处的。可以使用arguments.length来确定实际传递给函数的参数的个数,然后使用arguments 参数对象来访问每个参数。
function myConcat(separator) {
var result = "", // 初始化列表
i;
// 遍历参数
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
可以传递任意数量的参数给这个函数,它串连每个参数转换成字符串“列表”。
// returns "red, orange, blue, "
myConcat(", ", "red", "orange", "blue"); // returns "elephant; giraffe; lion; cheetah; "
myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // returns "sage. basil. oregano. pepper. parsley. "
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
需要注意的是:arguments变量类似于数组,不是真正的数组。arguments变量类似数组是因为它编号索引和length属性,此外,也不具备数组处理方法。更多信息参看Javascript参考Function object
预定义函数
javascript有几个一级预定义函数:
- eval
- isFinite
- isNaN
- parseInt and parseFloat
- Number and String
- encodeURI, decodeURI, encodeURIComponent, and decodeURIComponent (JavaScript1.5及更高版本可用).
以下各节将介绍这些函数,更多详细信息参考 JavaScript Reference
eval 函数
eval函数不引用特定对象来运行计算一行javascript字符串类型的代码,其语法如下:
eval(expr);
expr为运行的字符串。
如果该字符串代表一个表达式,eval运行计算该表达式。如果该参数代表一行或多行JavaScript语句中,eval执行语句。eval代码作用域与调用eval代码作用域相同。不要用eval运行一个计算表达式;javascript自动运行计算表达式。
isFinite 函数
isFinite函数确定参数是否为一个有限数字。语法如下:
isFinite(number);
number为数字类型。
如果参数为NaN,正无穷大或负无穷大,此方法返回false,否则返回true。
下面的代码检查客户端的输入,确定它是否是一个有限数字。
if(isFinite(ClientInput)){
/* 执行指定步骤 */
}
isNaN 函数
isNaN函数判断参数是否是“NaN”(非数字值),语法如下:
isNaN(testValue);
testValue为需要判断的值。
parseFloat函数和parseInt函数运行一个非数字值时,返回NaN。如果传入一个“NaN”(非数字),isNaN返回true,否则false。
下面的代码确定floatValue是否是一个数字,然后相应地调用对应程序。
var floatValue = parseFloat(toFloat);
if (isNaN(floatValue)) {
notFloat();
} else {
isFloat();
}
parseInt函数 和 parseFloat函数
两个解析(转换)函数,parseInt和parseFloat,当参数为字符串时返回一个数字值。
parseFloat语法:
parseFloat(str);
其中parseFloat解析它的参数字符串str,并试图返回一个浮点数.如果遇到一个字符不是一个符号(+或 - ),数字(0-9),小数点或指数,则在此处返回值,并忽略该字符及其后的所有字符。如果第一个字符不能被转换为数字,则返回“NaN”(非数字)。
parseInt语法
parseInt(str [, radix]);
parseInt函数解析转换第一个字符串参数str,并尝试返回一个以指定的radix参数为基数的整数。radix为可选参数。理由radix为10则转换为十进制数,为8时转换八进制数,16时转换为十六进制等等。对高于十的进制数,使用字母表中的字母来表示大于9的数。例如十六进制数使用A-F。
如果parseInt函数遇到一个不是指定基数的数字字符,则忽略该字符和后续字符,返回解析到该点的整数值。如果第一个字符不能转换为指定基数的数字,返回NaN。parseInt函数截取字符串转为整数。
Number 和 String 函数
Number 和 String 函数可以把一个对象转为数字类型或字符串类型。语法如下:
var objRef;
objRef = Number(objRef);
objRef = String(objRef);
objRef作为对象引用。Number作为对象的valeOf()方法;String作为对象的toString()方法。
下面的例子转换Date对象为可读的字符串。
var D = new Date(430054663215),
x;
x = String(D); // x equals "Thu Aug 18 04:37:43 GMT-0700 (太平洋夏令时) 1983"
下面的例子把String(字符串)对象转换为Number(数字)对象。
var str = "12",
num;
num = Number(str);
我们可以通过DOM的write()和javascript的typeOf运算符来做一个检测。
var str = "12",
num;
document.write(typeof str);
document.write("<br/>");
num = Number(str);
document.write(typeof num);
escape 和 unescape 函数(JavaScript 1.5以上已废弃)
escape和unescape 函数对非ASCII字符不能正常运行,已被弃用。在JavaScript1.5和更高版本,使用encodeURI,decodeURI,encodeURIComponent和decodeURIComponent。
escape和unescape函数可以对字符串进行编码和解码。escape函数返回参数在ISO拉丁字符集十六进制编码。unescape函数返回指定的十六进制编码值的ASCII字符串。
语法如下:
escape(string);
unescape(string);
它们主要用于服务器端JavaScript对URL键值对进行编码和解码。
译文:Javascript-Functions的更多相关文章
- What exactly is the parameter e (event) and why pass it to JavaScript functions?
What exactly is the parameter e (event) and why pass it to JavaScript functions? 问题 Well, when I lea ...
- Javascript Functions
Javascript 全局对象 全局属性和函数可用于所有内建的Javascript对象 顶层函数(全局函数) decodeURI()解码某个编码的URI. decodeURIComponent()解码 ...
- Understand JavaScript Callback Functions and Use Them
In JavaScript, functions are first-class objects; that is, functions are of the type Object and they ...
- 【repost】JavaScript Scoping and Hoisting
JavaScript Scoping and Hoisting Do you know what value will be alerted if the following is executed ...
- 理解callback function in javascript
以下内容主要摘自[1,2] (1)In javascript, functions are first-class objects, which means functions can be used ...
- How to load a local .CSS file & JavaScript resources using iPhone UIWebView Class
This post will cover the basic setup and creation of an application with web content for iPhone that ...
- JavaScript闭包的底层运行机制
转自:http://blog.leapoahead.com/2015/09/15/js-closure/ 我研究JavaScript闭包(closure)已经有一段时间了.我之前只是学会了如何使用它们 ...
- Run JavaScript on your PeopleSoft pages conditionally
Here, PeopleCode sets the logic that determines when the JavaScript code will run. This is not as si ...
- JavaScript Madness: Dynamic Script Loading
Introduction I've developed some pretty seriously Javascript intensive sites, where the sheer quanti ...
- [Javascript] Array methods in depth - filter
Array filter creates a new array with all elements that pass the test implemented by the provided fu ...
随机推荐
- mysql 支持emoji
1.修改my.cnf [client] default-character-set = utf8mb4 [mysqld] collation-server = utf8mb4_unicode_ci c ...
- Computer Science Theory for the Information Age-2: 高维空间中的正方体和Chernoff Bounds
高维空间中的正方体和Chernoff Bounds 本文将介绍高维空间中正方体的一些性质,以及一个非常常见也是非常有用的概率不等式——Chernoff Bounds. 考虑$d$维单位正方体$C=\{ ...
- SQL SERVER中架构的理解
在sqlserver 2005中,可能大家在工作或学习的时候会经常发现这样一些问题,你使用一个账户在数据库中创建了一张表,却发现你自己创建的表却没有修改和查询的权限,这是一件很郁闷的事情,在sqlse ...
- jQuery Mobile 连接外部连接或切换动画
jQuery Mobile不同网页之间的跳转问题 jQuery Mobile,一个新的手机终端脚本开发库,从名字可以看出,它是基于jQuery:目前支持很多种手机设备,包括IOS/Android/Bl ...
- cocos2d-x 3.0 alpha1 生成Qt qch帮助文档
Qt的助手挺好用的. 比chm好多了 cocos2d-x使用doxygen生成文档. 默认生成的是html形式, 需要打开浏览器, 这个是比较耗资源吧 可以修改配置, 让doxygen同时输出qch形 ...
- 想学React Native?你只需要一个App!(11月5号更新)
最近有点空闲时间,顺手研究下react-native,2013年的时候在老师的指导下使用jQuery Mobile做过手机应用,那个运行速度慢呀!让我对WebApp和PhoneGap这一类的跨平台Ap ...
- C#获取CPU等硬件ID(转载)
System.Management命名空间提供对大量管理信息和管理事件集合的访问,这些信息和事件是与根据 Windows 管理规范 (WMI) 结构对系统.设备和应用程序设置检测点有关的.应用程序和服 ...
- Virtualbox - Fatal: Could not read from the boot medium; system halted!
刚装好的虚拟机系统,重新打开Virtualbox时出现个什么提示没认真看,顺势点了下去......结果虚拟机的xp系统打不开了,启动后出现:Fatal: Could not read from the ...
- json2使用方法
例子1: //直接声明json数据结构 var myJSONObject = {"bindings": [ {"ircEvent": "PRIVMSG ...
- 使用NumberPicker定制自己喜欢的Date&TimePicker
1.NumberPicker简介: NumberPicker是Android3.0之后引入的一个控件,主要功能是用于选择一组预定义好数字的控件. 该控件主要需要指导一个用于监听当前value变化的li ...