作者:shihuaping0918@163.com儒老,轉(zhuǎn)載請注明作者
在繼續(xù)分析代碼之前蝴乔,需要先講一下node.js中的this是什么。因?yàn)椴恢v這個(gè)的話驮樊,后面的內(nèi)容進(jìn)行不下去淘这。在以前版本的node.js中,全局this是個(gè)空對(duì)象巩剖,在node8的repl中铝穷,全局this和global是相等的。
> this === global
true
>
但是佳魔,如果使用node8執(zhí)行js文件曙聂,全局this是個(gè)空對(duì)象。
console.log(this)
let result = this === global
console.log(result)
執(zhí)行結(jié)果:
{}
false
好鞠鲜,這個(gè)很操蛋的事實(shí)還是要接受的宁脊。node.js中的this和瀏覽器中的this又是不一樣的。忘掉在瀏覽器中的經(jīng)驗(yàn)吧贤姆,只要記得this只能隨著函數(shù)走就行了榆苞。為了不影響三觀,后面的js語句都只能在文件中寫好霞捡,然后再用node去執(zhí)行它坐漏。
在C++/java中,this永遠(yuǎn)都是和某個(gè)對(duì)象相關(guān)的碧信,this生存在類作用域中赊琳,隱式存在著。但是在node.js中砰碴,它的行為很是詭異躏筏。
一、在普通函數(shù)中的this呈枉,實(shí)際上是在引用global趁尼,如果你不相信,就執(zhí)行一下下面的代碼猖辫。記得先保存文件酥泞,然后再執(zhí)行文件。
function fn(){
this.num = 10;
}
fn();
console.log(this); {}
console.log(this.num); undefined
console.log(global.num); 10
二住册、this作用域是和函數(shù)緊密相關(guān)的婶博。來看段稍微長一點(diǎn)的代碼。
var name = "like global...";
function one() {
var name = "in func one...";
var other = "somewhat...";
function two() {
var name = "in func two...";
console.log({name: name, other: other});
}
two();
console.log({name: name, other: other});
}
one();
console.log({name: name});
console.log({other: other});
這段代碼是執(zhí)行不了的,語法報(bào)錯(cuò)凡人。執(zhí)行環(huán)境node8名党,其它的環(huán)境也許能通過。在console.log({other:other})引用了函數(shù)one作用域里的other挠轴。都是不合法的传睹。
那什么情況是合法的,只有引用作用域內(nèi)的才合法岸晦。
var name = "like global...";
function one() {
var name = "in func one...";
var other = "somewhat...";
function two() {
var name = "in func two...";
console.log({name: name,other:other });
}
two();
console.log({name: name, other: other});
}
one();
console.log({name: name});
代碼證明欧啤,同名變量可以在不同作用域存在,不同作用域引用同名變量得到的值不同启上。也就是存在作用域同名變量覆蓋的情況邢隧。
三、“構(gòu)造函數(shù)”的this指向的是它自己冈在,而不是global倒慧。
function Person(name,age) {
this.name = name;
this.age = age;
}
let p1 = new Person("lilei", 50);
let p2 = new Person("hanmeimei",45);
console.log(p1);
console.log(p2);
console.log(global.name);
console.log(global.age);
四、this魔幻走位包券,上面看的例子都還好理解纫谅,下面來一個(gè)讓人覺得很詭異的例子。
let Person = {
name : "sam",
age : 18,
foo: function() {
console.log(this.name + ",how old are you?", this.age);
}
};
let Pet = {
name : "dog",
age : 3,
foo : Person.foo
};
Pet.foo();
輸出結(jié)果為
dog,how old are you? 3
驚喜不驚喜溅固,意外不意外付秕?name和age前不加this是執(zhí)行不了的,因?yàn)樽饔糜騿栴}侍郭。但是加上以后呢询吴,為什么輸出的和java/c++中的完全不一樣。原因就是this是隨著執(zhí)行上下文發(fā)生改變的励幼。ecma5提供了一個(gè)bind方法汰寓,bind可以指定一個(gè)this參數(shù),以確保函數(shù)在執(zhí)行的時(shí)候苹粟,里面的this永遠(yuǎn)是bind時(shí)的那個(gè)this,而不會(huì)隨著調(diào)用上下文發(fā)生變化跃闹。
最后總結(jié)一下:
1.在js中嵌削,創(chuàng)建一個(gè)作用域的唯一方法就是使用function關(guān)鍵字。for循環(huán)望艺,case之類的都不行苛秕。這和c++/java是不一樣的。
2.var聲明的變量在整個(gè)當(dāng)前域都是有效的找默,?而且它會(huì)覆蓋外部同名變量艇劫。
3.this和arguments是隨著代碼調(diào)用位置的變化而變化的。每個(gè)嵌套層次切換時(shí)都發(fā)生變化惩激。