apply莱睁、call 有什么作用苍碟,什么區(qū)別
要說(shuō)清除apply和call的作用就要從this的指向開(kāi)始講起
- this值的指向
this, 是函數(shù)內(nèi)部的屬性, 指向的函數(shù)據(jù)以執(zhí)行的環(huán)境對(duì)象, 注意: this的指向只有函數(shù)調(diào)用的時(shí)候才能確定- 在全局調(diào)用的時(shí)候指向的是window
- 作為對(duì)象的方法調(diào)用的時(shí)候指向的是那個(gè)對(duì)象
- 構(gòu)造函數(shù)的時(shí)候指向的是構(gòu)造出來(lái)的對(duì)象
- 在事件的回調(diào)函數(shù)中指的是注冊(cè)事件dom節(jié)點(diǎn)(this === e.currentTarget)
- 只用apply和call調(diào)用的時(shí)候指向的是第一個(gè)參數(shù)指定對(duì)象, 如果第一個(gè)null就指向window
例子:
var name = 'hello'
var obj = {
name: 'world'
}
function sayName() {
console.log(this.name)
}
//全局調(diào)用, 默認(rèn)指向window
sayName()//輸出'hello'
//作為obj的方法調(diào)用, 指向obj
obj.sayName = sayName
obj.sayName()//輸出'world'
//使用call指定this值
sayName.call(obj)//輸出'world'
- apply和call的作用
apply和call的作用是相同的, 都是指定函數(shù)的this值和參數(shù)調(diào)用函數(shù), 其實(shí)JavaScript完全可以不支持使用.
調(diào)用函數(shù)的方法, 例如obj.sayName()
, 這只是一個(gè)語(yǔ)法糖, 使得this的指向去不夠清晰, 而使用apply和call調(diào)用卻使this的指向十分清晰
例如:
sayName.call(null)//如果不指定, 函數(shù)內(nèi)部的this指向的就是window
sayName.call(obj)//指定this的指向?yàn)閛bj
- apply和call的區(qū)別
區(qū)別在于傳遞給函數(shù)的參數(shù), apply接受的是數(shù)組形式, call接受的是多個(gè)參數(shù), 因?yàn)閍pply接受數(shù)組形式的參數(shù), 所以就有一些特別的用法, 例如
var numArr =[1,2,3,4,5,6,7]
Math.min.apply(null, numArr)//就可以獲得數(shù)組中的最小值
Math.max.apply(null,numArr)//就可以獲得數(shù)組中的最大值
注意: 雖然apply接受的是數(shù)組, 但是傳遞給函數(shù)的參數(shù)還是數(shù)組的元素, 而不是整個(gè)數(shù)組
代碼練習(xí)題
//1. 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
//輸出"John: hi!"
//2. 下面代碼輸出什么诵冒,為什么
func()
function func() {
alert(this)
}
//輸出window, 因?yàn)閒unc()是在全局環(huán)境下調(diào)用的, 全局環(huán)境綁定的是window對(duì)象
//3. 下面代碼輸出什么
function fn0(){
function fn(){
console.log(this);
}
fn();
}
fn0();//輸出window對(duì)象
document.addEventListener('click', function(e){
console.log(this);//輸出dom節(jié)點(diǎn)document
setTimeout(function(){
console.log(this);//輸出window對(duì)象
}, 200);
}, false);
//4. 下面代碼輸出什么碍扔,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
//"John"
//因?yàn)閏all的第一個(gè)參數(shù)指定this的值
//5. 代碼輸出躺枕?
var john = {
firstName: "John",
surname: "Smith"
}
function func(a, b) {
alert( this[a] + ' ' + this[b] )
}
func.call(john, 'firstName', 'surname')
//輸出"John Smith"
//6. 以下代碼有什么問(wèn)題歉井,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么, 當(dāng)$btn被點(diǎn)擊的時(shí)候, this指向$btn
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
//問(wèn)題: this指向只有當(dāng)函數(shù)調(diào)用是才確定, 當(dāng)$btn點(diǎn)擊的時(shí)候, this指的是$btn, 而不是module
//修改:
var module= {
bind: function(){
var that = this
$btn.on('click', function(){
console.log(that)
that.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}