JavaScript 函数
函数是将复用的代码块封装起来的模块,它允许你在一个代码块中存储一段用于处理单任务的代码,然后在任何你需要的时候用一个简短的命令来调用,而不是把相同的代码写很多次。
声明定义
在js中函数是Function类的创建实例,所以可以使用类的实例化方式声明定义函数
let func = new Function("txt","console.log(txt)");
func("hello world"); // 输出:hello world
最常用的方式是采用函数定义的方式来定义函数
function func(txt)
{
console.log(txt);
}
func("hello world");//输出 hello world
函数作为对象成员
let student =
{
firstName : "张",
lastName : "三",
getName : function()
{
console.log(`${this.firstName} ${this.lastName}`);
}
}
student.getName(); // 输出: 张 三
全局函数
声明在全局的函数被称为全局函数,全局函数和全局变量一样会声明在window对象中,会将window对象中的同名函数覆盖。这种操作方式是不建议的,容易覆盖掉重要的window对象的属性,建议使用模块处理。
console.log(window.screenX); //2200
当我们定义了 screenX 函数后就覆盖了window.screenX方法
function screenX() {
return "hello world";
}
console.log(screenX()); //hello world
函数提升
使用函数表达式定义的函数 和 用var关键字创建的函数都是全局的变量,都存在变量提升
sum(2,3); // 发生变量提升:输出5
function sum(x,y)
{
console.log(x + y);
}
变量函数定义不会被提升
sum(2,3); // 报错
let sum = function (x,y)
{
console.log(x+y);
}
匿名函数
所谓匿名函数指的就是没有签名的函数,在某些场景下,我们不需要复用我们的函数。一般是将函数作为右值传递,最常见在于赋值给函数形参。(类似C++的函数指针)
//将匿名函数传递给变量sum
let sum = function(x,y)
{
return x + y;
}
console.log(sum(2,3)); // 输出:5
let arr = [1,2,3,4];
//使用匿名函数给arr.reduce传递参数,求和
let sum = arr.reduce(function(tatol,value)
{
return tatol += value;
});
console.log(sum); // 输出: 10
箭头函数(lambda 表达式)
箭头函数是匿名函数的一种简写形式,是js提供的一种语法糖 ,格式如下: (参数列表) => {函数体}
如果函数体只有一个返回语句,可以省略大括号和return语句。如果只有一个参数可以省略小括号,没有参数则用一对空的小括号表示,不可省略。
let sum = (x,y)=> x + y;
// 等效于let sum = function(x,y){return x+y;}
console.log(sum(x,y));
- 箭头函数下的this的坑:
在js中,箭头函数自身没有this
, 箭头函数中的this 会继承定义函数时的上下文,和外层函数指向同一个this。也就是说箭头函数里的this指的是它的上一层环境。
形参实参
形参是在函数声明时设置的参数,实参指在调用函数时传递的值。
- 当函数定义的参数大于调用时传递的参数时,即参数没有传够时,js不会报错,未传递的参数值为undifine
- 当函数定义的参数小于调用时传递的参数时,即参数传多了时,js也不会报错,从前往后参数传够了后面的被忽略
function func(x,y,z)
{
console.log(`x = ${x},y = ${y}, z = ${z}`);
}
//参数传少了
func(1,2);//x = 1,y = 2, z = undefined
//参数传多了
func(1,2,3,4);//x = 1,y = 2, z = 3
默认参数
对于一些形参,我们希望它们不被赋值时也能拥有一个初始值,拥有初始值的参数就被称为默认参数,还是用上面传少的例子这次给z添加默认值。
function func(x,y,z = 1)
{
console.log(`x = ${x},y = ${y}, z = ${z}`);
}
//参数传少了
func(1,2);//x = 1,y = 2, z = 1
注意:为了使得默认参数有意义,默认参数只能放在常规参数的后面,否则浏览器将无法确定是省略的哪个参数。
function func(x,y = 1,z )
{
console.log(`x = ${x},y = ${y}, z = ${z}`);
}
//参数传少了
func(1,2);//x = 1,y = 2, z = undefined
发生了意料之外的情况,当我们传递两个参数时,浏览器会将2传递给y
arguments
arguments 是函数获得到所有参数集合,下面是利用 arguments 和箭头函数求和的例子
function sum()
{
return[...arguments].reduce((total,value)=> total+=value);
}
console.log(sum(1,2,3,4)); // 10
- 箭头函数没有arguments
回调函数
在某个时刻被其他函数调用的函数称为回调函数,例如上面的数组array
的成员函数reduce
其实就是接受了一个回调函数,我们用箭头函数代替了回调函数。
apply/call/bind
改变this指针,也可以理解为对象借用方法。三者都可以改变构造函数中的空对象,即让函数里的this指向到另一个对象。
apply和call的区别仅仅在于传递的参数不同,而bind的不同点在于,apply和call在被绑定后都会立即执行,而bind并不会立即执行。
let a ={};
let b ={};
let c ={};
function func(name)
{
this.name = name;
//输出func的this
console.log(this.name);
}
//使用apply、call绑定的区别在于apply传入一个数组,而call传入对象
func.call(a,"张三"); //输出 : 张三
func.apply(b,["李四"]);//输出 : 李四
//而使用bind不会立即执行函数
func.bind(c,"王五"); //不执行函数