一 、關(guān)于this
Javascript中的this經(jīng)常讓人糊涂,但總的一個原則就是,this總是指向一個對象,而具體指向哪個對象是在javascript執(zhí)行階段由執(zhí)行環(huán)境動態(tài)綁定的,而非在javascript初始化階段聲明時的環(huán)境
實際中,this的指向大概分為以下四類:
(1) 作為對象的方法調(diào)用
(2) 作為普通函數(shù)調(diào)用
(3) 構(gòu)造器調(diào)用
(4) Function,prototype.call或Function.prototype.apply,動態(tài)的改變出入函數(shù)的this
1.作為對象的方法調(diào)用時,this指向改對象
var obj = {
name:"xiaoming",
age:25,
say:function(){
alert(this === obj);
alert("我叫" + this.name + "我今年" + this.age + "歲");
}
};
obj.say();
2.作為普通函數(shù)調(diào)用,this總是指向全局對象window
alert(this); ?//window
var name = "xiaoming";
function getName(){
return this.name;
}
alert(getName()); //xiaoming
3. 構(gòu)造器調(diào)用, 當用 new 運算符調(diào)用函數(shù)時,該函數(shù)總是會返回一個對象,通常情況下,構(gòu)造函數(shù)里的 this 就指向返回的這個對象
function Person(){
this.name = "xiaoming";
}
var xiaoming = new Person();
alert(xiaoming.name);
在構(gòu)造函數(shù)中還有一種特例,那就是在構(gòu)造函數(shù)中顯示的返回一個對象,那這個this就不跟我們期待的一樣了,例如:
function Person(){
this.name = "xiaoming";
return {
name:"我是另外一個xiaoming"
}
}
var which = new Person();
alert(which.name); //我是另外一個xiaoming
二 、接下來說說apply.call,bind的區(qū)別以及他們中的this
var xiaoming = {
name:"xiaoming",
age:25,
say:function(){
console.log("我叫"+this.name+",我今年"+this.age+"歲了。");
}
}
var xiaoli = {
name:"xiaoli",
age:27
}
xiaoming.say() //很明顯,就是"我叫xiaoming,我今年25歲了"
//如果我現(xiàn)在想打印出xiaoli的名字,怎么辦呢?那就用到了call,apply.bind
//他們的作用就是改變this指向的對象
xiaoming.say.call(xiaoli);
xiaoming.say.apply(xiaoli);
xiaoming.say.bind(xiaoli)();
從以上代碼中我們發(fā)現(xiàn)call.bind,apply都可以改變this的指向,但是好像call和apply沒什么區(qū)別呀?難道兩個的作用是一樣的?答案是當然不一樣。
bind的區(qū)別已經(jīng)很明顯了,bind后面需要加一個(),這又是為什么呢?
這是因為call和apply直接返回的是函數(shù)調(diào)用后的結(jié)構(gòu),而bind方法返回的是一個函數(shù),不信,你可以typeof一下,看返回的是不是function哦。
好,接下來解決call和apply到底有什么區(qū)別呢?如果現(xiàn)在我把代碼改一下
var xiaoming = {
name:"xiaoming",
age:25,
say:function(school,hobby){
console.log(this.name+"|"+this.age+"|"+school+hobby);
}
}
var xiaoli = {
name:"xiaoli",
age:27
}
xiaoming.say.call(xiaoli,"shcool1","羽毛球");
xiaoming.say.apply(xiaoli,["school1","羽毛球"])
從上面可以看出,他們的區(qū)別無非就是傳參的形式不一樣,apply必須把參數(shù)放進數(shù)組
三、最后再來說說bind方法
bind方法就是把函數(shù)綁定到一個對象上。但里面有一點坑是,用bind返回的函數(shù),它是沒有prototype屬性的。
四 .另外apply和call還能繼承
function Person(name,age){
this.name = name;
this.age = age;
}
function student(name,age,className){
Person.call(this,name,age);
this.className = className;
}
var Amy = new student("Amy",25,"一年級");
console.log(Amy.age)