一函数的一些基础概念:
1.js 中的函数使用 function 来声明
2. 关于 return:
2.1 函数在执行到 return 语句后悔立即停止并退出, return 后面的代码永远不会得到执行;
2.2 函数不必指定是否返回值, 只要 return 语句后跟要返回的值即可实现返回值;
2.3 return 语句不带任何返回值时, 会返回 undefined 值, 这种做法一般用在需要提前停止函数执行而又不需要返回值的情况
3. 理解参数:
3.1 函数不介意传递进来参数个数以及类型, 因为 js 中的参数在内部是用一个数组来表示的, 函数接收到的始终是这个数组, 至于数组中包含的内容并不关心
(即使你定义的函数只接收两个参数, 那么你传递一个或三个或不传参数都无所谓);
3.2 可以使用 arguments 对象来访问参数数组, arguments[i] 来访问第 i+1 个参数, arguments.length 确定传递进来的参数的个数;
3.3 没有传递值的命名参数将被自动赋值 undefined;
3.4 js 中所有的参数都是值传递, 没有引用传递;
4. 没有重载: 如果出现两个相同名字的函数, 后者会覆盖前者但是我们可以控制传递参数的类型和数量让函数做出不同的反应, 从而模仿重载的实现
二深入理解 Function 类型
JS 中 Function 类型实际上是一种对象, 每一个函数实际上都是 Function 类型的一个实例, 函数通常是使用函数声明语法定义的, 每一个函数都有一些默认的属性和方法;
由于函数是对象, 故函数名实际上也是一个指向函数对象的指针变量, 不会与某个函数绑定, 函数是对象, 函数名是指针
1. 函数声明与表达式
函数声明会优先被读取使用 (可以提前访问)
- console.log(test(10,10))//20
- function test(num1,num2) {
- return num1+num2;
- }
函数表达式则必须等到执行完它所在的表达行后再可以使用
- console.log(test(10,10))// 会报错
- var test = function (num1,num2) {
- return num1+num2;
- };
2. 作为值的函数
js 中的函数名本身就是变量, 所以函数也可以作为值来使用, 可以像传递参数一样把一个函数传递给另一个函数
- function sum (num1, num2) {
- return num1 + num2;
- }
- function fuc (num3, num4) {
- return num3 + num4;
- }
- console.log(fuc(sum(2,3), 5));//10
js 中的函数名本身就是变量, 所以可以将一个函数作为另一个函数的结果返回
- function sum (num1, num2) {
- return num1+num2;
- }
- function func(num1){
- return sum(num1,10);
- }
- alert(func(10)); //20
3. 函数内部属性
在函数内部包含两个特殊的对象: arguments 和 this
arguments:
arguments 是一个类数组, 用来保存函数传递过来的参数
arguments 中还有一个很重要的属性就是 callee, 是一个指针变量, 指向的是 arguments 所在的函数本身, 在递归的时候最好用这个属性, 因为如果函数名改变了, 也不需要改变内部的实现, arguments.callee() 始终代表的是这个函数本身
- // 用 arguments.callee 的好处是, 当函数名改变了以后, 不需要改动递归出的函数,
- function box(num) {
- if (num <= 1) {
- return 1;
- } else {
- return num * arguments.callee(num - 1);
- //arguments.callee 代表的是函数的本身, 故和上面是同样的效果
- }
- }
- alert(box(3)); //6
- this:
this 这个属性代表的是它所在的对象本身, this 引用的是函数据以执行的环境对象, 也就是函数执行的作用域
window 是 JS 中最大的一个对象, 在 window 对象中声明一个变量其实就是给 window 这个对象声明一个属性, var box=1; 相当于 window.box=1; 也就等价于 this.box=1;
当在全局作用域中调用函数时, this 对象引用的就是 window
在显示的声明一个对象 box, 这个 box 中使用的 this 就代表的是 box 本身, this.color 就是返回的 box 中属性 color 的值, 而不是 window 对象中 color 的值
- // this 代表的是对象本身, 下面在对象 box 中的 this, 就代表对象 box
- var color = '红色'; // window 对象的属性,
- var box = {
- color: '蓝色',
- run: function() {
- alert(this.color); // 蓝色
- return this.color;
- }
- }
- alert(window.color); // 红色
- alert(this.color); // 红色 此处 this 代表的是 window 对象, 故 this.color 是代表的 window 的属性
- alert(box.run()); // 蓝色
4. 函数的属性和方法
每个函数都包含两个属性: length 和 prototype
length: 函数的属性 length 代表的是函数希望接收的参数的个数, 是由声明函数时参数列表中的个数决定的
prototype:prototype 是保存所有实例方法的真正所在, 也就是原型
prototype 下面有两个方法 apply(),call(), 这两个方法都是函数非继承而来的方法, 是每一个函数都具有的方法
这两个方法的用途都是在特定的作用域中调用函数 (看 this 指向的作用域是谁), 也就是说调用特定的对象下面调用函数, 有点类似于 C# 的反射中调用对象的方法
- function sum (num1, num2) {
- return num1 + num2;
- }
- var result = sum.apply(this,[10,20]);
- var result = sum.call(this,10,20);
- console.log(result);
func.apply(): 这个方法有两个参数, 第一个是要执行这个方法的作用域, 也就是传递一个对象过去, 第二个参数是一个数组, 这个数组中是存放的调用的函数 func 的实参, 也就是要传递给 func 的值, 当然第二个参数可以省略
func.call(): 这个方法和上面的 apply() 方法是一样的, 不同的是参数, 第一个同样是作用域, 是一样的, 其余的参数是逐个列举出啦传递给函数的, 而不是传递一个数组过去
- var color = 'red';
- var box = {
- color: 'green'
- }
- function sayColor() {
- return this.color;
- }
- alert(sayColor()); //red 对象是 window
- alert(sayColor.apply(window)); //red 对象是 window
- alert(sayColor.apply(this)); //red 对象是 window
- alert(sayColor.apply(box)); //green 对象是 box
使用这 apply() 和 call() 这两个方法来扩充作用域最大的好处是对象不需要与方法发生任何的耦合关系, 也就是上面说的对象中可能不存在这个方法, 但只要存在这个对象就 OK
来源: https://www.cnblogs.com/chaixiaozhi/p/6718110.html