js原始數據類型和引用數據類型=>callback數據傳輸原理


摘要:js的數據類型有種划分方式為 原始數據類型和 引用數據類型。

原始數據類型 存儲在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置。棧區包括了 變量的標識符和變量的值。

 引用數據類型 存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存處。放在棧空間中的值是該對象存儲在堆中的地址。

存儲在堆和棧中的原始值和引用值

按值傳遞 VS. 按引用傳遞

按值傳遞(call by value)是最常用的求值策略:函數的形參是被調用時所傳實參的副本。修改形參的值並不會影響實參。

按引用傳遞(call by reference)時,函數的形參接收實參的隱式引用,而不再是副本。這意味着函數形參的值如果被修改,實參也會被修改。同時兩者指向相同的值。

按引用傳遞會使函數調用的追蹤更加困難,有時也會引起一些微妙的BUG。

按值傳遞由於每次都需要克隆副本,對一些復雜類型,性能較低。兩種傳值方式都有各自的問題。

demo實例

typeof 運算符,返回一個字符串,指示未計算的操作數的類型

    var person,name;
    person = 'kn';

    name=person;
    person='黑白';
    console.log(person,name,typeof person)//黑白 kn string

person的改變沒有改變name,說明 string 是按值傳遞的。賦值時創建一塊新的內存空間

1、基本類型

  • Boolean.  布爾值,true 和 false.
  • null. 一個表明 null 值的特殊關鍵字。 JavaScript 是大小寫敏感的,因此 null 與 NullNULL或其他變量完全不同。
  • undefined.  變量未定義時的屬性。
  • Number.  表示數字,例如: 42 或者 3.14159。
  • String.  表示字符串,例如:"Howdy"
  • Symbol ( 在 ECMAScript 6 中新添加的類型).。一種數據類型,它的實例是唯一且不可改變的。

不可變(immutable)性質

基本類型是不可變的(immutable),只有對象是可變的(mutable). 有時我們會嘗試“改變”字符串的內容,但在JS中,任何看似對string值的”修改”操作,實際都是創建新的string值。任何方法都無法改變一個基本類型的值,  

1     var str = "abc";
2     str[0]; // "a"
3     str[0] = "d";
4     console.log(str); //abc
5 
6     var name = 'jozo';
7     var upName=name.toUpperCase(); 
8     console.log(upName,name); // 輸出 'JOZO' 'jozo'

方法操作無法改變一個基本類型的值

1     var person = 'kn';
2     person.age = 24;
3     person.method = function(){};
4 
5     console.log(person.age); // undefined
6     console.log(person.method); // undefined

上面代碼可知,我們不能給基本類型添加屬性和方法

 

2.引用類型

引用類型的值是可變的

 
        
1     var obj = {x : 0};
2     obj.x = 100;
3     var o = obj;
4     o.x = 1;
5     console.log(obj.x)// 1, 被修改
6     o = {x:100};  //等同於重新賦值,重新開辟內存,不是修改
7     console.log(JSON.stringify(obj),JSON.stringify(o))//{"x":1} {"x":100}
8     obj.x; // 1, 不會因o = {"x":100}改變
 
        

引用類型的值是同時保存在棧內存和堆內存中的對象

javascript和其他語言不同,其不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間,那我們操作啥呢? 實際上,是操作對象的引用,
所以引用類型的值是按引用訪問的。
准確地說,引用類型的存儲需要內存的棧區和堆區(堆區是指內存里的堆內存)共同完成,棧區內存保存變量標識符和指向堆內存中該對象的指針,
也可以說是該對象在堆內存的地址。
假如有以下幾個對象:

var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};

則這三個對象的在內存中保存的情況如下圖:

 

    var person1 = {};
    var person2 = {};
    console.log(person1 == person2); // false

引用類型時按引用訪問的,換句話說就是比較兩個對象的堆內存中的地址是否相同,那很明顯,person1和person2在堆內存中地址是不同的。

 

兩種數據類型在實參和形參中的區別

首先要明白什么實參什么是形參。

實參:可以是常量、變量、表達式、函數等, 無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應預先用賦值,輸入等辦法使實參獲得確定值。
形參:全稱為“形式參數”是在定義函數名和函數體的時候使用的參數,目的是用來接收調用該函數時傳遞的參數。
形參的作用是實現主調函數與被調函數之間的聯系,通常將函數所處理的數據,影響函數功能的因素或者函數處理的結果作為形參。
function addNum(param)  //相對於addNum方法來說 param是形參
{ 
    param+=10; 
     return param; 
} 
var num=10;  
var result=addNum(num); //相對於addNum方法來說 num是實參
console.log(num);  //10  
console.log(result);//20

上面的例子中,當將 num作為實參傳入方法 addNum是 param作為形參接受 並在方法體內使用,且num在全局中沒用改變,但當實參為引用類型時

1 function fun(param)  //相對於fun方法來說 param是形參
2 { 
3     param[0]=99; 
4      return param; 
5 } 
6 var num=[10];  
7 var result=fun(num); //相對於fun方法來說 num是實參
8 console.log(num[0]);  //99 
9 console.log(result);//[99]

在方法體內改變 形參將同時改變實參。這個是其他語言中不會存在的,例如php,需要操作引用時,使用 &地址符 在形參的時候聲明

 1 <?php
 2 function fun($param)  //相對於fun方法來說 param是形參   function fun(&$param){}
 3 { 
 4     $param[0]=99; 
 5       // return $;
 6 } 
 7 $num=[10];  
 8 fun($num); //相對於fun方法來說 num是實參
 9 var_dump($num);
10 /*
11 array (size=1)
12   0 => int 10
13   */
14 
15 ?>

 思考: 正因為js中 function的形參若為引用類型時,可以影響實參! 推斷 callback中參數原理

 1     function fun(data,callback){
 2         var json=[1,2,3];
 3         callback(json)
 4     }
 5 
 6     var data=[];
 7     fun(data,function(result){
 8         data=result;
 9     })
10     console.log(data)//[1, 2, 3]

如上例子 在回調函數中修改了 變量 data

知識點1、 function 是一種數據類型,可以當做參數傳遞 2、數組是引用類型 3、引用類型的形參會影響實參

 1 <body>
 2     <button onclick='log()'>ajax</button>
 3 </body>
 4 <script>
 5     function fun(data,callback){
 6         setTimeout(function(){
 7             var json=[1,2,3];
 8             callback(json)
 9         },4000)
10     
11     }
12 
13     var data=[];
14     fun(data,function(res){
15         data=res;
16     })
17     console.log(data)//[]
18     function log(){
19         console.log(data)//[1, 2, 3]  4秒后輸出 
20     }
21 
22 </script>

使用 setTimeout 模擬ajax請求! 

 

 

 

 

 

參考地址: http://www.w3school.com.cn/js/pro_js_value.asp 

http://www.qdfuns.com/notes/17660/7f82003c5ce92d39d19d6be0403f3f3b.html

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM