简单来说调用 call、apply、 bind 的对象,必须是个函数 Function;
call、apply、 bind都是改变函数this的指向;
第一个传参都是要this要指向的对象,apply只能有2个参数,call和bind可以大于2个参数;
apply、call是立即执行函数,bind需要再次调用。
call的写法
Function.call(obj,param1, param2, ... paramN)
需要注意的几点:
- 调用 call 的对象,必须是个函数 Function。
- call 的第一个参数是一个对象。调用者将会指向这个对象。如果不传,则默认为全局对象 window。
- 第二个参数开始,可以接收任意个参数。每个参数会映射到调用者Function 的参数上。但是如果将所有的参数作为数组传入,它们会作为一个整体映射到 Function 对应的第一个参数上,之后参数都为空。
function Person (name,sex,age) { console.log(name+"是个"+sex+"孩子,今年"+age+"岁了。") } Person.call(this,"大P","男",20); //大P是个男孩子,今年20岁了。 Person.call(this,["大P","男",20]); //大P,男,20是个undefined孩子,今年undefined岁了。
apply的写法
Function.apply(obj,[param1, param2, ... paramN])
需要注意的几点:
- 它的调用者必须是函数Function,并且只接收两个参数,第一个参数是一个对象,和call是一样的规则。
- 第二个参数,必须是数组或者类数组,它们会被转换成类数组,传入 Function 中,并且会被映射到 Function 对应的参数上。这也是 call 和 apply 之间,很重要的一个区别。
function Person (name,sex,age) { console.log(name+"是个"+sex+"孩子,今年"+age+"岁了。") } Person.apply(this,"大P","男",20); //报错,因为第二个参数类型不对 Person.apply(this,["大P","男",20]);//大P是个男孩子,今年20岁了。 Person.apply(this, { 0: "大P", 1: "男", 2: 20, length: 3 }); //第二个参数使用类数组形式,输出 大P是个男孩子,今年20岁了。
bind的写法
Function.bind(obj,param1, param2, ... paramN)
需要注意的几点:
- 调用 bind 的对象,必须是个函数 Function。
- bind 的第一个参数是一个对象,规则和call一样。
- 第二个参数开始,可以接收任意个参数。规则和call一样
- bind返回的是调用者function的一个拷贝,这也是bind和call 、apply最大的区别
function Person (name,sex,age) { console.log(name+"是个"+sex+"孩子,今年"+age+"岁了。") } Person.bind(this,"大P","男",20);//返回Person的拷贝 Person.bind(this,"大P","男",20)();//大P今年20岁了。
call、apply、bind的应用用
日常写代码,这几个方法可能用得不多,但一些特殊场景用处还是蛮大的
例如通过call或者apply可以实现函数继承
函数继承
/*父类*/ function Parent(name,sex,age) { this.name = name; this.sex = sex; this.age = age; } /*子类*/ function Child(homepage) { this.homepage = homepage; Parent.call(this,"大P","男",20); // Parent.apply(this,["大P","男",20]); // 如果用apply就这样写 this.say = function(){ var printStr = this.name+"是个"+this.sex+"孩子,今年"+this.age+"岁了。"+this.name+"的个人主页是:"+this.homepage; console.log(printStr) } } var child = new Child("http://www.coolfish.cn"); child.say(); //大P是个男孩子,今年20岁了。大P的个人主页是:http://www.coolfish.cn
子类中的Parent.call(this,"大P","男",20)可以理解为在子类中定义
this.name = "大P"; this.sex = "男"; this.age = 20;
获取数组最大值最小值
var array = [9,5,2,7]; var max = Math.max.apply(null, array); var min = Math.min.apply(null, array); console.log("Max:"+max,"Min:"+min); // Max:9 Min:2