關於node中的this,module,exports
接觸到node後對於node中可以自由使用module和exports感到很神奇,再加上自己碰到的一些問題,做了一些總結,先丟擲自己的一些問題:
場景1:
const redis=require("redis");
var client=redis.createClient("6379","127.0.0.1");
client.on("error", (error)=>{
console.log(error);
});
client.on("connect", ()=>{
console.log("redis connect successful");
});
console .log(this); //{}
console.log(exports);//{}
console.log(module.exports);//{}
module.exports=client;
console.log(this);//{}
console.log(exports);//{}
console.log(module.exports);// RedisClientObj
場景2
const redis=require("redis");
var client=redis.createClient("6379","127.0.0.1");
client.on("error", (error)=>{
console .log(error);
});
client.on("connect", ()=>{
console.log("redis connect successful");
});
console.log(this); //{}
console.log(exports);//{}
console.log(module.exports);//{}
exports=client;
console.log(this);//{}
console.log(exports);//RedisClientObj console.log(module.exports);// {}
場景3
const redis=require("redis");
var client=redis.createClient("6379","127.0.0.1");
client.on("error", (error)=>{
console.log(error);
});
client.on("connect", ()=>{
console.log("redis connect successful");
});
console.log(this); //{}
console.log(exports);//{}
console.log(module.exports);//{}
exports.result=client;
console.log(this);//{'result':RedisClientObj}
console.log(exports);//{'result':RedisClientObj}
console.log(module.exports);// {'result':RedisClientObj}
這個模組就是簡單引入redis,這裡redis不是重點,可以忽略,關鍵點是之後的那些console
查詢了很多資料後,感覺以上的問題可以歸咎為2點:
1.node模組執行時幫我們做了什麼操作
2.函式引數的傳遞是值傳遞還是引用傳遞
別急,喝口水,讓我一步步往下講。
首先關鍵是要弄清楚,你寫了一個模組以後,node做了什麼封裝操作,以上面的程式碼為例:
let module={"id":"module_id","exports":{},"path_name":"path_name","children":"children"};
let getResult=function(exports,module){
//開始自己模組的程式碼
const redis=require("redis");
var client=redis.createClient("6379","127.0.0.1");
client.on("error", (error)=>{
console.log(error);
});
client.on("connect", ()=>{
console.log("redis connect successful");
});
module.exports=client;
//自己程式碼塊結束
return module.exports;
}
let exported = getResult.call(module.exports,module.exports,module);
從上面看來,node會為我們先準備一個module物件,然後把他當作函式的引數傳進來,由於使用了call,導致函式體內的this就會指向module.exports,而傳進去的引數又是module.exports和module。
接著在函式體內,我們就可以使用module和exports這兩個引數了,這裡要注意的是,這裡傳參是值傳遞,即該物件的記憶體地址,不是引用傳遞!
然後我們先來看場景1:
通過上面程式碼可以很清楚知道,開始實際上module.exports和exports是指向同一個物件,而this開始又是指向module.exports,所以開始的三個console出來都是空物件。之後開始對module.exports賦值,這裡要注意了,我們使用的module,實際上是傳進來的引數,是外面定義那個module物件的地址,現在我們對module.exports賦值,如此一來,module裡面這個exports的地址指向已經變了,指向了另一塊記憶體,而由於是值傳遞,this和exports儲存的仍然是之前的記憶體地址,所以他們仍然為{}
再看場景2:
同樣的道理,這次對exports賦值,也只有exports會變化,而this和module.exports還是指向之前的記憶體地址。
場景3:
這裡的賦值是對exports.res來說的,這裡並沒有開闢新的記憶體去覆蓋exports,只是在exports上新加了一個屬性罷了,所以exports的記憶體地址沒有改變,最後三個打印出來都是被賦了值的物件。
以上只是自己的一些總結,歡迎指正。