摘要:等價于彈出全局變量和局部變量的區別的變量的是根據方法塊來劃分的也就是說以的一對大括號來劃分。在函數內部,如果沒有用進行申明,則創建的變量是全局變量,而不是局部變量了。
令人心痛的血淋淋教訓,再犯這些錯誤我不是人。
setTimeout與console.log()執行順序setTimeout延時為0時, setTimeout(function(){ console.log(2); },0); console.log(1); //輸出順序:1,2 setTimeout(function(){ console.log(4); },0); setTimeout(function(){ console.log(5); },0); console.log(1); console.log(2); console.log(3); //輸出順序:1,2,3,4,5
原因:(記住嘍,記不住打死你!!?。?/strong>:頁面中所有由setTimeout定義的操作,都將放在同一個隊列中依次執行。而這個隊列的執行時間需要等到函數調用棧執行完畢后才會執行,也就是等待所有的可執行代碼執行完畢,才會輪到setTimeout執行其內部操作,并且按照其時延時間長短順序執行代碼!
再來個高深的:瞅著
setTimeout(function(){ console.log("a:"+a); },0); var a = 1; console.log("b:"+b); var b = 2; var c = 3; var d = 4; var e = 5; function fx(c){ console.log("c:"+c); } function fn(e,d){ console.log("d:"+d); setTimeout(function(){ console.log("e:"+e); },10); } setTimeout(function(){ console.log("b2:"+b); },20); fn(e,d); fx(c);
輸出結果:
原因: 1、console.log()函數會在setTimeout函數之前執行,并且b在輸出之前未被定義所以最先輸出undefined; 2、之后,會執行fn函數和fx函數,而fn函數內存在console.log函數,那么它將會先輸出d的值4; 3、然后,在fx函數內也存在console.log函數,同樣會先輸出c的值3; 4、再來比較setTimeout函數時延長短,依次輸出1,5,2。
3)
for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 0); console.log(i); } //0 1 2 3 3 3 用到了閉包
4)
for (var i = 0; i < 3; i++) {} console.log(i); //3,也就說i可以在for循環體外訪問到。所以是沒有塊級作用域。
5)
var i = 0; setTimeout(function() { console.log(i); }, 0); console.log(i); i++; setTimeout(function() { console.log(i); }, 0); console.log(i); i++; setTimeout(function() { console.log(i); }, 0); console.log(i); i++; 等價于: var i = 0; console.log(i); i++; console.log(i); i++; console.log(i); i++; setTimeout(function() { console.log(i); }, 0); setTimeout(function() { console.log(i); }, 0); setTimeout(function() { console.log(i); }, 0); //彈出 0 1 2 3 3 3全局變量和局部變量的區別
1)
var a = "Hello"; function test(){ var a; alert(a); a = "World"; alert(a); } test();//undefined world
2)
var a = "Hello"; function test(){ alert(a); a = "World"; alert(a); } test();//Hello World
3)
var a =1; function test(){ alert(a); var a = 2; alert(a); } test(); alert(a); //undefined 2 1
Javascript的變量的scope是根據方法塊來劃分的(也就是說以function的一對大括號{ }來劃分)。是function塊,而for、while、if塊并不是作用域的劃分標準,可以看看以下幾個例子:
function?test2(){?????? alert?("before?for?scope:"+i);???? //?i未賦值(并不是未聲明!使用未聲明的變量或函數全拋出致命錯誤而中斷腳本執行)???????//?此時i的值是underfined?????? for(var?i=0;i<3;i++){?????????? alert("in?for?scope:"+i);??//?i的值是?0、1、2,?當i為3時跳出循環?????? }????? alert("after?for?scope:"+i);??//?i的值是3,注意,此時已經在for?scope以外,但i的值仍然保留為3???????????? while(true){?????????? var?j?=?1;?????????? break;?????? }?????? alert(j);???? //?j的值是1,注意,此時已經在while?scope以外,但j的值仍然保留為1???????? if(true){?????????? var?k?=?2;?????? }?????? alert(k);??//k的值是1,注意,此時已經在if?scope以外,但k的值仍然保留為1?? }?? test2();?? //若在此時(function?scope之外)再輸出只存在于test2?這個function?scope里的?i、j、k變量會發生神馬效果呢??? alert(i);?//error!?沒錯,是error,原因是變量i未聲明(并不是未賦值,區分test2函數的第一行輸出),導致腳本錯誤,程序到此結束!?? alert("這行打印還會輸出嗎?"+i);?//未執行?? alert(j);?//未執行?? alert(k);?//未執行
Javascript在執行前會對整個腳本文件的聲明部分做完整分析(包括局部變量),從而確定實變量的作用域。怎么理解呢?看下面一個例子:
var?a?=1;????? function?test(){?????????? alert(a);?//a為undefined!?這個a并不是全局變量,這是因為在function?scope里已經聲明了(函數體倒數第4行)一個重名的局部變量,??????????????????????? //所以全局變量a被覆蓋了,這說明了Javascript在執行前會對整個腳本文件的定義部分做完整分析,所以在函數test()執行前,??????????????????????? //函數體中的變量a就被指向內部的局部變量.而不是指向外部的全局變量.?但這時a只有聲明,還沒賦值,所以輸出undefined。?????????? a=4;????????????????? alert(a);??//a為4,沒懸念了吧??這里的a還是局部變量哦!?????????? var?a;?????//局部變量a在這行聲明?????????? alert(a);??//a還是為4,這是因為之前已把4賦給a了?????? }?????? test();?????? alert(a);?//a為1,這里并不在function?scope內,a的值為全局變量的值?
當全局變量跟局部變量重名時,局部變量的scope會覆蓋掉全局變量的scope,當離開局部變量的scope后,又重回到全局變量的scope,而當全局變量遇上局部變量時,怎樣使用全局變量呢?用window.globalVariableName。
var?a?=1;?????? function?test(){????????????? alert(window.a);??//a為1,這里的a是全局變量哦!?????????? var?a=2;?????//局部變量a在這行定義?????????? alert(a);??//a為2,這里的a是局部變量哦!?????? }?????? test();?????? alert(a);?//a為1,這里并不在function?scope內,a的值為全局變量的值
**總結:(每個例子慢慢看,就全懂了)
1、js有兩級作用域,全局和局部,局部也叫函數作用域
2、全局作用域的變量局部可以使用,局部作用域的變量只能在函數體內使用
3、var和function聲明的變量都聲明提前,賦值留在原地
4、如果局部和全局變量重名,優先使用局部變量
5、第3條和第4條,解釋了全局和局部都有相同變量名的時候,而在函數體內打印的變量是undefined**
一般情況下,是可以省略var的,但有兩點值得注意: 1、var a=1 與 a=1 ,這兩條語句一般情況下作用是一樣的。但是前者不能用delete刪除。不過,絕大多數情況下,這種差異是可以忽略的。 2、在函數內部,如果沒有用var 進行申明,則創建的變量是**全局變量,而不是局部變量**了。所以,建議變量申明加上var關鍵字。
瞅著:
1)
var t = 1; function a(){ console.log(t); var t=2; } a();//undefined;
輸出undefined,原因:function()中相當于
var t; console.log(t); t = 2; 表示變量t已聲明,但還未賦值,輸出undefined。
2)
但是變量提升只對var命令聲明的變量有效,如果一個變量不是用var命令聲明的,就不會發生變量提升。 console.log(aa); aa =1; 以上代碼將會報錯:ReferenceError: aa is not defined。
3)
var t = 1; function a(){ console.log(t); t=2; } a();//1
4)
函數聲明變量提升 foo(); function foo(){ console.log("aaa"); } //輸出aaa 原因:函數聲明提升 (函數聲明提升直接把整個函數提到執行環境的最頂端) 它相當于 function foo(){ console.log("aaa"); } foo();
5)
foo(); var foo = function(){ console.log("aaa"); } 它相當于: var foo; foo(); //foo is not a function foo = function(){ console.log("aaa"); } 上面代碼輸出undefined 是因為變量提升后并沒有賦值因此輸出undefined 輸出foo is not a function 原因是:js解析遇到 foo()時會默認當做函數來解析
6)最厲害的一個
console.log(foo); var foo=10; console.log(foo); function foo(){ console.log(10); } console.log(foo); 他相當于: function foo(){ console.log(10); } var foo; console.log(foo); foo=10; console.log(foo); console.log(foo);
函數提升在變量提升上面,第一個console.log(foo);為什么會輸出函數題呢,原因在于 var foo; 并未有賦值只是聲明,因此他會調用上面的值.
this指向全局環境中,this指向window console.log(this.document === document); // true // 在瀏覽器中,全局對象為 window 對象: console.log(this === window); // true this.a = 37; console.log(window.a); // 37
函數調用
非嚴格模式下,this 默認指向全局對象window
function f1(){ return this f1() === window; // true 而嚴格模式下, this為undefined function f2(){ "use strict"; // 這里是嚴格模式 return this; } f2() === undefined; // true
1)
對象中的this var o = { user:"李鋼鐵", fn:function(){ console.log(this.user); //李鋼鐵 } } o.fn();
這里的this指向的是對象o,因為你調用這個fn是通過o.fn()執行的,那自然指向就是對象o,這里再次強調一點,this的指向在函數創建的時候是決定不了的,在調用的時候才能決定,誰調用的就指向誰,一定要搞清楚這個。
2).
var o = { user:"李鋼鐵", fn:function(){ console.log(this.user); //李鋼鐵 } } window.o.fn(); this指向o
3).
var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //12 } } } o.b.fn();
總結:如果一個函數中有this,這個函數有被上一級的對象所調用,那么this指向的就是上一級的對象。
4).
var o = { a:10, b:{ // a:12, fn:function(){ console.log(this.a); //undefined } } } o.b.fn(); this指向b,因為this只會指向它的上一級對象,不管這個對象中有沒有this要的東西。
5).
特殊情況 var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //undefined console.log(this); //window } } } var j = o.b.fn; j(); 這里this指向的是window,,this永遠指向的是最后調用它的對象,也就是看它執行的時候是誰調用的,例子4中雖然函數fn是被對象b所引用,但是在將fn賦值給變量j的時候并沒有執行所以最終指向的是window。
4.
構造函數中this function Fn(){ this.user = "李鋼鐵"; } var a = new Fn(); console.log(a.user); //李鋼鐵 指向實例化對象a
當this遇到return時,如果返回值是一個對象,那么this指向的就是那個返回的對象,如果返回值不是一個對象那么this還是指向函數的實例。
function fn() { this.user = "李鋼鐵"; return undefined; } var a = new fn; console.log(a); //fn {user: "李鋼鐵"} function fn() { this.user = "李鋼鐵"; return 1; } var a = new fn; console.log(a.user); //李鋼鐵 特殊情況:雖然null也是對象,但是在這里this還是指向那個函數的實例,因為null比較特殊。 function fn() { this.user = "李鋼鐵"; return null; } var a = new fn; console.log(a.user); //李鋼鐵
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98201.html
摘要:變量作用域一個變量的作用域表示這個變量存在的上下文。在這種情況下,僅僅函數聲明的函數體被提升到頂部。雖然我們無需用來修飾形式參數,但是形式參數的確也是變量,并且被自動提升到次高的優先級函數聲明。 關于作用域,變量提升,函數提升的個人理解 參考: 阮一峰的JavaScript參考教程2.7函數部分 思否上一篇關于作用域,提升的博客 一篇關于作用域和提升的個人博客 MockingBird...
摘要:要達到想要的效果正確的做法是即用來產生一個立即作用域,保證回調函數執行的時候最近的原型作用域的就是當時循環的。判斷數組中是否存在滿足條件的項,只要有一項滿足條件,就會返回。 之前常常因為不注意,習慣用寫PHP或者Java的方式來寫nodejs,產生了了一些錯誤,這里總結一些小小的trick,以便于展示nodejs的不同,和平時需要注意的地方。 變量提升 var variable = g...
摘要:前言最近在學前幾天看到兩道題剛開始看懵懵懂懂這幾天通過各種查資料慢慢的理解頓悟了對匿名函數閉包立即執行函數的理解也更深了一點在此分享給大家我的理解與總結希望能幫助大家理解因為這篇文章是我用心總結的查閱了很多的資料所以總結的比較細篇幅較長如果 前言 最近在學JS,前幾天看到兩道題,剛開始看懵懵懂懂,這幾天通過各種查資料,慢慢的理解,頓悟了,對匿名函數,閉包,立即執行函數的理解也更深了一點...
摘要:局部變量在函數中聲明的變量,函數的參數作用域是局部性的,在函數體外,或者說的當前作用域的上層是無法直接讀取的。執行結果這樣我們就在外層取得了函數內部局部變量的也就是閉包實現從外部讀取局部變量的能力。 淺談作用域 ??當我們新建一個可以儲存變量的值,怎么才能讀取到這個變量呢?能訪問到這個變量,就說明符合作用域規則,作用域規則就可以說是js引擎讀取變量的規則。??在js中變量分為兩種,全局...
閱讀 2078·2021-11-23 10:13
閱讀 2788·2021-11-09 09:47
閱讀 2737·2021-09-22 15:08
閱讀 3312·2021-09-03 10:46
閱讀 2230·2019-08-30 15:54
閱讀 909·2019-08-28 18:09
閱讀 2429·2019-08-26 18:26
閱讀 2341·2019-08-26 13:48