(function(){
var obj, sayHi;
obj = {};
sayHi = function(str){
console.log(str);
}
obj.sayHello = function(str1){
sayHi(str1);
}
obj.sayYo = function(str2){
console.log(str2);
}
window.obj = obj;
})()
obj.sayHello("hello world!"); // hello world!
obj.sayYo("yo, what's up?"); // yo, what's up?
我自己碰到的一個小問題,不知道你們有沒有,最近比較喜歡寫匿名函數,剛看到這個的時候,習慣性倒過來看,心想僅僅是把obj暴露出來了,為什麼在執行sayHello的時候可以執行sayHi?
想到之前看過js的運作機制。
不知道是不是這樣子:
js在運作的時候應該是先預解析
所以在執行sayHello之前,匿名函式裡面的sayHello應該已經變成了
obj.sayHello = function(str1){
function(str1){
console.log(str1);
};
};
本人非專業的,不知道這樣理解對不對?
這個是作用域的問題。
只要記住函數在創建的時候就已經保存了作用域,不管你後面在哪裡調用,結果都是一樣,就像你這個程式碼,改成這樣,結果還是一樣(為了下面好分析,給這個立即呼叫函數加個名字,叫test):
分析一下,當obj.sayHello這個函數創建的時候,他會保存著目前所有的作用域:
這時候很明顯sayHi函數在test的作用域裡面,所以sayHello裡面直接保存著這個引用,就算在全局作用域裡面運行了,全局作用域裡面重新定義的sayHi依然無法影響它,因為他是從test函數裡面找的,看看下面這個例子你就懂了:
foo函數的作用域就是foo本身+全域作用域,所以就算在立即執行函數裡面執行,輸出值也不會是20,只會是10
這麼理解不好吧,這應該是閉包概念。 http://www.ruanyifeng.com/blo...
在一個function裡面訪問一個變量,首先先看這個function有沒有聲明這個變量,沒有,就到外層作用域去找,這裡就是這種情形,在(function(){})()這個function裡找到了sayHi,所以就直接呼叫了,如果這個時候是沒有聲明sayHi的話,那就繼續往function外層去找,直接找到全局還是木有。那就沒有然後了