一旦签、js默認(rèn)綁定
在全局聲明的對象或者函數(shù)都會被認(rèn)為是window對象下的毙石,這時(shí)候默認(rèn)this是綁定到全局作用域下的window對象下
function foo(){
console.log(this.a);
}
var a=2;
foo();
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
} };
alert(object.getNameFunc()()); //"The Window"
由于getNameFunc函數(shù)返回一個(gè)函數(shù)渐行,因此這個(gè)函數(shù)會立即執(zhí)行,函數(shù)會搜索this和argument,只能搜索到活動(dòng)對象為止,不能訪問外部函數(shù)這兩個(gè)變量喇完。執(zhí)行變成
var func = object.getNameFunc(); func(); //這個(gè)func結(jié)果在全局作用域執(zhí)行了,沒在object活動(dòng)作用域執(zhí)行
從而導(dǎo)致最終調(diào)用函數(shù)的執(zhí)行環(huán)境是window
我們使用閉包可以改進(jìn)如下代碼
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //"My Object"
二剥啤、隱式綁定
當(dāng)函數(shù)引用時(shí)候存在上下文的時(shí)候會產(chǎn)生隱式綁定 this總是指向調(diào)用該函數(shù)的對象锦溪,就是看點(diǎn)前面的變量是誰,this就指向誰(看執(zhí)行函數(shù)前面有沒有點(diǎn))
var a=3;
function foo(){
console.log(this.a);
}
var obj={
a:2,
foo:foo
}
foo(); //3
obj.foo(); //2
三府怯、顯式綁定
顯示綁定就是常用的call刻诊,apply,bind函數(shù)強(qiáng)制綁定this的指向
具體實(shí)現(xiàn)方式可以參考 call牺丙,apply则涯、bind實(shí)現(xiàn)原理這篇文章
四、new綁定
function lala(a){
this.a=a;
}
foo(4);
var obj=new lala(2);
console.log(a); // 4
console.log(obj.a); // 2
new的源代碼中會將傳入的構(gòu)造函數(shù)的prototype賦值給一個(gè)新new出來的object對象的-proto-屬性上,同時(shí)會使用apply去改變this指向?qū)魅氲臉?gòu)造函數(shù)的this指向改變到新new出來的object對象上面去 從而實(shí)現(xiàn)構(gòu)造函數(shù)的繼承粟判,將傳入的一些屬性繼承下來肖揣,實(shí)現(xiàn)原理如下
function objectFactory() {
var obj = new Object();
var [Constructor, ...args] = [ ...arguments];
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, args);
return obj;
};
五、
但是在settimeout里面就有所不同浮入,這是由于setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上。這會導(dǎo)致這些代碼中包含的 this 關(guān)鍵字會在
非嚴(yán)格模式下指向 window (或全局)對象
嚴(yán)格模式指向undefined
那么需要使用箭頭函數(shù)綁定this羊异,看下面??
var obj={
num:3,
fn:function(){
setTimeout(function(){
console.log(this.num);
});
}
}
obj.fn();//undefined
var obj1={
num:4,
fn:function(){
setTimeout(() => {
console.log(this.num);
});
}
}
obj1.fn();//4
箭頭函數(shù)沒有自己的this事秀,是繼承來的,箭頭函數(shù)的this指向的是誰調(diào)用箭頭函數(shù)的外層function野舶,箭頭函數(shù)的this就是指向該對象易迹,如果箭頭函數(shù)沒有外層函數(shù),則指向window平道。這樣可以方便地讓我們在 setTimeout ,setInterval中方便的使用this睹欲。此問題也可以使用bind來綁定this,或者將this存在一個(gè)變量來調(diào)用
var c = {
lala: 2,
fun: () => {
console.log(this, '//////'); // 這里的this指向window 箭頭函數(shù)外層沒有function
this.lala++;
console.log(this.lala);
}
}
c.fun();
c.fun();
var c = {
lala: 2,
fun: function() {
return () => {
console.log(this, '//////'); // 這里的this指向c 因?yàn)榧^函數(shù)外層有function一屋,這個(gè)function是c調(diào)用
this.lala++;
console.log(this.lala);
}
}
}
c.fun()();
c.fun()();