深入理解Function类型

1.函数是对象,函数名是指针

  函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

function sum(num1, num2){
    return num1 + num2;
}
alert(sum(10,10)); //20 

var anotherSum = sum;
alert(anotherSum(10,10)); //20 

sum = null;
alert(anotherSum(10,10)); //20

以上代码定义了一个名为sum()函数,又声明了一个anotherSum与sum相等。当将sum设置为null时,因为不带括号是函数指针名不是调用函数,所以只是将函数指针设为null。anotherSum则可以继续调用函数。

2.没有重载

  将函数名想象为指针,就可以理解为什么JavaScript中没有函数重载。

function add(num){
    return num + 100;
}
function add(num){
    return num + 200;
}

var result = add(100); //300

以上代码声明了两个同名函数,而结构则是后面的函数覆盖了前面的函数,实际上覆盖了引用第一个函数的变量add。


3.函数声明与函数表达式

  解释器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解释器会率先读取函数声明,并使其执行任何代码之前可用;至于函数表达式,则必须等到解释器执行到它所在的代码行,才会真正被解释执行。

alert(add(100));
function add(num){
    return num + 100;
}

以上代码完全可以正常运行。因为代码开始之前,解释器已经通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中。如果把上面的函数声明改为函数表达式则会在执行期间导致错误。

alert(add(100));
var add = function(num){
    return num + 100;
}

在执行期间会导致“unexpected identifier”(意外标识符)的错误。因为在调用时add并未声明。


4.函数属性和方法

  每个函数都包含两个属性:length和prototype。其中length表示参数个数,而prototype则是JavaScript基于原型的面向对象中最重要的一个属性,它保存了类似于父类的对象的属性和方法。 每个函数也都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

  apply()方法接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组。

function sum(num1, num2){
    return num1 + num2;
}
function applySum(num1, num2){
    return sum.apply(this,arguments);
    // OR return add.apply(this, [num1,num2]);
}
alert(sum(10,10)); //20
alert(applySum(10,10)); //20

call()方法和apply()方法的作用相同,它们的区别仅在于接受参数的方式不通。对于call()方法,第一个参数与apply()方法一样,而其余参数都是直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来。

function sum(num1, num2){
    return num1 + num2;
}
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20

至于使用apply()还是call(),完全取决于你采取哪种给函数传递参数的方式最方便。在不给函数传递参数的情况下,两个方法都一样。

  事实上,传递参数并非apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。

window.color = "red";
var o = { color: "blue" };

function sayColor(){
    alert(this.color);    
}

sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue

  使用call()或者apply()来扩充作用域最大的好处,就是对象不需要与方法有任何耦合关系。当不需要参数情况下,也可以通过bind()来扩充作用域。


更多精彩:点击打开链接

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值