函数是什么

基本概念

函数,是可复用的代码块,它允许你在一个代码块中存储一段用于处理单任务的代码,然后在任何你需要的时候用一个简短的命令来调用。

浏览器内置函数

或许你已经用过很多浏览器内置函数了。比如:

  • replace() 将字符串中的某串字符用另一串字符代替
  • join() 将数组变成字符串
  • Math.random() 生成一个随机数
  • ……

函数与方法

程序员把函数称为对象方法(method)的一部分。严格说来,内置浏览器函数并不是函数——它们是方法

二者区别在于方法是在对象内定义的函数。浏览器内置函数(方法)和变量(称为属性)存储在结构化对象内,以使代码更加高效,易于处理。

this

我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。

this的不同的情况:

  • 以函数的形式调用时,thiswindow
  • 以方法的形式调用时,this就是调用方法的对象
  • 以构造函数的形式调用时,this就是新创建的对象

自定义函数

方式一:

1
2
3
4
function 函数名([形参1,形参2...形参N]){  
语句...
}
123

方式二:

1
2
3
var 函数名 = function([形参1,形参2...形参N]){  
语句...
};

调用函数

1
函数名([实参1,实参2…实参N]);

匿名函数

可以创建一个没有名称的函数:

1
2
3
function() {
语句...
}

这个函数叫做匿名函数 — 它没有函数名! 它也不会自己做任何事情。 你通常将匿名函数与事件处理程序一起使用, 例如,如果单击相关按钮,以下操作将在函数内运行代码:

1
2
3
4
5
var myButton = document.querySelector('button');

myButton.onclick = function() {
alert('hello');
}

函数参数

一些函数需要在调用它们时指定参数 ——这些参数值需要放在函数括号内,才能正确地完成其工作。

参数又分为形参实参

形参

形式参数

  • 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
  • 定义形参就相当于在函数内声明了对应的变量但是并不赋值
  • 形参会在调用时才赋值

实参

实际参数

  • 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参
  • 调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值
    • 如果实参的数量大于形参,多余实参将不会赋值,
    • 如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined

函数的返回值

通常,返回值是用在函数在计算某种中间步骤。你想得到最终结果,其中包含一些值。那些值需要通过一个函数计算得到,然后返回结果可用于计算的下一个阶段。

  • 返回值,就是函数执行的结果
  • 使用return来设置函数的返回值
    • 语法:return 值;
  • 该值就会成为函数的返回值,可以通过一个变量来接收返回值
  • return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出
  • return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象
  • 如果return后不跟值,或者是不写return,函数默认返回undefined

函数的作用域和冲突

我们来谈一谈 scope 即作用域 — 处理函数时一个非常重要的概念。当你创建一个函数时,函数内定义的变量和其他东西都在它们自己的单独的范围内,不能被函数外的代码访问。

所有函数的最外层被称为全局作用域。 在全局作用域内定义的值可以在任意地方访问。

全局作用域

  • 直接在script标签中编写的代码都运行在全局作用域中
  • 全局作用域在打开页面时创建,在页面关闭时销毁
  • 全局作用域中有一个全局对象windowwindow对象由浏览器提供
    • 可以在页面中直接使用,它代表的是整个的浏览器的窗口
    • 在全局作用域中创建的变量都会作为window对象的属性保存
    • 在全局作用域中创建的函数都会作为window对象的方法保存
  • 在全局作用域中创建的变量和函数可以在页面的任意位置访问
  • 尽量不要在全局中创建变量

函数作用域

  • 函数作用域在函数执行时创建,在函数执行结束时销毁,每次调用函数都会创建一个新的函数作用域
  • 在函数作用域中创建的变量,不能在全局中访问
  • 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找
    • 如果找到了则直接使用,如果没有找到则到上一级作用域中寻找

冲突

有时我们不希望变量可以在代码中的任何地方访问 - 从其他地方调用的外部脚本可能会开始搞乱代码并导致问题,因为它们恰好与代码的其他部分使用了相同的变量名称,就会造成冲突