-
Notifications
You must be signed in to change notification settings - Fork 14
Description
JavaScript 函数
JavaScript 中的函数:用于执行特定任务的代码块。
另外,将脚本script编写为函数以避免页面载入时执行该脚本。
JavaScript 函数语法:
- A JavaScript function is defined with the function keyword, followed by a name, followed by parentheses ()
- 函数名称可以包含字母,数字,下划线和美元符号(与变量相同的规则),建议使用驼峰命名法
- The parentheses may include parameter names separated by commas:
(parameter1, parameter2, ...) - The code to be executed, by the function, is placed inside curly brackets: {}
function name(parameter1, parameter2, parameter3) {
code to be executed
}-
Function parameters are listed inside the parentheses () in the function definition.
-
Function arguments are the values received by the function when it is invoked.
// 实例:将实参 argument 传入形参 parameter name(1, 2, 3);
-
Inside the function, the arguments (the parameters) behave as local variables.
形参和实参的区别:
- 英文名字不同:形参是 parameter ,实参是 argument 。
- 本质不同:形参的本质是一个名字,不占用内存空间。实参的本质是一个变量,已经占用内存空间。
在 Javadoc 或 MSDN 中的地位不同: Javadoc 和 MSDN 提到一个方法有哪些参数,往往用 parameter 这个词。只有到程序员真正使用这个方法,才是 argument。
在调试的时候, parameter 就转变成 argument ,这时也往往不使用 argument 一词,而是称之为 variable (变量),因为实参本质上就是一个变量,在内存中占用一块空间。
注意:JavaScript 函数传入的参数是可选的。
ECMAScript 函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不会有什么怨言。之所以会这样,原因是 ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任何元素,无所谓;如果包含多个元素,也没有问题。实际上,在函数体内可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。
其实, arguments 对象只是与数组类似(它并不是 Array 的实例),因为可以使用方括号语法访问它的每一个元素(即第一个元素是arguments[0],第二个元素是argumetns[1],以此类推),使用length属性来确定传递进来多少个参数。——《JavaScript高级程序设计(第3版)》
JavaScript 函数分类
- 系统函数
- 自定义函数
- 匿名函数(属于自定义函数)
分类一:系统函数
| 常用的系统函数举例 | 描述 |
|---|---|
| parseInt() | 解析一个字符串并返回一个整数 |
| parseFloat() | 解析一个字符串并返回一个浮点数 |
| isNaN() | 检查某个值是否是数字,返回 true / false |
| eval() | 计算 JavaScript 字符串,并把它作为脚本代码来执行 |
/*系统函数实例*/
parseInt("143dd") //将字符串转化为整数,结果为143
parseFloat("143.33dd") //解析一个字符串,并返回一个浮点数,结果为143.33分类二:自定义函数:
自定义函数方式一:
function 函数名 (参数1,参数2, ... ){
//函数代码块
}自定义函数方式二:
var 函数名 = function (参数1,参数2, ... ){
//函数代码块
}函数的调用
函数可以通过其名字加上括号中的参数进行调用。
JavaScript 自定义函数时,参数只需要声明变量名称,不需要使用
var。
函数的调用有以下两种方式:
-
事件名=函数名(传递的实参值),例如:onclick = "myFunction()"
-
直接使用
函数名(传递的实参值),例如:var result = add(2, 3);
函数的返回值
通过
return关键字返回函数的值
实例:
function sayHello(name){
return ( name + "说了句hello。" );
}
var str = sayHello("Fatli");
alert( str ); // Fatli说了句hello。与 Java 一样,函数在执行过
return语句后立即停止代码。因此,return语句后的代码都不会被执行。
分类三:匿名函数(属于自定义函数)
还有一种自定义函数,叫匿名函数 Anonymous Function ,即没有函数名。
存储在变量中的函数不需要函数名称。它们总是使用变量名称调用。
实例一:
// 自定义(匿名)函数
// The function ends with a semicolon(分号) because it is a part of an executable statement.
var x = function (a, b) {
return a * b;
};
// 匿名函数的调用:
var z = x(4, 3);实例二:
// 自定义(匿名)函数
var fn = function() {
alert(123);
};
// 匿名函数的调用:
fn();
// 括号()中直接写函数体,直接执行(匿名)函数
// 直接执行(匿名)函数,一般用于框架的封装
(function() {
alert(123);
})实例三:
// 直接执行 setInterval() 方法中的括号中匿名函数
// 直接执行 setInterval() 方法
// 3 秒后弹框显示 Hello
setInterval(function() {
alert("Hello");
}, 3000);附:匿名函数通常作为(内部)自调函数使用,是为 JavaScript Function Closures(闭包)
- https://www.w3schools.com/js/js_function_closures.asp
- http://www.w3school.com.cn/js/pro_js_functions_closures.asp
示例: https://github.com/tastejs/todomvc/blob/gh-pages/examples/vue/js/app.js
附:回调函数
当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。
打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数(to register a callback function)。
摘自:https://www.zhihu.com/question/19801131
实例1:
微信小程序中的回调函数(旧文档链接已失效):https://developers.weixin.qq.com/miniprogram/dev/api/device.html
新文档链接:https://developers.weixin.qq.com/miniprogram/dev/api/device/network/wx.getNetworkType.html
// 旧文档写法
wx.getNetworkType({
// 接口调用成功的回调函数
success: function(res) {
var networkType = res.networkType
}
})
// 新文档写法,回调函数简写
wx.getNetworkType({
// success函数是接口调用成功的回调函数
// 可以简写成这样:
success (res) {
const networkType = res.networkType
}
})// wx.onNetworkStatusChange(function callback)
// 监听网络状态变化事件
// 参数
// function callback
// 网络状态变化事件的回调函数
wx.onNetworkStatusChange(function (res) {
console.log(res.isConnected)
console.log(res.networkType)
})实例2: https://github.com/FatliTalk/vue_json_api/blob/gh-pages/index-new-loading%26filter.html :
// --snip--
// 用 Vue.js 实现 filter 过滤器效果
filteredList:function () {
function useRuler(people) {
return people.height > 100;
// 此处 } 后不能有逗号,
}
// 此处的useRuler是回调函数,作为参数传入到另一个函数filter中。
// 可以简单理解为filtet()过滤函数的执行需要一个过滤的标准,useRuler()这个回调函数就是这个标准:身高大于100
var newList = this.comments.filter(useRuler)
return newList;
},
// --snip--附一:箭头函数
ES6(ECMAScript 2015)允许使用“箭头”
=>定义函数。
1. 关于箭头函数
参考:
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
- http://es6.ruanyifeng.com/#docs/function#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0
箭头函数的渊源可以追溯到上古时期一个叫 Lambda 演算的东西。
数学家们喜欢用纯函数式编程语言,纯函数的特点是没有副作用,给予特定的输入,总是产生确定的输出,甚至有些情况下通过输出能够反推输入。要实现纯函数,必须使函数的执行过程不依赖于任何外部状态,整个函数就像一个数学公式,给定一套输入参数,不管是在地球上还是火星上执行都是同一个结果。
箭头函数要实现类似纯函数的效果,必须剔除外部状态。所以当你定义一个箭头函数,在普通函数里常见的 this、arguments、caller 在箭头函数是没有的。
2. 微信小程序中使用箭头函数
参考:
- https://blog.krimeshu.com/2017/02/27/tricks-from-es6-for-mina/
- https://blog.csdn.net/Legend_1937/article/details/80321773
-
ES6 中增加了箭头表达式,效果和匿名函数相似,但箭头表达式更为简练,且内部执行时的 this 与外侧一致,不再需要每次都额外增加变量引用了。
-
微信小程序里,对每个页面编写的代码逻辑,都作为生命周期钩子函数(如:onLoad, onShow, onUnload)和自定义函数(如:各类组件回调函数)写在 AppService 内。
-
这两种函数内,this 都指向当前 Page 对象,在这些函数里做的各种异步操作,回调内的 this 基本都应该仍然保持为当前 Page 对象。在这个情况下,使用箭头表达式可以减少重复的工作、也减少遗漏 this 时出错的几率。
// ES5
var net = require('../public/net');
Page({
data: {
list: []
},
onShow: function () {
var self = this;
net.get('/Index/getList', function (res) {
res = res || {};
var status = res.status,
data = res.data,
list = data.list;
if(status == 2) {
self.setData({list: list});
}
});
}
});
// ES6
import * as net from '../public/net';
Page({
data: {
list: []
},
onShow: function () {
net.get('/Index/getList', (res = {}) => {
let {status, data: {list}} = res;
if (status == 2) {
// 此处 this 的指向与 onShow 内一致,无需增加 self 变量
this.setData({list});
}
});
}
});再举一个例子,通过微信小程序提供的API wx.getSystemInfo(Object object) 获取屏幕高度。
API文档:https://developers.weixin.qq.com/minigame/dev/api/base/system/system-info/wx.getSystemInfo.html
// ES5
Page({
data: {
windowHeight: 0
},
onLoad() {
let _this = this;
wx.getSystemInfo({
success: function(res) {
_this.setData({windowHeight: res.windowHeight});
}
});
}
});
// ES6
Page({
data: {
windowHeight: 0
},
onLoad() {
wx.getSystemInfo({
// 这里的success函数是接口调用成功的回调函数,
// 并且这里的箭头=>不能省略,不能写成 success (res) {}
success: (res) => {
this.setData({windowHeight: res.windowHeight});
}
});
}
});3. 箭头函数使用场景
- 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如用在 map、reduce、filter 的回调函数定义中;
- 不要在最外层定义箭头函数,因为在函数内部操作 this 会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,将 this 控制在可见的范围内;
- 箭头函数最吸引人的地方是简洁。在有多层函数嵌套的情况下,箭头函数的简洁性并没有很大的提升,反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数。
附二:Javascript 方法
参考:
- https://www.liaoxuefeng.com/wiki/1022910821149312/1023023754768768
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Method_definitions
在一个对象中绑定函数,称为这个对象的方法。
在JavaScript中,对象的定义是这样的:
var student = {
name: 'Fatli',
birth: 1990
};但是,如果我们给 student 绑定一个函数,就可以做更多的事情。比如,写个 age() 方法,返回 student 的年龄:
var student = {
name: 'Fatli',
birth: 1996,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
console.log(student.age); //输出fatli.age的函数体内容
console.log(student.age()); //23