函数是什么
基本概念
函数,是可复用的代码块,它允许你在一个代码块中存储一段用于处理单任务的代码,然后在任何你需要的时候用一个简短的命令来调用。
浏览器内置函数
或许你已经用过很多浏览器内置函数了。比如:
replace()
将字符串中的某串字符用另一串字符代替join()
将数组变成字符串Math.random()
生成一个随机数- ……
函数与方法
程序员把函数称为对象方法(method)的一部分。严格说来,内置浏览器函数并不是函数——它们是方法。
二者区别在于方法是在对象内定义的函数。浏览器内置函数(方法)和变量(称为属性)存储在结构化对象内,以使代码更加高效,易于处理。
this
我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
使用this
来引用上下文对象,根据函数的调用形式不同,this
的值也不同。
this的不同的情况:
- 以函数的形式调用时,
this
是window
- 以方法的形式调用时,
this
就是调用方法的对象 - 以构造函数的形式调用时,
this
就是新创建的对象
自定义函数
方式一:
1 | function 函数名([形参1,形参2...形参N]){ |
方式二:
1 | var 函数名 = function([形参1,形参2...形参N]){ |
调用函数
1 | 函数名([实参1,实参2…实参N]); |
匿名函数
可以创建一个没有名称的函数:
1 | function() { |
这个函数叫做匿名函数 — 它没有函数名! 它也不会自己做任何事情。 你通常将匿名函数与事件处理程序一起使用, 例如,如果单击相关按钮,以下操作将在函数内运行代码:
1 | var myButton = document.querySelector('button'); |
函数参数
一些函数需要在调用它们时指定参数 ——这些参数值需要放在函数括号内,才能正确地完成其工作。
参数又分为形参和实参
形参
形式参数
- 定义函数时,可以在
()
中定义一个或多个形参,形参之间使用,
隔开 - 定义形参就相当于在函数内声明了对应的
变量
但是并不赋值 - 形参会在调用时才赋值
实参
实际参数
- 调用函数时,可以在
()
传递实参,传递的实参会赋值给对应的形参 - 调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值
- 如果实参的数量大于形参,多余实参将不会赋值,
- 如果实参的数量小于形参,则没有对应实参的形参将会赋值
undefined
函数的返回值
通常,返回值是用在函数在计算某种中间步骤。你想得到最终结果,其中包含一些值。那些值需要通过一个函数计算得到,然后返回结果可用于计算的下一个阶段。
- 返回值,就是函数执行的结果
- 使用
return
来设置函数的返回值- 语法:
return 值;
- 语法:
- 该值就会成为函数的返回值,可以通过一个变量来接收返回值
return
后边的代码都不会执行,一旦执行到return
语句时,函数将会立刻退出return
后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象- 如果
return
后不跟值,或者是不写return
,函数默认返回undefined
函数的作用域和冲突
我们来谈一谈 scope 即作用域 — 处理函数时一个非常重要的概念。当你创建一个函数时,函数内定义的变量和其他东西都在它们自己的单独的范围内,不能被函数外的代码访问。
所有函数的最外层被称为全局作用域。 在全局作用域内定义的值可以在任意地方访问。
全局作用域
- 直接在
script
标签中编写的代码都运行在全局作用域中 - 全局作用域在打开页面时创建,在页面关闭时销毁
- 全局作用域中有一个全局对象
window
,window
对象由浏览器提供- 可以在页面中直接使用,它代表的是整个的浏览器的窗口
- 在全局作用域中创建的变量都会作为
window
对象的属性保存 - 在全局作用域中创建的函数都会作为
window
对象的方法保存
- 在全局作用域中创建的变量和函数可以在页面的任意位置访问
- 尽量不要在全局中创建变量
函数作用域
- 函数作用域在函数执行时创建,在函数执行结束时销毁,每次调用函数都会创建一个新的函数作用域
- 在函数作用域中创建的变量,不能在全局中访问
- 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找
- 如果找到了则直接使用,如果没有找到则到上一级作用域中寻找
冲突
有时我们不希望变量可以在代码中的任何地方访问 - 从其他地方调用的外部脚本可能会开始搞乱代码并导致问题,因为它们恰好与代码的其他部分使用了相同的变量名称,就会造成冲突。
GitHub Issues