this的指向在函數(shù)定義的時候是確定不了的的畴,只有函數(shù)執(zhí)行的時候才能確定this到底指向誰,實際上this的最終指向的是那個調(diào)用它的對象
function a(){
var user = "ben";
console.log(this.user); //undefined
console.log(this); //Window
}
a();
var o = {
user:"ben",
fn:function(){
console.log(this.user); //ben
}
}
o.fn();
this 的四種綁定規(guī)則
this的4種綁定規(guī)則分別是:默認綁定足淆、顯示綁定隱式綁定巢块、、new 綁定巧号。優(yōu)先級從低到高
默認綁定
什么叫默認綁定族奢,即沒有其他綁定規(guī)則存在時的默認規(guī)則。這也是函數(shù)調(diào)用中最常用的規(guī)則丹鸿。
來看這段代碼:
function foo() {
} console.log( this.a );
var a = 2;
foo(); //打印的是什么越走?
foo() 打印的結(jié)果是2。
因為foo()是直接調(diào)用的(獨立函數(shù)調(diào)用),沒有應(yīng)用其他的綁定規(guī)則廊敌,這里進行了默認綁定铜跑,將全局對象綁定this上,所以this.a 就解析成了全局變量中的a骡澈,即2
隱式綁定
除了直接對函數(shù)進行調(diào)用外锅纺,有些情況是,函數(shù)的調(diào)用是在某個對象上觸發(fā)的肋殴,即調(diào)用位置上存在上下文對象囤锉。
function foo() {
console.log( this.a );
}
var a = 2;
var obj = {
a: 3,
foo: foo
};
obj.foo(); // ?
obj.foo() 打印的結(jié)果是3。
這里foo函數(shù)被當做引用屬性护锤,被添加到obj對象上官地。這里的調(diào)用過程是這樣的:
獲取obj.foo屬性 -> 根據(jù)引用關(guān)系找到foo函數(shù),執(zhí)行調(diào)用
所以這里對foo的調(diào)用存在上下文對象obj烙懦,this進行了隱式綁定驱入,即this綁定到了obj上,所以this.a被解析成了obj.a氯析,即3沧侥。
多層調(diào)用鏈
function foo() {
console.log( this.a );
}
var a = 2;
var obj1 = {
a: 4,
foo: foo
};
var obj2 = {
a: 3,
obj1: obj1
};
obj2.obj1.foo(); //?
obj2.obj1.foo() 打印的結(jié)果是4。
同樣魄鸦,我們看下函數(shù)的調(diào)用過程:
先獲取obj1.obj2 -> 通過引用獲取到obj2對象,再訪問 obj2.foo -> 最后執(zhí)行foo函數(shù)調(diào)用
這里調(diào)用鏈不只一層癣朗,存在obj1拾因、obj2兩個對象,那么隱式綁定具體會綁哪個對象旷余。這里原則是獲取最后一層調(diào)用的上下文對象绢记,即obj2,所以結(jié)果顯然是4(obj2.a)正卧。
顯示綁定
相對隱式綁定蠢熄,this值在調(diào)用過程中會動態(tài)變化,可是我們就想綁定指定的對象炉旷,這時就用到了顯示綁定
可以通過這兩個方法call(…)或apply(…)來實現(xiàn)
function foo() {
console.log( this.a );
}
var a = 2;
var obj1 = {
a: 3,
};
var obj2 = {
a: 4,
};
foo.call( obj1 ); // 3
foo.call( obj2 ); // 4
new 綁定
在js中签孔,構(gòu)造函數(shù)與普通函數(shù)的區(qū)別不是很大。接下來就主要講講兩者的區(qū)別窘行。
1.在命名規(guī)則上饥追,構(gòu)造函數(shù)一般是首字母大寫,普通函數(shù)則是遵照小駝峰式命名法罐盔。
2.在函數(shù)調(diào)用時
//構(gòu)造函數(shù)
function Egperson (name,age) {
this.name = name;
this.age = age;
this.sayName = function () {
alert(this.name);
}
}
var person = new Egperson('mike','18'); //this-->person
person.sayName(); //'mike'
//普通函數(shù)
function egPerson (name,age) {
this.name = name;
this.age = age;
this.sayName = function () {
alert(this.name);
}
}
egPerson('alice','23'); //this-->window
window.sayName(); //'alice'