【亚洲必赢官网】长远浅出妙用

深切浅出妙用 Javascript 中 apply、call、bind

2015/09/24 · JavaScript
· 4 评论 ·
apply,
bind,
call

正文作者: 伯乐在线 –
chokcoco
。未经小编许可,禁止转发!
迎接参预伯乐在线 专栏撰稿人。

那篇文章实在是很难下笔,因为网上有关作品如拾草芥。

巧合的是先天看到阮老师的一篇小说的一句话:

“对自家来说,博客首先是一种知识管理工具,其次才是传播工具。我的技艺小说,主要用来整理自己还不懂的知识。我只写那个自己还并未完全了解的事物,这一个自己领会的事物,往往没有引力写。炫耀没有是我的心劲,好奇才是。”

对此那句话,无法扶助更加多,也让自身下决心好好写这篇,网上作品虽多,大多复制粘贴,且晦涩难懂,我盼望可以由此那篇文章,可以清晰的升级对apply、call、bind的认识,并且列出有些它们的妙用加深回忆。

   apply、call

在 javascript 中,call 和 apply
都是为着改变某个函数运行时的上下文(context)而留存的,换句话说,就是为着改变函数体内部
this 的对准。

JavaScript
的一大特色是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是能够变更的」那样的概念。

先来一个板栗:

JavaScript

function fruits() {} fruits.prototype = { color: “red”, say: function()
{ console.log(“My color is ” + this.color); } } var apple = new fruits;
apple.say(); //My color is red

1
2
3
4
5
6
7
8
9
10
11
function fruits() {}
 
fruits.prototype = {
    color: "red",
    say: function() {
        console.log("My color is " + this.color);
    }
}
 
var apple = new fruits;
apple.say();    //My color is red

只是要是大家有一个目的banana= {color : “yellow”} ,我们不想对它再度定义
say 方法,那么大家得以由此 call 或 apply 用 apple 的 say 方法:

JavaScript

banana = { color: “yellow” } apple.say.call(banana); //My color is
yellow apple.say.apply(banana); //My color is yellow

1
2
3
4
5
banana = {
    color: "yellow"
}
apple.say.call(banana);     //My color is yellow
apple.say.apply(banana);    //My color is yellow

据此,可以看出 call 和 apply 是为着动态改变 this 而产出的,当一个 object
没有某个方法(本栗子中banana没有say方法),可是其余的有(本栗子中apple有say方法),大家得以凭借call或apply用其余对象的方法来操作。

apply、call 的区别

对此 apply、call
二者而言,功能完全等同,只是接受参数的法门不太雷同。例如,有一个函数定义如下:

JavaScript

var func = function(arg1, arg2) { };

1
2
3
var func = function(arg1, arg2) {
 
};

就足以通过如下形式来调用:

JavaScript

func.call(this, arg1, arg2); func.apply(this, [arg1, arg2])

1
2
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])

里头 this 是您想指定的上下文,他可以是其余一个 JavaScript
对象(JavaScript 中任何皆对象),call 须求把参数按顺序传递进入,而 apply
则是把参数放在数组里。

JavaScript
中,某个函数的参数数量是不定点的,因而要说适用标准的话,当你的参数是驾驭通晓多少时用
call 。

而不确定的时候用 apply,然后把参数 push
进数组传递进入。当参数数量不确定时,函数内部也可以由此 arguments
那一个数组来遍历所有的参数。

为了巩固深化记念,上边罗列部分常用用法:

1、数组之间追加

JavaScript

var array1 = [12 , “foo” , {name “Joe”} , -2458]; var array2 = [“Doe”
, 555 , 100]; Array.prototype.push.apply(array1, array2); /* array1
值为 [12 , “foo” , {name “Joe”} , -2458 , “Doe” , 555 , 100] */

