1. call、apply、bind作用于函數(shù)上
2. call
<script type="text/javascript">
var Dog = function () {
this.name = "旺星人";
this.shout = function () {
alert(this.name);
}
};
var Cat = function () {
this.name = "喵星人";
};
var dog = new Dog();
var cat = new Cat();
dog.shout.call(cat); //dog.shout中的this對(duì)象,將指向cat對(duì)象。
dog.shout(); //this還是指向dog
</script>
3. apply
<script type="text/javascript">
var xh = {
name: "小紅",
job: "JS工程師"
};
var xm = {
name: "小明",
job: "資深前端開發(fā)工程師"
};
var jx = {
name: "杰西",
job: "前端開發(fā)總監(jiān)"
};
//杰西,男,今年24歲,在前端開發(fā)網(wǎng)擔(dān)任前端開發(fā)總監(jiān)一職
function myjob(gender, age, company) {
alert(this.name + "," + gender + ",今年" + age + "歲,在" + company + "擔(dān)任" + this.job + "一職");
}
myjob.call(xh, "女", 22, "騰訊");
myjob.call(xm, "男", 23, "谷歌");
myjob.call(jx, "男", 24, "前端開發(fā)網(wǎng)");
myjob.apply(xh, ["女", 22, "騰訊"]);
myjob.apply(xm, ["男", 23, "谷歌"]);
myjob.apply(jx, ["男", 24, "前端開發(fā)網(wǎng)"]);
</script>
總結(jié):
- 在call傳入?yún)?shù)的時(shí)候,需要與函數(shù)所接受的參數(shù)一一對(duì)應(yīng);
- 在apply傳入?yún)?shù)的時(shí)候,則以數(shù)組的方式傳入,數(shù)組中的元素需要與函數(shù)所接受的參數(shù)一一對(duì)應(yīng);
- call、apply都是屬于立即調(diào)用
3.bind
- MDN的解釋是:bind()方法會(huì)創(chuàng)建一個(gè)(新函數(shù)),稱為綁定函數(shù),當(dāng)調(diào)用這個(gè)綁定函數(shù)時(shí),綁定函數(shù)會(huì)以創(chuàng)建它時(shí)傳入 bind()方法的第一個(gè)參數(shù)作為 this,傳入 bind() 方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。
// 1.常用this賦值寫法
<script type="text/javascript">
var foo = {
bar: 1,
eventBind: function () {
var _this = this;
$('.someClass').on('click', function (event) {
/* Act on the event */
console.log(_this.bar); //1
});
}
}
</script>
// 2.bind()改變this指向
<script type="text/javascript">
var foo = {
bar: 1,
eventBind: function () {
$('.someClass').on('click', function (event) {
/* Act on the event */
console.log(this.bar); //1
}.bind(this));
}
}
</script>
- 直接使用對(duì)象屬性
<script type="text/javascript">
var jx = {
name: "杰西",
gender: "男",
age: 24,
company: "前端開發(fā)網(wǎng)(W3Cfuns.com)",
job: "前端開發(fā)總監(jiān)",
say: function () {
alert(this.name + "," + this.gender + ",今年" + this.age + "歲,在" + this.company + "擔(dān)任" + this.job + "一職");
}
};
jx.say();
var xm = jx.say.bind({
name: "小明",
gender: "男",
age: 23,
company: "谷歌 Google",
job: "資深前端開發(fā)工程師"
});
xm();
//注意:JavaScript1.8.5版本中,原生實(shí)現(xiàn)bind方法,目前IE9+,F(xiàn)F4,Chrome7+,opera
</script>
- 重復(fù)使用bind會(huì)有什么效果
<script type="text/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(); //?
</script>
答案是,兩次都仍將輸出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是無效的。更深層次的原因, bind() 的實(shí)現(xiàn),相當(dāng)于使用函數(shù)在內(nèi)部包了一個(gè) call / apply ,第二次 bind() 相當(dāng)于再包住第一次 bind() ,故第二次以后的 bind 是無法生效的。
apply、call、bind比較
<script type="text/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
</script>
- 三個(gè)輸出的都是81,但是注意看使用 bind() 方法的,他后面多了對(duì)括號(hào)。
- 也就是說,區(qū)別是,當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時(shí)候,使用 bind() 方法。而 apply/call 則會(huì)立即執(zhí)行函數(shù)。
再總結(jié)一下:
- apply 、 call 、bind 三者都是用來改變函數(shù)的this對(duì)象的指向的;
- apply 、 call 、bind 三者第一個(gè)參數(shù)都是this要指向的對(duì)象,也就是想指定的上下文;
- apply 、 call 、bind 三者都可以利用后續(xù)參數(shù)傳參;
- bind 是返回對(duì)應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。