js中bind、apply、call、callee、caller的使用
在js中,apply,call,bind三者都是用来改变函数的this对象的指向
相同点
不同点
执行以下代码
console.log("***example start***");
var person1 = {
name:"张三",
age:23,
say:function(){
console.log("我的名字是:",this.name+";我的年龄是:"+this.age);
},
say2:function(school,gender){
school = school ? school : "社会大学";
gender = gender ? gender : "男";
console.log("我的名字是:",this.name+";我的年龄是:"+this.age+";我的学校是:"+school+";我的性别:"+gender);
}
};
var person2 = {
name:"李四",
age:25
};
console.log("***直接调用say start***");
person1.say();
console.log("***直接调用say end***");
console.log("***apply调用say start***");
person1.say.apply(person2);
console.log("***apply调用say end***");
console.log("***call调用say start***");
person1.say.call(person2);
console.log("***call调用say end***");
console.log("***bind调用say start***");
person1.say.bind(person2)();
console.log("***bind调用say end***");
console.log("***带参数直接调用say start***");
person1.say2("哈佛1","男1");
console.log("***带参数直接调用say end***");
console.log("***带参数apply调用say start***");
person1.say2.apply(person2,["哈佛2","男2"]);
console.log("***带参数apply调用say end***");
console.log("***带参数call调用say start***");
person1.say2.call(person2,"哈佛3","男3");
console.log("***带参数call调用say end***");
console.log("***带参数bind调用say start***");
person1.say2.bind(person2,"哈佛4","男4")();
console.log("***带参数bind调用say end***");
console.log("***带参数bind调用say2 start***");
person1.say2.bind(person2)("哈佛5","男5");
console.log("***带参数bind调用say end***");
console.log("***example end***");
输出:
***example start***
***直接调用say start***
我的名字是: 张三;我的年龄是:23
***直接调用say end***
***apply调用say start***
我的名字是: 李四;我的年龄是:25
***apply调用say end***
***call调用say start***
我的名字是: 李四;我的年龄是:25
***call调用say end***
***bind调用say start***
我的名字是: 李四;我的年龄是:25
***bind调用say end***
***带参数直接调用say start***
我的名字是: 张三;我的年龄是:23;我的学校是:哈佛1;我的性别:男1
***带参数直接调用say end***
***带参数apply调用say start***
我的名字是: 李四;我的年龄是:25;我的学校是:哈佛2;我的性别:男2
***带参数apply调用say end***
***带参数call调用say start***
我的名字是: 李四;我的年龄是:25;我的学校是:哈佛3;我的性别:男3
***带参数call调用say end***
***带参数bind调用say start***
我的名字是: 李四;我的年龄是:25;我的学校是:哈佛4;我的性别:男4
***带参数bind调用say end***
***带参数bind调用say2 start***
我的名字是: 李四;我的年龄是:25;我的学校是:哈佛5;我的性别:男5
***带参数bind调用say end***
***example end***
1:以下是apply方法的用法
<input type="text" id="myText" value = "input value">
<script>
console.log("***以下为apply方法的实例 start***");
console.log("***example1:***");
var value = "global value";
function Obj(){
this.value = "obj value"
}
function GetValue(){
console.log(this.value);
}
window.GetValue();
GetValue();
GetValue.apply(window);
GetValue.apply(new Obj());
GetValue.apply(document.getElementById("myText"));
console.log("***example2:***");
var first_obj = {
num:12
}
var second_obj = {
num:23
}
function multiply(operation,mult){
var num = ""
switch (operation){
case "+":
num = this.num + mult;
break;
case "-":
num = this.num - mult;
break;
case "*":
num = this.num * mult;
break;
case "/":
num = this.num / mult;
break;
}
console.log(this.num +operation+mult+" = "+num);
}
multiply.apply(first_obj,["+",3])
multiply.apply(second_obj,["*",3])
console.log("***数组之间追加***");
var arr1 = [1,2,3,4];
var arr2 = [5,6,7];
console.log("before arr1:"+arr1)
console.log("before arr2:"+arr2)
Array.prototype.push.apply(arr1,arr2);
console.log("after arr1:"+arr1)
console.log("after arr2:"+arr2)
console.log("***获取数组之间的最大值和最小值***");
var arr1 = [1,2,3,4];
var maxNum = Math.max.apply(Math,arr1)
var minNum = Math.min.apply(Math,arr1)
console.log("最大值:"+maxNum)
console.log("最小值:"+minNum)
console.log("***验证是否是数组***");
function isArray(obj){
console.log(Object.prototype.toString.apply(obj))
return Object.prototype.toString.apply(obj) === "[object Array]";
}
console.log("[1,2,3]是数组吗:"+isArray([1,2,3]))
console.log("123是数组吗:"+isArray("123"))
console.log("new Object()是数组吗:"+isArray(new Object()))
console.log("***传入的参数不确定***");
function logArg(arg){
console.log.apply(console,arguments)
}
logArg(1)
logArg(1,2)
console.log("***传入的参数是字符串,且输出时候拼接字符串***");
function logStr(){
var args = Array.prototype.slice.apply(arguments);
args.unshift("zyb:");
console.log.apply(console,args)
}
logStr("hello"," world");
console.log("***以下为apply方法的实例 end***");
</script>
输出:
***apply方法 start***
***example1:***
global value
global value
global value
obj value
input value
***example2:***
12+3 = 15
23*3 = 69
***数组之间追加***
before arr1:1,2,3,4
before arr2:5,6,7
after arr1:1,2,3,4,5,6,7
after arr2:5,6,7
***获取数组之间的最大值和最小值***
最大值:4
最小值:1
***验证是否是数组***
[object Array]
[1,2,3]是数组吗:true
[object String]
123是数组吗:false
[object Object]
new Object()是数组吗:false
***传入的参数不确定***
1
1 2
***传入的参数是字符串,且输出时候拼接字符串***
zyb: hello world
***apply方法 end***
2:以下是call方法的用法
<input type="text" id="myText" value = "input value">
<script>
console.log("***以下为bind方法的实例 start***");
console.log("***example1:***");
var value = "global value";
function Obj(){
this.value = "obj value"
}
function GetValue(){
console.log(this.value);
}
window.GetValue();
GetValue();
GetValue.bind(window)();
GetValue.bind(new Obj())();
GetValue.bind(document.getElementById("myText"))();
console.log("***example2:***");
var first_obj = {
num:12
}
var second_obj = {
num:23
}
function multiply(operation,mult){
var num = ""
switch (operation){
case "+":
num = this.num + mult;
break;
case "-":
num = this.num - mult;
break;
case "*":
num = this.num * mult;
break;
case "/":
num = this.num / mult;
break;
}
console.log(this.num +operation+mult+" = "+num);
}
multiply.bind(first_obj,"+",3)();
multiply.bind(second_obj,"*",3)();
multiply.bind(first_obj)("-",3);
multiply.bind(second_obj)("/",3);
console.log("***以下为bind方法的实例 end***");
</script>
输出:
***bind方法 start***
***example1:***
global value
global value
global value
obj value
input value
***example2:***
12+3 = 15
23*3 = 69
12-3 = 9
23/3 = 7.666666666666667
***bind方法 end***
3:以下是bind方法的用法
<input type="text" id="myText" value = "input value">
<script>
console.log("***以下为call方法的实例 start***");
console.log("***example1:***");
var value = "global value";
function Obj(){
this.value = "obj value"
}
function GetValue(){
console.log(this.value);
}
window.GetValue();
GetValue();
GetValue.call(window);
GetValue.call(new Obj());
GetValue.call(document.getElementById("myText"));
console.log("***example2:***");
var first_obj = {
num:12
}
var second_obj = {
num:23
}
function multiply(operation,mult){
var num = ""
switch (operation){
case "+":
num = this.num + mult;
break;
case "-":
num = this.num - mult;
break;
case "*":
num = this.num * mult;
break;
case "/":
num = this.num / mult;
break;
}
console.log(this.num +operation+mult+" = "+num);
}
multiply.call(first_obj,"+",3)
multiply.call(second_obj,"*",3)
console.log("***以下为call方法的实例 end***");
</script>
输出:
***call方法 start***
***example1:***
global value
global value
global value
obj value
input value
***example2:***
12+3 = 15
23*3 = 69
***call方法 end***
4:callee:返回正在执行的function对象
1):callee可以打印函数本身
function test1(){
console.log(arguments)
console.log(arguments.callee)
}
test1();
输出:
Arguments[0]
function test1(){
console.log(arguments)
console.log(arguments.callee)
}
2):callee可以验证参数
function test2(arg1,arg2){
if(arguments.length == arguments.callee.length){
console.log("形参和实参长度相等")
}else{
console.log("形参长度:"+arguments.length)
console.log("实参长度:"+arguments.callee.length)
}
}
test2(1,2);
test2(1,2,3);
输出:
形参和实参长度相等
形参长度:3
实参长度:2
3):callee可以进行递归计算
function sum(n){
if(n <=0){
return 0;
}else{
return n + arguments.callee(n-1)
}
}
var _sum1 = sum(-1)//1
var _sum2 = sum(0)//1
var _sum3 = sum(1)//2
var _sum4 = sum(2)//4
var _sum5 = sum(3)//7
var _sum6 = sum(4)//11
console.log(_sum1)//1
console.log(_sum2)//1
console.log(_sum3)//2
console.log(_sum4)//4
console.log(_sum5)//7
console.log(_sum6)//11
5:caller:返回一个对函数的引用,即调用了该函数的函数体
对于函数来说,caller属性只有在函数执行时候才有定义,如果有程序顶层调用,caller为null,如果是有其它函数调用,caller为调用函数体
function InnerFun(){
console.log("caller:"+InnerFun.caller);
if(InnerFun.caller == null){
console.log("该函数是由顶层调用,不是由其它函数调用")
}else{
console.log("该函数是由其它函数调用,不是由顶层调用")
}
}
function OuterFun(){
console.log("OuterFun")
InnerFun()
}
InnerFun();
OuterFun();
输出:
caller:null
该函数是由顶层调用,不是由其它函数调用
OuterFun
caller:function OuterFun(){
console.log("OuterFun")
InnerFun()
}
该函数是由其它函数调用,不是由顶层调用