1
2
3
4
var array1 = [12 , "foo" , {name "Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

2、获取数组中的最大值和最小值

JavaScript

var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers =
Math.max.apply(Math, numbers), //458 maxInNumbers =
Math.max.call(Math,5, 458 , 120 , -215); //458

1
2
3
var  numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers),   //458
    maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

number 本身并未 max 方法,可是 Math 有,我们就可以借助 call 或者 apply
使用其方法。

3、验证是不是是数组(前提是toString()方法没有被重写过)

JavaScript

functionisArray(obj){ returnObject.prototype.toString.call(obj) ===
‘[object Array]’ ; }

1
2
3
functionisArray(obj){
    returnObject.prototype.toString.call(obj) === ‘[object Array]’ ;
}

4、类(伪)数组使用数组方法

JavaScript

var domNodes =
Array.prototype.slice.call(document.getElementsByTagName(“*”));

1
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

Javascript中存在一种名为伪数组的目的社团。相比特其余是 arguments
对象,还有像调用 getElementsByTagName , document.childNodes 之类的,它们重回NodeList对象都属于伪数组。不可以使用
Array下的 push , pop 等方法。

不过大家能透过 Array.prototype.slice.call 转换为真正的数组的盈盈 length
属性的靶子,那样 domNodes 就可以使用 Array 下的拥有办法了。

长远精通运用apply、call

下面就借用一道面课题,来更深切的去领略下
apply 和 call 。

概念一个 log 方法,让它可以代劳 console.log 方法,常见的化解措施是:

JavaScript

function log(msg) { console.log(msg); } log(1); //1 log(1,2); //1

1
2
3
4
5
function log(msg) {
  console.log(msg);
}
log(1);    //1
log(1,2);    //1

地点方法可以缓解最基本的必要,可是当传入参数的个数是不确定的时候,上边的章程就失效了,那些时候就可以设想拔取apply 或者
call,注意那里传出几个参数是不确定的,所以选拔apply是最好的,方法如下:

JavaScript

function log(){ console.log.apply(console, arguments); }; log(1); //1
log(1,2); //1 2

1
2
3
4
5
function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2

接下去的要求是给每一个 log 消息添加一个”(app)”的前辍,比如:

JavaScript

log(“hello world”); //(app)hello world

1
log("hello world");    //(app)hello world

该怎么做相比较优雅呢?那个时候要求想到arguments参数是个伪数组,通过
Array.prototype.slice.call
转化为专业数组,再选择数组方法unshift,像这么:

JavaScript

function log(){ var args = Array.prototype.slice.call(arguments);
args.unshift(‘(app)’); console.log.apply(console, args); };

1
2
3
4
5
6
function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift(‘(app)’);
 
  console.log.apply(console, args);
};

bind

说完了 apply 和 call ,再来说说bind。bind() 方法与 apply 和 call
很相像,也是可以更改函数体内 this 的指向。

MDN的诠释是:bind()方法会成立一个新函数,称为绑定函数,当调用这么些绑定函数时,绑定函数会以创设它时传出 bind()方法的首先个参数作为 this,传入 bind() 方法的第一个以及随后的参数加上绑定函数运行时我的参数根据顺序作为原函数的参数来调用原函数。

直接来探望现实哪些选用,在广阔的单体形式中,平常我们会使用 _this , that
, self 等保存 this
,那样咱们得以在变更了上下文之后继续引用到它。 像那样:

JavaScript

