首頁 >web前端 >js教程 >詳解JavaScript的變數及作用域

詳解JavaScript的變數及作用域

jacklove
jacklove原創
2018-06-11 17:47:491772瀏覽

假如你沒去過天安門、故宮、長城相當於你沒到過北京。假如你搞不懂JS變數的作用域,相當於你沒學過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

  • 全域的變數和函數,都是window物件的屬性和方法。

  • 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中文网。

  • 相关推荐:

  • 关于$.ajax()方法参数详解

  • 讲解数学对象Math相关内容

  • 关于JS和JSP的区别讲解

以上是詳解JavaScript的變數及作用域的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn