从上面的示例中可以发现apply的第2个参数是一个数组,数组中的内容将映射到被调用方法的参数中,如果单这样看发现不如call方便,其实如果直接取方法的参数arguments则apply要方便一些。通过简单的变化就可以替代call。
function display(){ show.apply(jack,arguments); } display("hi","224cm");
结果:
hi:jack,20,224cm
javascript里call和apply操作符可以随意改变this指向
如果在javascript语言里没有通过new(包括对象字面量定义)、call和apply改变函数的this指针,函数的this指针都是指向window的。
关于this指针,我的总结是:是谁调用的函数,那么这个函数中的this指针就是它;如果没有明确看出是谁调用的,那么应该就是window调用的,那么this指针就是window。
3.3.3、caller
在一个函数调用另一个函数时,被调用函数会自动生成一个caller属性,指向调用它的函数对象。如果该函数当前未被调用,或并非被其他函数调用,则caller为null。
在JavaScript的早期版本中,Function对象的caller属性是对调用当前函数的函数的引用
function add() { console.log("add被调用"); //add方法的调用函数,如果调用add方法的不是函数则为null console.log(add.caller); } function calc(){ add(); } //直接调用add方法 add(); //间接通过calc方法调用 calc();
运行结果:
caller与this还是有区别的,this是指调用方法的对象,而caller是指调用函数的函数。
<script type="text/javascript"> function add(n) { console.log("add被调用"); if(n<=2){ return 1; } return add.caller(n-1)+add.caller(n-2); } function calc(n){ console.log("calc被调用"); return add(n); } //1 1 2 console.log(calc(3)); </script>
结果:
3.3.4、Callee
当函数被调用时,它的arguments.callee对象就会指向自身,也就是一个对自己的引用
function add(n1,n2){ console.log(n1+n2); //arguments.callee(n1,n2); //指向add方法 return arguments.callee; } add(1,2)(3,4)(5,6)(7,8)(8,9);
运行结果:
当第1次调用add方法时输入3,立即将函数返回再次调用,每次调用后又返回自己,这样可以实现链式编程。
3.5、立即执行函数表达式 (IIFE)
IIFE即Immediately-Invoked Function Expression,立即执行函数表达式
3.5.1、匿名函数与匿名对象
匿名函数就是没有名称的函数,javascript中经常会使用匿名函数实现事件绑定,回调,实现函数级的私有作用域,如下所示:
function(){ console.log("这是一个匿名函数"); };
匿名对象:
{ name:"foo", show:function(){ console.log(this.name); } }
没有名称的匿名函数也叫函数表达式,它们间是有区别的。
3.5.2、函数与函数表达式
下面是关于函数与函数表达式定义时的区别
a)、函数定义(Function Declaration)
function Identifier ( Parameters ){ FunctionBody }
function 函数名称(参数){函数主体}
在函数定义中,参数(Parameters)标识符(Identifier )是必不可少的。如果遗漏,会报提示错误:
代码:
function(){ console.log("这是一个匿名函数"); };
结果:
b)、函数表达式(Function Expression)
function Identifier(Parameters){ FunctionBody }
函数表达式中,参数和标识符都是可选的,与函数定义的区别是标识符可省去。
其实,"function Identifier(Parameters){ FunctionBody }"并不是一个完整的函数表达式,完整的函数的表达式,需要一个赋值操作。
比如: var name=function Identifier(Parameters){ FunctionBody }
3.5.3、立即执行函数表达式与匿名对象
//1 正常定义函数 function f1(){ console.log("正常定义f1函数"); }; //2 被误解的函数表达式 function(){ console.log("报错Unexpected token ("); }(); //3 IIFE,括号中的内容被解释成函数表达式 (function(){ console.log("IIFE,正常执行"); })(); //4 函数表达式 var f2=function(){ console.log("这也被视为函数表达式"); };