Ich habe viele Informationen gesehen, die besagen, dass das Objekt, das diese Funktion aufruft, in dieser Funktion auf dieses Objekt verweist.
Im folgenden Beispiel wird die Funktion foo über die Anweisung foo() aufgerufen. Warum zeigt dies auf die globale Welt? Wird Window.foo() nicht vom globalen Objekt aufgerufen?
Bitte um Rat, danke!
var x = 10;
var obj = {
x: 20,
f: function () {
var foo = function (){
console.log(this.x);
}
foo();
}
};
obj.f(); //10
樓上講的有點(diǎn)問題,foo不是全局變量,簡(jiǎn)單點(diǎn)來判斷(非嚴(yán)格模式)就是:
1.當(dāng)一個(gè)函數(shù)沒有被指定上級(jí)對(duì)象的時(shí)候,this指向window
2.當(dāng)一個(gè)函數(shù)有被指定上級(jí)對(duì)象的時(shí)候,this僅指向最靠近的上級(jí)(父)對(duì)象
如 foo.fn.o() , o里面的this指向fn
是這樣子的,我寫在注釋里面
var x = 10;
var obj = {
x: 20,
f: function () {
var foo = function (){
console.log(this.x);//你這是把函數(shù)賦值給一個(gè) foo的變量。此時(shí)的 foo 是全局的,所以下面調(diào)用 foo()這里是10嘛
}
foo();
}
};
obj.f(); // 這個(gè)調(diào)用 f 函數(shù),因?yàn)?f(),并沒有返回出去什么,所以這里是 undefined
對(duì)于內(nèi)部函數(shù)
,即聲明在另一個(gè)函數(shù)體內(nèi)的函數(shù),都將會(huì)綁定到全局對(duì)象
上,這是JavaScript的設(shè)計(jì)缺陷
,正確的設(shè)計(jì)方式是內(nèi)部函數(shù)的this應(yīng)該綁定到其外層函數(shù)對(duì)應(yīng)的對(duì)象上,所以導(dǎo)致以上問題。
為了規(guī)避這一設(shè)計(jì)缺陷,可以采用變量替代
的方法,約定俗成,可以使用self
或that
,代碼如下:
var x = 10;
var obj = {
x: 20,
f: function () {
var self = this;
var foo = function (){
console.log(self.x);
}
foo();
}
};
obj.f();
首先搞清楚一個(gè)道理:
1: window也是一個(gè)對(duì)象,它是一個(gè)特殊的對(duì)象,它代表全局。 當(dāng)你以以下方式調(diào)用一個(gè)函數(shù)的時(shí)候:
function foo(){....}
foo();//
第二行的這種調(diào)用方式(函數(shù)前面沒有一個(gè)你自己定義的object),我們叫做‘全局調(diào)用’。其實(shí)等同于window.foo()。所以你看出來了嗎?在全局調(diào)用函數(shù),其實(shí)是在對(duì)象上調(diào)用函數(shù)的一個(gè)特例,因?yàn)檫@時(shí)候的對(duì)象是window.
2: 那為什么上面的代碼是在全局調(diào)用了foo(),而不是在obj上面呢?我把代碼改一下,讓他輸出20:
var x = 10;
var obj = {
x: 20,
f: function () {
console.log(this.x);
}
};
obj.f();//20
對(duì)比一下,兩段代碼,找找它們的不同。
var x = 10;
var obj = {
x: 20,
f: function () {
console.log(this.x); // 20
var foo = function (){
// 這里函數(shù)的作用域是window
console.log(this.x);
}
foo();
}
};
obj.f(); //10
var x = 10;
var obj = {
x: 20,
f: function () {
let that = this;
var foo = function (){
// 這里形成了閉包
console.log(that.x);
}
foo();
}
};
obj.f(); //20
你可以把代碼改寫為這樣子的:
var x = 10;
var obj = {
x: 20,
f: function () {
var foo = function (){
console.log(this.x);
}
foo.call(null) // 等價(jià)于foo.call(window)
}
};
obj.f.call(obj); //10 結(jié)果不變
通過上面的例子,你可以這樣理解 當(dāng)調(diào)用一個(gè)函數(shù)的時(shí)候,JavaScript解析器是按照call或者apply這樣的形式去調(diào)用的。通過這樣的方式來為函數(shù)中的this指定一個(gè)值。這兩個(gè)方法的第一個(gè)參數(shù)就是foo方法被調(diào)用時(shí)其內(nèi)部this的值,如果call方法的第一個(gè)參數(shù)為null、undefined時(shí),就會(huì)默認(rèn)把全局對(duì)象作為第一個(gè)參數(shù)(你可以試試foo.call()、foo.call(null)、foo.call(undefined))