了解函数,我们首先要从函数的定义方法开始了解。
1、函数的定义
与java中不同,JavaScript中的函数有两种定义方法,第一种和java中相同,直接写出 function XX ( 参数信息 ) { 函数内容 } 即可。
另一种定义方式类似于之前的变量定义,新建一个var变量,然后将function的值赋给他,同时在function后面提供函数的相关信息,比如参数和函数体等。
图1.1 函数的两种定义方法
当我们试图调用函数时,我们需要给函数提供参数。之前我们已经说过,JavaScript是一门不“严谨”的语言,因此我们在提供参数的时候可以随意提供参数的个数,并且我们调用函数时试图传给函数的每个参数都能在函数中正常获取。区别就是我们函数声明的时候定义的几个参数会一一对应的传入,而多出来的参数需要我们用别的方法获取。JavaScript为我们提供了两种获取这些参数的方法:
首先,我们可以通过arguments来获取传入的所有参数,包括正常赋值的和多余的参数。同时,arguments还提供了.length方法,让我们可以获取参数的个数。
另一种方法是采用rest方法来获取所有多余的参数,类似arguments中,rest也有。length方法,让我们可以获取多余参数的个数。注意,如果使用rest的话我们要在函数声明的时候在参数后加上,,,rest,才能让rest数组生效。
图1.2 rest与arguments方法获取多余参数
我们了解了两种方法之后,这两种方法的区别是什么呢?首先,摆在眼前的区别就是一个是获取所有参数,一个是获取剩余参数。另一个区别是rest是一个真实的数组,而argument只是一个“类数组对象”,一个含有length属性的对象。
2、作用域
当我们涉及到函数之后,我们就不得不提及另一个问题,那就是定义的变量的作用域。
作用域的第一条规则就是若无同名对象,函数内部可访问外部的对象,若同名,则在函数内部,变量会覆盖来自外部的变量,而外部仍访问外部的变量。由于这种规则,如果两个没有包含关系的函数中定义了同名对象,则他们会互不干扰的存在。
图2.1 作用域的基础规则
如果我们拿到了别人的代码,在未定义的情况下使用的一个新变量的话会怎么样呢?
图2.2 变量的作用域扩展
显然,我们的变量被JavaScript自动定义了,同时赋值“undefined”,我们的定义在后面,而前面却正常的使用了该变量,这就是变量作用域的“扩张”。
在C语言,Java等中都存在“全局变量”一说,显然,在JavaScript中也存在类似的说法。我们定义的每一个“全局”变量,或者函数,都被存在Windows对象下,如果我们使用对象的访问方法,即 Windows.变量名 来访问所有“全局”的内容,仍能正常访问。这也就是说,JavaScript帮助我们定义的一些函数会被我们无意中重写。因此,我们可以采用新定义一个对象,并将自己定义的所有内容放在该对象下的方法避免这种情况的产生。
图2.3 Windows访问“全局”内容
如果我们想避免自己定义的内容被更改,我们也可以使用const修饰符来定义内容,防止内容被他人修改。相对的,如果我们只是想简单的使用一个变量,我们可以使用let修饰符来修饰变量,类似局部变量,let修饰符修饰的变量在使用完成之后就会被丢弃。
3、方法
我们之前已经学过了对象的定义,如果我们的一个对象中,有一个属性,他的属性值是一个函数,如 grade:function ( ) { },那么这个函数就可以被称为这个对象的方法,而属性的名称就是函数的函数名。我们可以在对象外通过调用类似调用对象属性的方法调用方法。
图3.3 方法的定义和调用
当然,和别的语言一样,JS中的函数也有this指针的使用,这里的this指向的是调用它的当前对象,如果我们再Windows下调用方法,那么this就会去寻找Windows下的该对象,而如果未找到,就会输出错误的结果。
那么我们能不能控制this指针的指向呢?答案是肯定的,我们可以通过apply方法来控制this指针的指向,apply中有两个参数,第一个参数是我们想让函数的this指针指向的对象,而后面则是我们给该函数提供的参数组,用【】括起来。
图3.4 this指针的控制
这里需要注意各个位置函数的括号是否添加,比如student中getAge就没有添加括号,即定义的age仍是一个方法,因此在最后输出consol的时候age需要加上括号。在getAge调用apply的时候后没有加上括号,要注意书写的格式。(不考虑js框架,纯JavaScript代码,除了使用apply和call调用之外,函数调用都要加括号)use strict加与不加都不影响最后两次结果的输出。
原文:https://www.cnblogs.com/winteriscomming/p/15107885.html