JavaScript 函数是通过 function 关键词定义的,既可以使用函数声明也可以使用函数表达式
函数声明
function functionName(parameters) {
要执行的代码
}
// 实例
function myFunction(a, b) {
return a * b;
}
// 分号用于分隔可执行的JavaScript语句
// 由于函数声明不是可执行的语句,以分号结尾并不常见
函数表达式
// JavaScript 函数也可以使用表达式来定义,函数表达式可以在变量中存储:
var x = function (a, b) {
return a * b
};
// 上述函数其实是一个匿名函数,存放在变量中的函数不需要函数名,它们总是使用变量名调用,其使用分号结尾是因为它是可执行语句的一部分
// 在变量中保存函数表达式之后,此变量可用作函数
var z = x(4,3)
函数的提升
提升(Hoisting)是JavaScript 将声明移动到当前作用域顶端的默认行为
Hoisting 应用于变量声明和函数声明
正因如此,JavaScript函数能够在声明之前被调用:
myFunction(5);
function myFunction(y) {
return y * y;
}
注意:使用表达式定义的函数不会被提升
函数是对象
JavaScript 中的 typeof 运算符会为函数返回 “function”。
但是最好是把 JavaScript 函数描述为对象,因为 JavaScript 函数都有属性和方法。
自调用函数
函数表达式可以作为“自调用”
自调用表达式是在不进行调用的情况下,自动被调用的
假如表达式后面跟着()
,函数表达式会自动执行
你无法对函数声明进行自调用,需要在函数周围添加括号,以指示它是一个函数表达式:
(function () {
var x = "Hello!"
})()
箭头函数
// ES5
var x = function(x,y) {
return x*y;
}
// ES6
const x = (x,y) => x*y;
/*
箭头函数没有自己的 this,它们不适合定义对象方法。
箭头函数不会被提升,所以它们必须在使用前进行定义。
使用 const 比使用 var 更安全,因为函数表达式始终是常量值。
如果函数是单个语句,则只能省略 return 关键字和大括号。但是,保留它们是一个好习惯:
*/
const x = (x,y) => {return x * y};
// 注意:IE11或更早的版本不支持箭头函数
函数参数
函数参数(parameter)指的是在函数定义中列出的名称。
函数参数(argument)指的是传递到函数或由函数接收到的真实值。
参数规则:
-
JavaScript 函数定义不会为参数(parameter)规定数据类型;
-
JavaScript 函数不会对所传递的参数(argument)实行类型检查;
-
JavaScript 函数不会检查所接收参数(argument)的数量
参数默认:
- 如果调用参数时省略了参数(少于被声明的数量),则丢失的值被设置为:
undefined
- 如果函数调用的参数太多(超过声明),则可以使用 arguments 对象来获取这些参数
- JavaScript 函数有一个名为 arguments 对象的内置对象
- arguments 对象包含函数调用时使用的参数数组
arguments.length
会返回函数被调用时收到的参数数目
JavaScript函数Call和apply
方法重用:使用call()
方法,可以编写能够在不同对象上使用的方法
函数是对象方法
在JavaScript中,函数是对象的方法
如果一个函数不是JavaScript 对象的方法,那么它就是全局对象的函数
JavaScript call()方法
call()
方法是预定义的JavaScript方法,它可以让你使用属于另一个对象的方法
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates",
}
var person2 = {
firstName:"Steve",
lastName: "Jobs",
}
// 调用person的fullname方法,并用于person1
person.fullName.call(person1); // 将返回 "Bill Gates"
带参数的call()方法
call()
方法可以接受参数
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates"
}
person.fullName.call(person1, "Seattle", "USA");
JavaScript aplly()方法
apply()
方法与 call()
方法非常相似
var person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = {
firstName: "Bill",
lastName: "Gates",
}
person.fullName.apply(person1); // 将返回 "Bill Gates"
call()和apply()之间的区别
call() 方法分别接受参数。
apply() 方法接受数组形式的参数。
如果要使用数组而不是参数列表,则 apply() 方法非常方便。
带参数的apply()方法
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"John",
lastName: "Doe"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);
与call()方法对比
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"John",
lastName: "Doe"
}
person.fullName.call(person1, "Oslo", "Norway");
闭包
JavaScript变量属于局部或全局作用域
全局变量能够通过闭包实现局部(私有)
注意:不通过关键词 var
创建的变量总是全局的,即使它们在函数中创建
变量的生命周期
全局变量活得和应用程序(窗口、网页)一样久
局部变量活得不长。它们在函数调用时创建,在函数完成后被删除
JavaScript嵌套函数
所有函数都有权访问全局作用域,事实上,在 JavaScript 中,所有函数都有权访问它们“上面”的作用域
JavaScript 支持嵌套函数,嵌套函数可以访问其上的作用域,例如:
// 内部函数 plus() 可以访问父函数中的 counter 变量
function add() {
var counter = 0;
function plus() {counter += 1;}
plus();
return counter;
}
add() // 将返回1
JavaScript闭包
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
// 计数器目前是 3
// 变量 add 的赋值是自调用函数的返回值。
// 这个自调用函数只运行一次。它设置计数器为零(0),并返回函数表达式。
// 这样 add 成为了函数。最“精彩的”部分是它能够访问父作用域中的计数器。
// 这被称为 JavaScript 闭包。它使函数拥有“私有”变量成为可能。
// 计数器被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。
// 闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。
闭包的更多介绍:
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
https://www.cnblogs.com/itjeff/p/10106855.html