1、理解基本類型和引用類型的值javascript
ECMAScript變量包含兩種不一樣數據類型的值:基本類型值 和 引用類型值。html
基本類型值指的是簡單的數據段,而引用類型的值指那些可能由多個值構成的對象 前端
引用類型的值是保存在內存中的對象,javascript不容許直接訪問內存中的位置,也就是不能直接操做對象的內存空間。在操做對象時,其實是在操做對象的引用而不是實際的對象。引用類型的值是按引用訪問的,基本類型是按值訪問的,由於能夠操做保存在變量中的實際的值。java
動態的屬性web
定義基本類型值和引用類型值的方式是相似的:建立一個變量併爲該變量賦值。但對保存到變量的不一樣類型值的操做是不同的。對於引用類型的值,能夠添加,改變和刪除其屬性和方法,可是,不能給基本類型的值添加屬性等操做。瀏覽器
var person = new Object(); //引用類型值 person.name = "小明"; alert(person.name); //小明 var name = "小明"; //基本類型值 name.age = 25; alert(name.age); //undefined
複製變量值函數
若是從一個變量向另外一個變量複製基本類型的值,會在變量對象上建立一個新值,而後把該值複製到新變量分配的位置上。spa
var num1 = 2; var num2 = num1;
num2的值會是2,這個值只是num1的值的一個副本,與num1的值2是徹底獨立的,這兩個變量能夠參與任何操做而不會相互影響。
指針
當從一個變量向一個變量複製引用類型的值,一樣也會將存儲在變量對象中的值複製一份放到爲新變量分配的空間中,但這個值的副本實際是個指針,而這個指針指向存在堆中的一個對象。也就是說,兩個值實際上引用的是同一個對象。所以,改變其中一個變量,另外一個變量也會受到影響。code
var obj1 = new Object(); obj1.name= "one"; var obj2 = obj1; alert(obj2.name); // one obj2.name = "two"; alert(obj1.name); //two //改變了obj2.name,obj1.name也被改變
傳遞參數
把函數外部的值複製給函數內部的參數,就像把值從一個變量複製到另外一個變量。訪問變量有按值和按引用兩種方式,而參數只能按值傳遞。
在向參數傳遞基本類型的值時,被傳遞的值會被複制給一個局部變量(命名參數)。
在向參數傳遞引用類型的值時,會把這的值在內存中的地址複製給一個局部變量,這個局部變量發生變化會反映在函數的外部。
function add(num){ num += 10; return num; } var count = 20; var result = add(count); alert(count); //20 alert(result); //30
誤區:在局部做用中修改的對象會在全局做用域中反映出來,就說明參數是按引用傳遞的 (X)
function setName(obj){ obj.name = "Tom"; obj = new Object(); //從新定義對象 obj.name = "Jim"; //定義不一樣值的name屬性 } var person = new Object(); setName(person); alert(person.name); // Tom //即便函數內部修改了參數的值,原始引用仍然保持不變
若是person是按引用傳遞的,那麼person就會自動被修改爲爲指向name屬性爲」Jim「的新對象,可是,在外部訪問person.name時,值仍然是」Tom「
檢測類型
檢測一個變量是否是基本數據類型用 typeof 操做符,typeof操做符肯定一個變量是字符串/數值/布爾值/undefined ,
若是變量值是一個對象或null,則返回「object」
instanceof操做符檢測是個什麼類型的對象,若是變量是給定引用類型對象,instanceof操做符就會返回true
A instanceof Object; B instanceof Array; C instanceof RegExp; ……
在檢測一個引用類型值和Object構造函數時,instanceof操做符始終會返回true,固然,若是使用instanceof操做符檢測基本類型的值,則該操做符始終會返回false,由於基本類型不是對象 。
2、理解執行環境及做用域
執行環境定義了變量或函數有權訪問的其餘數據,決定了他們各自的行爲。
每一個執行環境都有一個與之關聯的變量對象,環境中定義的全部變量和函數都保存在這個對象中。
全局執行環境是最外圍的一個執行環境。在web瀏覽器中,全局執行環境被認爲是window對象,所以全部全局變量和函數都是做爲window對象的屬性和方法建立的,全局執行環境直到應用程序退出時纔會被銷燬。
當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈。做用域鏈的用途,是保證 對執行環境有權訪問的 全部變量和函數 的有序訪問。
var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColor(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; //這裏能夠訪問color、anotherColor、temperColor } //這裏能夠訪問color、anotherColor swapColor(); } //這裏只能訪問color changeColor();
以上代碼涉及3個執行環境:全局環境,changeColor()的局部環境和swapColor()的局部環境。內部環境能夠經過做用域鏈訪問全部的外部環境,但外部環境不能訪問內部環境的任何變量和函數。這些環境之間是有次序的,每一個環境都能夠向上搜索做用域鏈,以查詢變量和函數名,但任何環境都不能經過向下搜索做用域鏈而進入另外一個執行環境。
延長做用域鏈
當執行流進入下列任何一個語句時,做用域鏈就會獲得加長:
◇ try-catch 語句的 catch 塊
◇ with 語句
這兩個語句都會在做用域鏈的前端添加一個變量對象,對with語句來講,會將指定的對象添加到做用域鏈中。對catch語句來講,會建立一個新的變量對象,其中包含的是被拋出的錯誤對象的聲明。
javascript沒有塊級做用域
◇聲明變量
function add(num1,num2){ var sum = num1 +num2; //局部變量 return sum; } var result = add(10,20); alert(result); //30 alert(sum); //訪問錯誤
雖然結果值從函數返回,但變量sum是局部變量,函數外部是訪問不到的。若不用 var聲明,那麼sum自動加入全局環境,這樣一來外部能夠訪問。
◇查詢標識符
查詢與給定名字的標識符,若是在局部環境中找到了該標識符,搜索過程中止,若是在局部環境中沒有找到,則沿做用域向上搜索。直到找到爲止。
var color = "blue"; function getColor(){ var color = "red"; return color; } alert(getColor()); //red