申请并致电
主要解决几个问题:
1.apply和call有什么区别?
2.什么时候用apply,什么时候用call?
3. apply的其他巧妙用法(一般在什么情况下可以使用apply)
apply:方法可以劫持另一个对象的方法,继承另一个对象的属性。
.apply(obj,args)方法可以接收两个参数
obj:这个对象将替换类中的this对象
args:这是一个数组,它将作为参数传递(args-->)
call:与apply含义相同,但参数列表不同。
.call(obj,[[,[,…[,]]]])
obj:这个对象将替换类中的this对象
: 这是参数列表
1.应用示例:
<script type="text/javascript">
/*定义一个人类*/
function Person(name,age)
{
this.name=name;
this.age=age;
}
/*定义一个学生类*/
functionStudent(name,age,grade)
{
Person.apply(this,arguments);
this.grade=grade;
}
//创建一个学生类
var student=new Student("zhangsan",21,"一年级");
//测试
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//大家可以看到测试结果name:zhangsan age:21 grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
</script>
分析:.apply(this,);
this:创建对象时,此时代表的是
: 是一个数组,即["","21","一年级"];
换句话说,通俗地说:就是用来执行这个类中的内容的。 该类中有this.name等语句,从而将属性创建到对象中。
2.调用示例
在函数中,可以修改apply如下:
Person.call(this,name,age);
没关系
3、什么时候用apply,什么时候用call?
在给出对象参数的情况下,如果参数是数组的形式,比如apply例子中传递的参数,这个参数是数组类型,调用时参数列表是一致的(即和的参数列表(前两者一致),可以使用apply,如果我的参数列表是这样的(年龄,姓名),而你的参数列表是(姓名,年龄,年级),可以使用call来实现。也就是直接指定对应值在参数列表中的位置(.call(this,age,name,grade));
4. apply 的其他一些巧妙用法
细心的人可能注意到了,我调用apply方法时,第一个参数是对象(this),第二个参数是一个数组集合。 调用的时候,它需要的不是数组,但是为什么给我一个数组,我还能把数组一一解析成参数。 这是 apply 的巧妙运用。 它默认可以将数组转换为参数列表([,,] 转换为,,)。 如果我们让使用程序将数组的每一项转换为参数列表可能需要一段时间。 借助apply的这个特性,我们有以下高效的方法:
a)Math.max可以实现数组中最大的项
因为Math.max参数不支持Math.max([,]),它是一个数组
但它支持Math.max(,,...),所以可以根据刚才apply的特点来解决var max=Math.max.apply(null, array),这样就可以轻松得到一个数组中最大的一项数组(apply 会将数组转换为参数,并将其一个参数一个参数地传递给方法)
调用此块时,第一个参数被赋予 null。 这是因为没有对象可以调用此方法。 我只需要使用这个方法来帮助我计算并得到返回的结果。 所以我直接传递一个null。
b)Math.min可以实现数组中最小的项
和 max 的思路一样 var min=Math.min.apply(null,array);
c)Array..push可以合并两个数组
同样,push方法不提供对数组的push,但是提供了push(,param,...),所以数组也可以用apply代替,即:
vararr1=new Array("1","2","3");
vararr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
也可以理解为arr1调用push方法,参数通过apply从数组转换成参数列表的集合。
什么情况下可以使用像Math.min这样的apply等特殊用法:
一般情况下,目标函数只需要n个参数列表,并且不接收数组形式([[,[,…[,]]]])。 这个问题可以通过申请巧妙解决!
1. 在 中,对象是一个特殊的对象,它实际上是当前函数的内置属性。 与 Array 非常相似,但实际上不是 Array 实例。 可以通过下面的代码来确认(当然,其实在函数中,call不需要写成.,直接写就可以了)。
Array.prototype.testArg = "test";
function funcArg() {
alert(funcArg.arguments.testArg);
alert(funcArg.arguments[0]);
}
alert(new Array().testArg); // result: "test" 8
funcArg(10); // result: "undefined" "10"
2. 对象的长度由实参的数量决定,而不是由形参的数量决定。 形式参数是在函数内部的内存空间中重新开辟的变量,但它们与对象内存空间不重叠。 对于 和 值都存在的情况,则同步这两个值,但对于其中一个没有值的情况,对于这种无值的情况,不会同步该值。 下面的代码可以验证。
function f(a, b, c){
alert(arguments.length); // result: "2"
a = 100;
alert(arguments[0]); // result: "100"
arguments[0] = "qqyumidi";
alert(a); // result: "qqyumidi"
alert(c); // result: "undefined"
c = 2012;
alert(arguments[2]); // result: "undefined"
}
f(1, 2);
3、从函数的声明和调用特点可以看出,函数不能重载。
根据其他语言中重载的依据:“函数返回值不同或者形参个数不同”,我们可以得出上述结论:
第一:函数声明没有返回值类型;
第二:严格来说,形参的个数只是为了方便函数中的变量操作。 事实上,实际参数已经存储在对象中。
另外,从函数本身,我们深刻的理解了为什么函数不能被重载:在函数中,函数实际上是一个对象,而函数名是对函数的引用,或者说函数名本身就是一个对象。多变的。 对于下面所示的函数声明和函数表达式,内容与上面相同(不考虑函数声明和函数表达式的区别),这对于我们理解函数不能重载非常有帮助。
function f(a){
return a + 10;
}
function f(a){
return a - 10;
}
// 在不考虑函数声明与函数表达式区别的前提下,其等价于如下
var f = function(a){
return a + 10;
}
var f = function(a){
return a - 10;
}
4.对象中有一个非常有用的属性:。 .返回该对象所在的当前函数引用。 建议使用。 使用递归函数调用时,而不是函数名称本身。
如下:
function count(a){
if(a==1){
return 1;
}
return a + arguments.callee(--a);
}
var mm = count(10);
alert(mm);
和:
。 返回给调用者。
看看下面的函数。 你可以将其复制到VS中并执行。
复制代码代码如下:
function caller() {
if (caller.caller) {
alert(caller.caller.toString());
} else {
alert("函数直接执行");
}
}
function handleCaller() {
caller();
}
handleCaller();
caller();
你会发现第一个alert会弹出调用函数的调用者,第二个alert因为没有在其他函数体中调用所以为null,所以执行了alert("函数直接执行");
:
返回正在执行的对象,即指定对象的主体。
是一个属性成员,代表对函数对象本身的引用,方便匿名
函数递归或者保证函数封装性。下面的代码先解释一下用法。 示例代码取自互联网。
复制代码代码如下:
function calleeLengthDemo(arg1, arg2) {
alert(arguments.callee.toString());
if (arguments.length == arguments.callee.length) {
window.alert("验证形参和实参长度正确!");
return;
} else {
alert("实参长度:" + arguments.length);
alert("形参长度: " + arguments.callee.length);
}
}
calleeLengthDemo(1);
第一个消息框弹出函数本身,这意味着它是对函数对象本身的引用。 另一个非常有用的应用是判断实际参数与行参数是否一致。 上面代码中第一个消息框会弹出实参长度为1,形参也就是函数本身的参数长度为2。
应用场景:
应用场景一般用于匿名函数