var foo = { bar : 1, eventBind: function(){ var _this = this;
$(‘.someClass’).on(‘click’,function(event) { /* Act on the event */
console.log(_this.bar); //1 }); } }

1
2
3
4
5
6
7
8
9
10
var foo = {
    bar : 1,
    eventBind: function(){
        var _this = this;
        $(‘.someClass’).on(‘click’,function(event) {
            /* Act on the event */
            console.log(_this.bar);     //1
        });
    }
}

出于 Javascript 特有的机制,上下文环境在 eventBind:function(){ }
过渡到 $(‘.someClass’).on(‘click’,function(event)
{ }) 发生了变更,上述使用变量保存 this 那几个艺术都是卓有功用的,也从没怎么问题。当然使用
bind() 能够进一步雅致的化解那么些题目:

JavaScript

var foo = { bar : 1, eventBind: function(){
$(‘.someClass’).on(‘click’,function(event) { /*【亚洲必赢官网】长远浅出妙用。 Act on the event *亚洲必赢官网 ,/
console.log(this.bar); //1 }.bind(this)); } }

1
2
3
4
5
6
7
8
9
var foo = {
    bar : 1,
    eventBind: function(){
        $(‘.someClass’).on(‘click’,function(event) {
            /* Act on the event */
            console.log(this.bar);      //1
        }.bind(this));
    }
}

在上述代码里,bind()
创立了一个函数,当以此click事件绑定在被调用的时候,它的 this
关键词会被设置成被传出的值(那里指调用bind()时传出的参数)。由此,那里大家传入想要的前后文
this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被实施的时候,
this 便指向 foo 对象。再来一个不难的板栗:

JavaScript

var bar = function(){ console.log(this.x); } bar(); // undefined var
func = bar.bind(foo); func(); // 3

1
2
3
4
5
6
7
var bar = function(){
    console.log(this.x);
}
 
bar(); // undefined
var func = bar.bind(foo);
func(); // 3

那边大家创建了一个新的函数 func,当使用 bind()
成立一个绑定函数之后,它被实践的时候,它的 this 会被设置成 foo ,
而不是像我们调用 bar() 时的大局功能域。

有个有意思的题目,若是连接 bind() 一遍,亦或者是连续 bind()
三遍那么输出的值是何等吧?像这么:

JavaScript

var bar = function(){ console.log(this.x); } var foo = { x:3 } var sed =
{ x:4 } var func = bar.bind(foo).bind(sed); func(); //? var fiv = { x:5
} var func = bar.bind(foo).bind(sed).bind(fiv); func(); //?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}
var sed = {
    x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?
 
var fiv = {
    x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?

答案是,两回都仍将出口 3 ,而非期待中的 4 和 5
。原因是,在Javascript中,数次 bind() 是不行的。更深层次的缘故, bind()
的落到实处,相当于选择函数在中间包了一个 call / apply ,第二次 bind()
相当于再包住第二回 bind() ,故第二次未来的 bind 是无能为力生效的。

apply、call、bind比较

那么 apply、call、bind 三者相相比,之间又有何异同呢?曾几何时使用
apply、call,哪一天使用 bind 呢。容易的一个板栗:

JavaScript

var obj = { x: 81, }; var foo = { getX: function() { return this.x; } }
console.log(foo.getX.bind(obj)()); //81 console.log(foo.getX.call(obj));
//81 console.log(foo.getX.apply(obj)); //81

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

多个出口的都是81,然而注意看使用 bind() 方法的,他背后多了对括号。

也就是说,差别是,当您期望改变上下文环境之后并非立刻施行,而是回调执行的时候,使用
bind() 方法。而 apply/call 则会即刻执行函数。

再计算一下:

  • apply 、 call 、bind 三者都是用来改变函数的this对象的对准的;
  • apply 、 call 、bind
    三者第四个参数都是this要针对性的靶子,也就是想指定的上下文;
  • apply 、 call 、bind 三者都足以拔取再而三参数传参;
  • bind 是回去对应函数,便于稍后调用;apply 、call 则是当时调用 。

本文实例出现的富有代码,在自我的github上得以下载。

打赏协助我写出越多好小说,谢谢!

打赏小编

诸君观众老爷我们好,欢迎收看四角裤总动员之程序猿的IT程序大讲堂,明天给大家大饱眼福一个小知识.就是call和apple的差异.

小编:伯乐在线专栏小编 – chokcoco

如有好文章投稿,请点击 →
那里询问详情

如需转发,发送「转发」二字查看表明

这篇小说实在是很难下笔,因为网上有关小说不胜枚举。
巧合的是前日看到阮老师的一篇小说的一句话:
“对自身来说,博客首先是一种文化管理工具,其次才是传播工具。我的技艺小说,首要用来打点自己还不懂的知识。我只写那么些自己还未曾完全驾驭的东西,那多少个自己精晓的事物,往往没有引力写。炫耀没有是自身的意念,好奇才是。”
对此这句话,不可能支持更加多,也让自身下决心好好写那篇,网上小说虽多,大多复制粘贴,且晦涩难懂,我希望可以通过那篇小说,可以清晰的升官对apply、call、bind的认识,并且列出一部分它们的妙用加深回忆。
apply、call
在 javascript 中,call 和 apply
都是为着改变某个函数运行时的上下文(context)而留存的,换句话说,就是为着改变函数体内部
this 的针对。
JavaScript
的一大特征是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是足以更改的」那样的定义。
先来一个板栗:

打赏接济自己写出越来越多好小说,谢谢!

任选一种支付格局

亚洲必赢官网 1
亚洲必赢官网 2

2 赞 16 收藏 4
评论


 

function fruits() {};
fruits.prototype = {
    color: "red",
    say: function() {
        console.log("My color is " + this.color);
    }
}

var apple = new fruits;
apple.say();    //My color is red

有关小编:chokcoco

亚洲必赢官网 3

经不住小运似水,逃可是此间少年。

个人主页 ·
我的小说 ·
63 ·
   

亚洲必赢官网 4

call和apple

在javascript中,
call和apple都是为着改变某个函数中运作的上下文(context)而留存的,换句话说就是为着改变函数内部的this的指向.

JavaScript
的一大特征是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以转移的」那样的定义。

先给我们来一个板栗: 

functionfruits() {}

fruits.prototype = {

color:”red”,

say:function() {

console.log(“My color is “+this.color);

}

}

varapple =newfruits;

apple.say();//My color is red

唯独一旦大家有一个对象banana= {color : “yellow”} ,大家不想对它再也定义
say 方法,那么我们可以透过 call 或 apply 用 apple 的 say 方法

banana = {

color:”yellow”

}

apple.say.call(banana);//My color is yellow

apple.say.apply(banana);//My color is yellow

因此,可以见见 call 和 apply 是为着动态改变 this 而出现的,当一个 object
没有某个方法(本栗子中banana没有say方法),不过其他的有(本栗子中apple有say方法),我们得以凭借call或apply用任何对象的法门来操作。


那篇小说实在是很难下笔,因为网上有关作品如拾草芥。

然而假诺我们有一个目的banana= {color : “yellow”} ,我们不想对它再度定义
say 方法,那么我们得以经过 call 或 apply 用 apple 的 say 方法:

apply、call 的区别

对于 apply、call
二者而言,功用完全平等,只是接受参数的不二法门不太一样。例如,有一个函数定义如下:

varfunc =function(arg1, arg2) {

};

就足以经过如下形式来调用:

func.call(this, arg1, arg2);

func.apply(this, [arg1, arg2])

里头 this 是您想指定的上下文,他得以是其他一个 JavaScript
对象(JavaScript 中所有皆对象),call 需求把参数按梯次传递进入,而 apply
则是把参数放在数组里。

JavaScript
中,某个函数的参数数量是不固定的,由此要说适用标准的话,当您的参数是醒目知道数据时用
call 。

而不确定的时候用 apply,然后把参数 push
进数组传递进入。当参数数量不确定时,函数内部也得以由此 arguments
这些数组来遍历所有的参数。

为了巩固深化回忆,上边罗列部分常用用法:

1、数组之间追加

vararray1 = [12 ,”foo”, {name”Joe”} , -2458];

vararray2 = [“Doe”, 555 , 100];

Array.prototype.push.apply(array1, array2);

/* array1 值为  [12 , “foo” , {name “Joe”} , -2458 , “Doe” , 555 ,
100] */

2、获取数组中的最大值和最小值

varnumbers = [5, 458 , 120 , -215 ];

varmaxInNumbers = Math.max.apply(Math, numbers),//458

maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215);//458

number 本身并未 max 方法,然而 Math 有,大家就可以借助 call 或者 apply
使用其艺术。

3、验证是不是是数组(前提是toString()方法没有被重写过)

functionisArray(obj){

return Object.prototype.toString.call(obj) ==='[object Array]’;

}

4、类(伪)数组使用数组方法

vardomNodes =
Array.prototype.slice.call(document.getElementsByTagName(“*”));

Javascript中设有一种名为伪数组的对象协会。相比特其他是 arguments

目标,还有像调用 getElementsByTagName , document.childNodes 之类的,它们重回NodeList对象都属

于伪数组。不可以利用 Array下的 push , pop 等艺术。

唯独大家能通过 Array.prototype.slice.call 转换为确实的数组的涵盖 length
属性的目的,那样 domNodes 就可以动用 Array 下的所有办法了。


 

banana = {
    color: "yellow"
}
apple.say.call(banana);     //My color is yellow
apple.say.apply(banana);    //My color is yellow

长远通晓运用apply、call

下面就借用一道面课题,来更尖锐的去领会下
apply 和 call 。

概念一个 log 方法,让它能够代劳 console.log 方法,常见的解决方法是:

functionlog(msg) {

console.log(msg);

}

log(1);//1

log(1,2);//1

上面方法可以化解最焦点的必要,可是当传入参数的个数是不确定的时候,上面的方法就失效了,这一个时候就足以考虑接纳apply 或者
call,注意那里流传多少个参数是不确定的,所以利用apply是最好的,方法如下:

functionlog(){

console.log.apply(console, arguments);

};

log(1);//1

log(1,2);//1 2

接下去的渴求是给每一个 log 音信添加一个”(app)”的前辍,比如:

log(“hello world”);//(app)hello world

该如何是好相比较优雅呢?这几个时候要求想到arguments参数是个伪数组,通过
Array.prototype.slice.call
转化为正式数组,再利用数组方法unshift,像这么:

functionlog(){

varargs = Array.prototype.slice.call(arguments);

args.unshift(‘(app)’);

console.log.apply(console, args);

};


偶合的是今日看到阮老师的一篇小说的一句话:

为此,可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 object
没有某个方法(本栗子中banana没有say方法),不过任何的有(本栗子中apple有say方法),大家可以借助call或apply用任何对象的点子来操作。
apply、call 的区别
对于 apply、call
二者而言,效能完全一致,只是接受参数的艺术不太相同。例如,有一个函数定义如下:

bind

说完了 apply 和 call ,再来说说bind。bind() 方法与 apply 和 call
很一般,也是足以转移函数体内 this 的针对性。

MDN的分解是:bind()方法会成立一个新函数,称为绑定函数,当调用那些绑定函数时,绑定函数会以创立它时传出 bind()方法的首先个参数

用作 this,传入 bind() 方法的第一个以及后来的参数加上绑定函数运行时我的参数依照顺序作为原函数的参数来调用原函数。

直白来探望具体哪些拔取,在广阔的单体方式中,平日大家会使用 _this , that
, self 等保存 this
,那样大家得以在变更了上下文之后持续引用到它。 像那样:

varfoo = {

bar : 1,

eventBind:function(){

var _this =this;

$(‘.someClass’).on(‘click’,function(event) {

/* Act on the event */

console.log(_this.bar);//1

});

}

}

由于 Javascript 特有的体制,上下文环境在 eventBind:function(){ }

紧接到 $(‘.someClass’).on(‘click’,function(event) { })
爆发了改动,上述使用变量保存

this 那么些艺术都是实用的,也并未什么问题。当然使用 bind()
可以更进一步雅致的缓解这些问题:

varfoo = {

bar : 1,

eventBind:function(){

$(‘.someClass’).on(‘click’,function(event) {

/* Act on the event */

console.log(this.bar);//1

}.bind(this));

}

}

在上述代码里,bind()
创设了一个函数,当那一个click事件绑定在被调用的时候,它的 this

关键词会被设置成被盛传的值(那里指调用bind()时传出的参数)。由此,那里大家传入想要的上下文
this(其实就是 foo ),到

bind() 函数中。然后,当回调函数被实施的时候, this
便指向 foo 对象。再来一个简单的板栗:

var bar =function(){

console.log(this.x);

}

var foo = {

x:3

}

bar();// undefined

var func = bar.bind(foo);

func();// 3

此处大家成立了一个新的函数 func,当使用 bind()
创造一个绑定函数之后,它被实施的时候,它的 this 会被设置成 foo ,
而不是像大家调用 bar() 时的全局成效域。

有个有趣的题材,若是连接 bind() 四次,亦或者是接二连三 bind()
三回那么输出的值是何等吧?像那样:

varbar =function(){

console.log(this.x);

}

var foo = {

x:3

}

var sed = {

x:4

}

var func = bar.bind(foo).bind(sed);

func();//?

var fiv = {

x:5

}

var func = bar.bind(foo).bind(sed).bind(fiv);

func();//?

答案是,五遍都仍将出口 3 ,而非期待中的 4 和 5
。原因是,在Javascript中,数十次 bind()

是行不通的。更深层次的因由, bind() 的达成,相当于选拔函数在里头包了一个
call / apply ,第二次 bind()

相当于再包住第四次 bind() ,故第二次之后的 bind 是无法生效的。


“对我来说,博客首先是一种文化管理工具,其次才是传播工具。我的技能文章,首要用来整治自己还不懂的学识。我只写那一个自己还一向不完全驾驭的东西,那多少个自己精通的事物,往往没有重力写。炫耀没有是自家的意念,好奇才是。”

var func = function(arg1, arg2) {

apply、call、bind比较

那么 apply、call、bind 三者相比较,之间又有何异同呢?何时使用
apply、call,曾几何时使用 bind 呢。不难的一个板栗:

var obj = {

x: 81,

};

var foo = {

getX:function() {

return this.x;

}

}

console.log(foo.getX.bind(obj)());//81

console.log(foo.getX.call(obj));//81

console.log(foo.getX.apply(obj));//81

七个出口的都是81,不过注意看使用 bind() 方法的,他背后多了对括号。

也就是说,分歧是,当您期望改变上下文环境之后并非立时实施,而是回调执行的时候,使用
bind() 方法。而 apply/call 则会马上施行函数。

再统计一下:

apply 、 call 、bind 三者都是用来改变函数的this对象的对准的;

apply 、 call 、bind
三者第三个参数都是this要针对性的对象,也就是想指定的上下文;

apply 、 call 、bind 三者都能够选拔三番五次参数传参;

bind 是回去对应函数,便于稍后调用;apply 、call 则是登时调用 。

 

};
就足以经过如下格局来调用:

对此那句话,不可以协助更多,也让自身下决心好好写那篇,网上小说虽多,大多复制粘贴,且晦涩难懂,我梦想可以透过那篇文章,可以清晰的提高对apply、call、bind的认识,并且列出一部分它们的妙用加深回忆。

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
个中 this 是你想指定的上下文,他得以是其余一个 JavaScript
对象(JavaScript 中总体皆对象),call 必要把参数按梯次传递进入,而 apply
则是把参数放在数组里。
JavaScript
中,某个函数的参数数量是不定点的,因而要说适用条件的话,当您的参数是简单来说知晓多少时用
call 。
而不确定的时候用 apply,然后把参数 push
进数组传递进入。当参数数量不确定时,函数内部也得以经过 arguments
这几个数组来遍历所有的参数。
为了巩固深化纪念,下边罗列部分常用用法:
1、数组之间追加

 

var array1 = [12 , "foo" , {name "Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

apply、call

2、获取数组中的最大值和最小值

 

var  numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers),   //458
maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

在 javascript 中,call 和 apply
都是为了转移某个函数运行时的上下文(context)而存在的,换句话说,就是为着转移函数体内部
this 的指向。

number 本身没有 max 方法,可是 Math 有,大家就足以凭借 call 或者 apply
使用其艺术。

 

3、验证是不是是数组(前提是toString()方法没有被重写过)

JavaScript
的一大特色是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是足以变动的」这样的定义。

functionisArray(obj){
return Object.prototype.toString.call(obj) === ‘[object Array]’ ;
}
4、类(伪)数组使用数组方法

 

var domNodes =
Array.prototype.slice.call(document.getElementsByTagName(“*”));
Javascript中留存一种名为伪数组的靶子社团。比较特其他是 arguments
对象,还有像调用 getElementsByTagName , document.childNodes
之类的,它们再次回到NodeList对象都属于伪数组。不可能应用 Array下的 push , pop
等措施。
唯独我们能经过 Array.prototype.slice.call 转换为实在的数组的涵盖 length
属性的对象,那样 domNodes 就足以选拔 Array 下的持有办法了。
深刻精晓运用apply、call
上边就借出一道面课题,来更深刻的去精晓下 apply 和 call 。
概念一个 log 方法,让它可以代劳 console.log 方法,常见的化解方法是:

先来一个板栗:

function log(msg) {
  console.log(msg);
}
log(1);    //1
log(1,2);    //1

 

地点方法能够化解最主题的须要,可是当传入参数的个数是不确定的时候,上边的主意就失效了,这么些时候就可以设想使用
apply 或者
call,注意那里传出几个参数是不确定的,所以选择apply是最好的,方法如下:

function fruits() {}

 

fruits.prototype = {

color: “red”,

say: function() {

console.log(“My color is ” + this.color);

}

}

 

var apple = new fruits;

apple.say(); //My color is red

function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2

 

接下去的须要是给每一个 log 信息添加一个”(app)”的前辍,比如:
log(“hello world”); //(app)hello world
该怎么办相比优雅呢?这几个时候要求想到arguments参数是个伪数组,通过
Array.prototype.slice.call
转化为正规数组,再利用数组方法unshift,像这么:

唯独如果大家有一个目标banana= {color : “yellow”} ,大家不想对它再一次定义
say 方法,那么我们得以由此 call 或 apply 用 apple 的 say 方法:

function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift('(app)');

  console.log.apply(console, args);
};

 

bind
说完了 apply 和 call ,再来说说bind。bind() 方法与 apply 和 call
很相似,也是足以更改函数体内 this 的对准。
MDN的诠释是:bind()方法会创立一个新函数,称为绑定函数,当调用那个绑定函数时,绑定函数会以创制它时传出
bind()方法的第二个参数作为 this,传入 bind()
方法的第一个以及随后的参数加上绑定函数运行时我的参数根据顺序作为原函数的参数来调用原函数。
直白来探视实际怎么样行使,在普遍的单体方式中,平日我们会拔取 _this , that
, self 等保存 this ,那样我们得以在改变了上下文之后持续引用到它。
像那样:

banana = {

color: “yellow”

}

apple.say.call(banana); //My color is yellow

apple.say.apply(banana); //My color is yellow

var foo = {
    bar : 1,
    eventBind: function(){
        var _this = this;
        $('.someClass').on('click',function(event) {
            /* Act on the event */
            console.log(_this.bar);     //1
        });
    }
}

 

鉴于 Javascript 特有的建制,上下文环境在 eventBind:function(){ } 过渡到
$(‘.someClass’).on(‘click’,function(event) { })
发生了转移,上述使用变量保存 this
那几个方法都是实惠的,也从未什么样问题。当然使用 bind()
可以越发文雅的化解这几个题目:

之所以,可以寓目 call 和 apply 是为着动态改变 this 而产出的,当一个 object
没有某个方法(本栗子中banana没有say方法),不过其余的有(本栗子中apple有say方法),大家得以凭借call或apply用任何对象的办法来操作。

var foo = {
    bar : 1,
    eventBind: function(){
        $('.someClass').on('click',function(event) {
            /* Act on the event */
            console.log(this.bar);      //1
        }.bind(this));
    }
}

 

在上述代码里,bind()
创制了一个函数,当那些click事件绑定在被调用的时候,它的 this
关键词会被设置成被流传的值(那里指调用bind()时传出的参数)。因而,那里大家传入想要的左右文
this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被执行的时候,
this 便指向 foo 对象。再来一个简单的栗子:

apply、call 的区别

var bar = function(){
    console.log(this.x);
}

bar(); // undefined
var func = bar.bind(foo);
func(); // 3

 

此处大家成立了一个新的函数 func,当使用 bind()
制造一个绑定函数之后,它被实施的时候,它的 this 会被设置成 foo ,
而不是像大家调用 bar() 时的全局功效域。
apply、call、bind比较
那就是说 apply、call、bind 三者相相比,之间又有何异同呢?哪天使用
apply、call,什么日期使用 bind 呢。不难的一个板栗:

对于 apply、call
二者而言,效用完全一致,只是接受参数的不二法门不太一样。例如,有一个函数定义如下:

var obj = {
    x: 81,
};

var foo = {
    getX: function() {
        return this.x;
    }
}

console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

 

多少个出口的都是81,可是注意看使用 bind() 方法的,他背后多了对括号。
也就是说,差异是,当你指望改变上下文环境之后不要立时施行,而是回调执行的时候,使用
bind() 方法。而 apply/call 则会及时执行函数。
再下结论一下:
* apply 、 call 、bind 三者都是用来改变函数的this对象的针对性的;
* apply 、 call 、bind
三者第二个参数都是this要本着的靶子,也就是想指定的上下文;
* apply 、 call 、bind 三者都足以使用接二连三参数传参;
* bind 是回去对应函数,便于稍后调用;apply 、call 则是立时调用 。

var func = function(arg1, arg2) {

 

};

 

就足以经过如下格局来调用:

 

func.call(this, arg1, arg2);

func.apply(this, [arg1, arg2])

 

中间 this 是你想指定的上下文,他得以是任何一个 JavaScript
对象(JavaScript 中所有皆对象),call 必要把参数按梯次传递进入,而 apply
则是把参数放在数组里。  

 

JavaScript
中,某个函数的参数数量是不固定的,因而要说适用标准的话,当您的参数是家喻户晓知道数据时用
call 。

 

而不确定的时候用 apply,然后把参数 push
进数组传递进入。当参数数量不确定时,函数内部也得以因而 arguments
那一个数组来遍历所有的参数。

 

为了巩固深化回忆,上边列举部分常用用法:

 

1、数组之间追加

 

var array1 = [12 , “foo” , {name “Joe”} , -2458];

var array2 = [“Doe” , 555 , 100];

Array.prototype.push.apply(array1, array2);

/* array1 值为 [12 , “foo” , {name “Joe”} , -2458 , “Doe” , 555 ,
100] */

 

2、获取数组中的最大值和最小值

 

var numbers = [5, 458 , 120 , -215 ];

var maxInNumbers = Math.max.apply(Math, numbers), //458

maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

 

number 本身没有 max 方法,可是 Math 有,我们就足以看重 call 或者 apply
使用其方法。

 

3、验证是或不是是数组(前提是toString()方法没有被重写过)

 

functionisArray(obj){

    returnObject.prototype.toString.call(obj) === ‘[object Array]’ ;

}

 

4、类(伪)数组使用数组方法

 

var domNodes = Array.prototype.slice.call(document.getElementsByTagName(“*”));

 

Javascript中设有一种名为伪数组的对象协会。相比较特其余是 arguments
对象,还有像调用 getElementsByTagName , document.childNodes
之类的,它们重临NodeList对象都属于伪数组。不可以接纳 Array下的 push , pop
等办法。

 

不过我们能经过 Array.prototype.slice.call 转换为确实的数组的带有 length
属性的目的,这样 domNodes 就足以采取 Array 下的兼具办法了。

 

深远掌握运用apply、call

 

上面就借出一道面课题,来更深刻的去明白下 apply 和 call 。

 

概念一个 log 方法,让它可以代劳 console.log 方法,常见的缓解方法是:

 

function log(msg) {

    console.log(msg);

}

log(1); //1

log(1,2); //1

 

下边方法可以化解最宗旨的要求,不过当传入参数的个数是不确定的时候,上边的情势就失效了,那几个时候就足以考虑采纳apply 或者
call,注意那里流传多少个参数是不确定的,所以利用apply是最好的,方法如下:

 

function log(){

    console.log.apply(console, arguments);

};

log(1); //1

log(1,2); //1 2

 

接下去的渴求是给每一个 log 信息添加一个”(app)”的前辍,比如:

 

log(“hello world”); //(app)hello world

 

该如何是好比较优雅呢?这些时候必要想到arguments参数是个伪数组,通过
Array.prototype.slice.call
转化为规范数组,再使用数组方法unshift,像这么:

 

function log(){

    var args = Array.prototype.slice.call(arguments);

    args.unshift(‘(app)’);

 

    console.log.apply(console, args);

};

 

bind

 

说完了 apply 和 call ,再来说说bind。bind() 方法与 apply 和 call
很一般,也是能够更改函数体内 this 的对准。

 

MDN的诠释是:bind()方法会创造一个新函数,称为绑定函数,当调用那几个绑定函数时,绑定函数会以创立它时传出
bind()方法的率先个参数作为 this,传入 bind()
方法的第四个以及随后的参数加上绑定函数运行时自己的参数依照顺序作为原函数的参数来调用原函数。

 

一平昔探视现实怎么样行使,在普遍的单体情势中,常常我们会拔取 _this , that
, self 等保存 this ,那样大家得以在转移了上下文之后继续引用到它。
像那样:

 

var foo = {

bar : 1,

eventBind: function(){

var _this = this;

$(‘.someClass’).on(‘click’,function(event) {

/* Act on the event */

console.log(_this.bar); //1

});

}

}

 

由于 Javascript 特有的体制,上下文环境在 eventBind:function(){ } 过渡到
$(‘.someClass’).on(‘click’,function(event) { })
发生了改观,上述使用变量保存 this
这个方式都是实用的,也绝非怎么问题。当然使用 bind()
能够进一步雅致的化解这么些问题:

 

var foo = {

bar : 1,

eventBind: function(){

$(‘.someClass’).on(‘click’,function(event) {

/* Act on the event */

console.log(this.bar); //1

}.bind(this));

}

}

 

在上述代码里,bind()
创设了一个函数,当那么些click事件绑定在被调用的时候,它的 this
关键词会被设置成被流传的值(那里指调用bind()时传出的参数)。由此,那里我们传入想要的光景文
this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被实施的时候,
this 便指向 foo 对象。再来一个不难的栗子:

 

var bar = function(){

console.log(this.x);

}

 

bar(); // undefined

var func = bar.bind(foo);

func(); // 3

 

那里大家成立了一个新的函数 func,当使用 bind()
创设一个绑定函数之后,它被实践的时候,它的 this 会被设置成 foo ,
而不是像我们调用 bar() 时的全局功用域。

 

有个有意思的题目,倘使延续 bind() 一次,亦或者是延续 bind()
三遍那么输出的值是何等啊?像那样:

 

var bar = function(){

console.log(this.x);

}

var foo = {

x:3

}

var sed = {

x:4

}

var func = bar.bind(foo).bind(sed);

func(); //?

 

var fiv = {

x:5

}

var func = bar.bind(foo).bind(sed).bind(fiv);

func(); //?

 

答案是,三遍都仍将出口 3 ,而非期待中的 4 和 5
。原因是,在Javascript中,数次 bind() 是船到江心补漏迟的。更深层次的原委, bind()
的完成,约等于采取函数在中间包了一个 call / apply ,第二次 bind()
相当于再包住第二回 bind() ,故第二次将来的 bind 是力不从心生效的。

 

apply、call、bind比较

 

那就是说 apply、call、bind 三者相相比,之间又有如何异同呢?几时使用
apply、call,什么时候使用 bind 呢。不难的一个板栗:

 

var obj = {

x: 81,

};

 

var foo = {

getX: function() {

return this.x;

}

}

 

console.log(foo.getX.bind(obj)()); //81

console.log(foo.getX.call(obj)); //81

console.log(foo.getX.apply(obj)); //81

 

三个出口的都是81,可是注意看使用 bind() 方法的,他背后多了对括号。

 

也就是说,不一致是,当您期望改变上下文环境之后并非马上执行,而是回调执行的时候,使用
bind() 方法。而 apply/call 则会立时实施函数。

 

再统计一下:

 

  • apply 、 call 、bind 三者都是用来改变函数的this对象的对准的;

  • apply 、 call 、bind
    三者第三个参数都是this要对准的目的,也就是想指定的上下文;

  • apply 、 call 、bind 三者都得以采纳三番五次参数传参;

  • bind是回来对应函数,便于稍后调用;apply、call则是及时调用 。

 

本文实例出现的保有代码,在自家的github上可以下载。

网站地图xml地图