假如你沒去過天安門、故宮、長城相當於你沒到過北京。假如你搞不懂JS變數的作用域,相當於你沒學過JS。關於JS變數作用域的重要性自己好好悟吧!提示:看這篇文章記得看註解!
JS是一門弱型(鬆散型)的語言,這也就是說其天生就與眾不同,獨領風騷!
在講解變數作用域之前,我們先來了解JS中的變數。 JS中的變數與其它語言有很大的不同,由於JS變數擁有鬆散(不強制)的本質,從而決定了其只是一個在特定階段保持特定類型值的名字。
基本資料型別的值會保存在堆疊記憶體中。而引用資料型別的值則保存在堆疊記憶體中,在堆疊記憶體中只保留引用型別的指標位址。
基本型別值有以下五種:undefined,Null,Boolean,Number和String。基本資料型別的值保存在堆疊記憶體中。
//在栈内存中开辟一块空间存储值为"laotie"的变量namevar name="laotie";//在栈内存中开辟一块空间存储值为"laotie"的变量name2var name2=name;//name与name2是相对独立的,所以改变name2的值为"xiaozhang",而name的值不会受到影响var name2="xiaozhang"; console.log(name);//laotieconsole.log(name2);//xiaozhang
再來看一下引用類型:
/*在栈内存中存放 obj的地址 * 其值存放在堆内存中。 * 栈内存的地址的指向堆内存中的值。*/var obj={ name:"zhangpeiyue"}/*将obj的地址赋值给obj2 所以在栈内存中存储的地址与obj的地址相同, obj与obj2共享同一个值。 */var obj2=obj; obj2.name="xiaozhang";//因为obj与obj2共享同一个值,所以上行代码改变的是同一个值console.log(obj.name);//xiaozhang //你也可以认为obj即为obj2,引用类型比较的是地址,因此为trueconsole.log(obj==obj2);//true
基本資料型別的比較,比較的是值:
//基本数据类型比较的是值,只要值相等比较结果即为truevar a=1;var b=1;console.log(a==b);//truevar c=2;var d=c;console.log(c==d);//true
引用類型的比較,比較的是位址:
var obj={ age:12}var obj2={ age:12}//引用类型比较的是地址,而不是值。//由于每次创建的引用类型地址都不同,所以结果为falseconsole.log(obj==obj2);//falsevar obj3={ age:12}//将obj3的地址赋值给obj4。所以地址相同var obj4=obj3;//由于比较的是地址,且obj3与obj4的地址相同,所以结果为trueconsole.log(obj3==obj4);再來來看看關於基本型別與引用型別作為函數中的參數問題
/*接收的所有基本数据类型,接收的是其值。 接收的参数都是函数体中的局部变量。 在函数体内改变值,对外部不会产生任何影响*/function fn(a){ a+=1; console.log(a);//14} var a=13;fn(a); console.log(a);//13
/*引用数据类型传递的是引用地址, 因此函数体中的obj与函数外的obj的引用地址相同。 所以函数体中的obj与函数外的obj共享同一值, 改变其中一个值,其它的也会随之改变 */function fn(obj){ obj.name="laowang" console.log(obj.name);//laowang} var obj={ name:"laotie"}fn(obj); console.log(obj.name);//laowang終於聊到作用域啦! JS變數作用域,就是指變數所影響的範圍。 JS中作用域分為全域作用域與局部作用域(函數作用域)。在全域作用域內定義的變數為全域變量,在局部作用域內定義的變數為局部變數。 全域作用域是最外圍定義的作用域,在web瀏覽器中全域作用域指的是window物件。因此在全域作用域定義的變數和函數,你可以認為是window物件的屬性與方法!
var color="red";//定义一个全局colorfunction fn(){ color="blue";//全局函数可以在函数内访问}fn(); console.log(color);//blue
var color="red";//定义一个全局colorfunction fn(){ color="blue";//全局函数可以在函数内访问}window.fn(); console.log(window.color);//blue
var color="yellow";//定义全局变量colorfunction fn(){ //在函数体内如果拥有指定的变量,就不会去外层查找 var color="red";//这里是局部变量color,外面是访问不到的哦 console.log(color);//red}fn(); console.log(color);//yellow
var color="green";function fn(){ //子函数是建议以下划线开头 function _fn2(){ var color2="orange"; console.log(color);//green console.log(color2);//orange } _fn2();//_fn2()的作用域在fn()内} fn(); _fn2();//在此处调用fn2()是调取不到的注意:當在一個作用域內執行程式碼時,就會有一個被稱為作用域鏈的東西。它的作用是保證變數與方法存取的有序性。也就是目前執行環境中存在指定的變數或方法就不會去外圍查找,如果沒有則會向外圍查找,直到找到為止!如果找不到會報錯!一層層向外尋找指定變數和方法的行為,形成了一個作鏈條。這個鏈條就是作用域鏈。存取局部變數要比全域變數快許多,因為不需要向外圍查找(向上查找)指定的變數。
* JS沒有區塊級作用域,所謂區塊級作用域指的是if,for等語句用花括號包裹的程式碼!
if(true){ var name="zhang"; } console.log(name);//zhang當你在函數中宣告一個沒有帶var關鍵字的變數時,這個變數就會成為全域變數。不過這種行為很容易造成命名衝突,所以非常不推薦大家使用!
function fn(){ //此处a=12相当于window.a=12。 a=12;//声明一个不带var关键字的变量}fn(); console.log(a);//12這是因為fn函數是在window環境下運行的,由此函數體內的a=12相當於執行了window.a=12。而window是JS的頂級對象。也可以認為我們為頂級物件增加了值為12的a屬性。所以變數a就成為了全域變數。
另外如果函數體內的變數是透過var關鍵字聲明的,則該變數為局部變量,只能在該函數體內進行訪問,函數體外是無法存取的。
function fn(){ var a=12; console.log(a);//12}fn(); console.log(a);//报错:a is not defined
var obj = { b: 2};var fn = function () {}; fn.c = 3;function test(x, y, z) { x = 4; y.b = 5; z.c = 6; return z; } test(a, obj, fn); console.log(a + obj.b + fn.c);//12
所谓变量的生命周期指的是变量由声明到销毁。
对于全局变量来讲,其生命周期是永久的,除非我们主动去销毁这个全局变量。而在函数体内声明的局部变量,当函数运行完以后,局部变量就失去了任何价值,它们也会随着函数的执行完毕而销毁。
var fn=function(){ var a=1;//退出函数后,局部变量a会销毁 console.log(a); }fn();
JS环境中分配的内存一般有如下生命周期
内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
内存使用:即读写内存,也就是使用变量、函数等
内存回收:使用完毕,由垃圾回收自动回收不再使用的内存
本文讲解了JavaScript的变量及作用域,更多相关内容请关注php中文网。
相关推荐:
以上是詳解JavaScript的變數及作用域的詳細內容。更多資訊請關注PHP中文網其他相關文章!