(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?
我自己碰到的一個(gè)小問(wèn)題,不知道你們有沒(méi)有,最近比較喜歡寫匿名函數(shù),剛看到這個(gè)的時(shí)候,習(xí)慣性倒過(guò)來(lái)看,心想僅僅是把obj暴露出來(lái)了,為什麼在執(zhí)行sayHello的時(shí)候可以執(zhí)行sayHi?
想到之前看過(guò)js的運(yùn)作機(jī)制。
不知道是不是這樣子:
js在運(yùn)作的時(shí)候應(yīng)該是先預(yù)解析
所以在執(zhí)行sayHello之前,匿名函式裡面的sayHello應(yīng)該已經(jīng)變成了
obj.sayHello = function(str1){
function(str1){
console.log(str1);
};
};
本人非專業(yè)的,不知道這樣理解對(duì)不對(duì)?
走同樣的路,發(fā)現(xiàn)不同的人生
這個(gè)是作用域的問(wèn)題。
只要記住函數(shù)在創(chuàng)建的時(shí)候就已經(jīng)保存了作用域,不管你後面在哪裡調(diào)用,結(jié)果都是一樣,就像你這個(gè)程式碼,改成這樣,結(jié)果還是一樣(為了下面好分析,給這個(gè)立即呼叫函數(shù)加個(gè)名字,叫test):
(function test(){
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;
})()
var sayHi = function(str) { // 就算在全局作用域里面加個(gè)sayHi函數(shù),也不會(huì)對(duì)sayHello有任何影響
console.log("Hi");
}
obj.sayHello("hello world!"); // hello world!
obj.sayYo("yo, what's up?"); // yo, what's up?
分析一下,當(dāng)obj.sayHello這個(gè)函數(shù)創(chuàng)建的時(shí)候,他會(huì)保存著目前所有的作用域:
sayHello.[[scope]] = [
sayHelloContext.AO,
testContext.VO,
globalContext.VO
]
這時(shí)候很明顯sayHi函數(shù)在test的作用域裡面,所以sayHello裡面直接保存著這個(gè)引用,就算在全局作用域裡面運(yùn)行了,全局作用域裡面重新定義的sayHi依然無(wú)法影響它,因?yàn)樗菑膖est函數(shù)裡面找的,看看下面這個(gè)例子你就懂了:
var x = 10;
function foo() {
alert(x);
}
(function () {
var x = 20;
foo(); // 10
})();
foo函數(shù)的作用域就是foo本身+全域作用域,所以就算在立即執(zhí)行函數(shù)裡面執(zhí)行,輸出值也不會(huì)是20,只會(huì)是10
這麼理解不好吧,這應(yīng)該是閉包概念。 http://www.ruanyifeng.com/blo...
在一個(gè)function裡面訪問(wèn)一個(gè)變量,首先先看這個(gè)function有沒(méi)有聲明這個(gè)變量,沒(méi)有,就到外層作用域去找,這裡就是這種情形,在(function(){})()這個(gè)function裡找到了sayHi,所以就直接呼叫了,如果這個(gè)時(shí)候是沒(méi)有聲明sayHi的話,那就繼續(xù)往function外層去找,直接找到全局還是木有。那就沒(méi)有然後了