版权声明:本文为博主原创文章,若转载请注明出处且不得删改。(如有错误请提出指正,部分文章会参考其他文章,已经表明参考出处,如有侵权请联系删除) https://blog.csdn.net/qq_34902437/article/details/81299583
参考 《JavaScript 高级程序设计》引用类型-Function
函数定义的三种方式
函数声明方式
function method(){
return 0;
}
函数表达式方式
var method = function(){
return 0;
}
构造函数方式
var method = new Function("return 0");
理解 JavaScript 中没有重载
重载是指函数名相同,但是函数参数类型和个数不同
function sum(n1,n2,n3){
return n1+n2+n3;
}
function sum(n1,n2){
return n1+n2;
}
// 20
alert(sum(10,10,10));
// 20
alert(sum(10,10));
我们从函数对象的角度再来理解就很容易了。
var sum = function(n1,n2,n3){
return n1+n2+n3;
}
// sum 的指向被覆盖了
sum = function(n1,n2){
return n1+n2;
}
// 20
alert(sum(10,10,10));
// 20
alert(sum(10,10));
函数声明与函数表达式
函数声明和函数表达式在定义函数的时候并无差别,除了一点,函数声明提升
(function declaration hoisting)。
意思就是函数声明的方式定义函数,解析器会提前解析函数声明,而函数表达式
只有执行到代码段才解析。
// 20
alert(sum(10,10));
function sum(n1,n2){
return n1+n2;
}
//报错
alert(sum(10,10));
var sum = function(n1,n2){
return n1+n2;
}
其实很容易理解,函数表达式实际上是对象指针,你还没有对象的时候怎么能指向它呢
?
函数作为值来使用
因为函数名本身就是变量,所以函数可以作为值来使用,也就是函数可以作为参数,以及作为另一个函数的返回结果。
函数作为参数
var add = function(n1){
return n1+10;
}
function sum(someFunction,n2){
return someFunction(n2);
}
// 20
alert(sum(add,10));
函数内部属性
arguments 的 callee(被叫者) 属性
callee 属性是一个指针,指向拥有 arguments 对象的函数。
我们用一个例子来说明
这是一个常见的阶乘函数。
function jiecheng(num){
if(num <= 1){
return 1;
}else{
return num * jiecheng(num-1);
}
}
但问题是,这个函数耦合性太强,一旦改动,整个函数都会发生变化。
实现解耦
function jiecheng(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1);
}
}
// 函数指针发生改变
var jiecheng2 = jiecheng;
this 属性
this 属性是当前执行环境的对象,如果是全局作用域,则是 window。
window.color = 'black';
// 定义一个变量对象
var o = {color:"blue"};
function sayColor(){
alert(this.color);
}
// black
sayColor();
//为对象 o 新增一个 sayColor 的方法,该方法指向全局作用域下的
//sayColor()
o.sayColor = sayColor;
// blue
o.sayColor();
PS:函数名仅仅是一个包含指针的变量而已。例如有函数 say(),如果只是 say 的话,就是函数指针,say()才是执行函数。
caller 属性
caller 属性保留调用当前函数的函数的引用。
上面的定义很拗口,我们通过一个实际的例子来解释。
function outer(){
inner();
}
function inner(){
alert(inner.caller);
}
outer();
//outer()执行之后显示的是 outer()函数内部的源代码
//所谓保存当前函数(inner)的函数(outer)的引用(指针)。
函数属性和方法
两个属性
length
length 返回的是函数命名参数的个数。
function a(){
}
function b(n1){
}
// 0
alert(a.length);
// 1
alert(b.length);
prototype
prototype 保存所有实例方法的真实所在。
方法
apply()和call()
两个方式都是在特定作用域调用函数。
apply(this,arguments)-参数1:运行函数作用域,-参数2:参数数组
call(this,arguments) -参数1:运行函数作用域,-参数2:参数对象
在参数上二者的区别是,apply 一般用于以数组的形式传递参数(参数多),而 call 则是一个个传递参数。
下面注重讲二者的意义-扩充作用域范围
window.color = 'blue';
var o = {color:'black'};
function sayColor(){
alert(this.color);
}
sayColor();
//blue,此时作用域为全局,this 自动转换为 window
sayColor.call(this);
//blue,此时作用域为全局
sayColor.call(window);
//black,此时作用域为对象 o,this 自动转换为 o 的this
sayColor.call(o);
bind()
创建一个函数实例,this 的作用域会被绑定传递到使用 bind()的函数上
var o = {color:'black'};
function sayColor(){
alert(this.color);
}
// 此时新函数 other 被指向 sayColor 函数且绑定了作用域 o
var other = sayColor.bind(o);
// black
other();